Asked  7 Months ago    Answers:  5   Viewed   35 times

If I try something such as:

int anint;
char achar;

printf("nEnter any integer:");
scanf("%d", &anint);
printf("nEnter any character:");
scanf("%c", &achar);
printf("nHellon");
printf("nThe integer entered is %dn", anint);
printf("nThe char entered is %cn", achar);

It allows entering an integer, then skips the second scanf completely, this is really strange, as when I swap the two (the char scanf first), it works fine. What on earth could be wrong?

 Answers

27

When reading input using scanf, the input is read after the return key is pressed but the newline generated by the return key is not consumed by scanf, which means the next time you read a char from standard input there will be a newline ready to be read.

One way to avoid is to use fgets to read the input as a string and then extract what you want using sscanf as:

char line[MAX];

printf("nEnter any integer:");
if( fgets(line,MAX,stdin) && sscanf(line,"%d", &anint)!=1 ) 
   anint=0;

printf("nEnter any character:");
if( fgets(line,MAX,stdin) && sscanf(line,"%c", &achar)!=1 ) 
   achar=0;

Another way to consume the newline would be to scanf("%c%*c",&anint);. The %*c will read the newline from the buffer and discard it.

You might want to read this:

C FAQ : Why does everyone say not to use scanf?

Tuesday, June 1, 2021
 
superhero
answered 7 Months ago
11

%f is looking for a float, not a double. If you want to use a double, use the format %lf.

As a somewhat interesting aside, clang warns about this without any extra flags, gcc 4.6 won't warn about it even with -Wall -Wextra -pedantic.

Tuesday, July 6, 2021
 
TMichel
answered 5 Months ago
52

If you want to use the intent with a BroadcastReceiver, you should use PendingIntent.getBroadcast instead of PendingIntent.getService. You might also need to setup an appropriate intent filter.

Tuesday, August 3, 2021
 
Adam
answered 4 Months ago
56

If do you have already permissions then:

In your service class or another service/activity you can switch the "component hability" to listen notifications:

    public void tryReconnectService() {
        toggleNotificationListenerService();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            ComponentName componentName =
                    new ComponentName(getApplicationContext(), NotificationReaderV2Service.class);

            //It say to Notification Manager RE-BIND your service to listen notifications again inmediatelly!
            requestRebind(componentName);
        }
    }

/**
* Try deactivate/activate your component service
*/
    private void toggleNotificationListenerService() {
        PackageManager pm = getPackageManager();
        pm.setComponentEnabledSetting(new ComponentName(this, NotificationReaderV2Service.class),
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
        pm.setComponentEnabledSetting(new ComponentName(this, NotificationReaderV2Service.class),
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    }

Your notification listener, is a SERVICE, it can be killed by System, you can do your service as FOREGROUND to drastically decrease the probability that the system will kill your service.

@Override
    public void onListenerConnected() {
        super.onListenerConnected();
        Log.d(TAG, "Service Reader Connected");
    Notification not = createNotification();
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (mNotificationManager != null) {
        mNotificationManager.notify(NOTIFICATION_ID, not);
    }

    startForeground(NOTIFICATION_ID, not);

    //Alarm to auto - send Intents to Service to reconnect, you can ommit next line.
    alarmIt();
}

If do you like so more "safe", you can to programming not-friendly battery alarms, try to use inexact alarms please, the user's battery will be happy:

private void alarmIt() {
    Log.d(TAG, "ALARM PROGRAMMATED at"+HotUtils.formatDate(new Date()));
    Calendar now = Calendar.getInstance();
    now.setTimeInMillis(System.currentTimeMillis());
    now.set(Calendar.MINUTE, now.get(Calendar.MINUTE) + 1);

    Intent intent = new Intent(this, NotificationReaderV2Service.class);
    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
    intent.setAction(REBIND_ACTION);

    PendingIntent pendingIntent = PendingIntent.getService(this, 0,
            intent, 0);

    AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    //The alarms that are repeated are inaccurate by default, use RTC_WAKE_UP at your convenience.
    //Alarm will fire every minute, CHANGE THIS iF DO YOU CAN, you can't use less than 1 minute to repeating alarms.
    manager.setRepeating(AlarmManager.RTC_WAKEUP, now.getTimeInMillis(), 1000 * 60 * 1, pendingIntent);
}

and next read the Intent to reconnect service binding:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "Notification service onStartCommandCalled");
    if (intent!=null && !HotUtils.isNullOrEmpty(intent.getAction()) && intent.getAction().equals(REBIND_ACTION)){
        Log.d(TAG, "TRYING REBIND SERVICE at "+HotUtils.formatDate(new Date()));
        tryReconnectService();//switch on/off component and rebind
    }
    //START_STICKY  to order the system to restart your service as soon as possible when it was killed.
    return START_STICKY;
}

Keep in mind that doing all these steps you can sure that your service will be killed anyway by the system but this code will restart the service and make it harder to kill it.

Maybe, you should consider using PARTIAL_WAKE_LOCK with your service and execute it in a process independently (:remote) if you want even more certainty (Maybe this is useless)

I would like to add a common error that is often followed, NEVER override the onBind and onUnbind method or overwrite the INTENT ACTION. This will cause your service to not be connected and never run onListenerConnected Keep the Intent as it is, in most cases you do not need to edit it.

Wednesday, August 4, 2021
 
stbamb
answered 4 Months ago
21

The following should do what you need for the first case.

#define MAX_STRING_LENGTH 20
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x

{
  ...
  char word[MAX_STRING_LENGTH+1];     
  scanf(file, "%" STRINGIFY(MAX_STRING_LENGTH) "s", word);
  ...
}

NOTE: Two macros are required because if you tried to use something like STRINGIFY2 directly you would just get the string "MAX_STRING_LENGTH" instead of its value.

For the second case you could use something like snprintf, and at least some versions of C will only let you allocate dynamically sized arrays in the heap with malloc() or some such.

Friday, August 13, 2021
 
OMGKurtNilsen
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share