chilliefiber
chilliefiber

Reputation: 651

Trouble getting sscanf to work correctly with certain inputs

I'm trying to read the values in those lines to the variables with sscanf and I'm getting very weird results. It works with some lines as long as I use floats, but with other similar lines with floats it doesn't work, and if I use doubles instead of floats it never works properly.

#include <stdio.h>
#include <stdlib.h>

void debug(char* line,int* year, int* month, int* day, double* temp, double* uncertainty,
char country[100]){
    int result;
    result = sscanf(line, "%i - %i - %i, %lf , %lf , %s", year, 
    month, day, temp, uncertainty, country);
    printf("%i-%i-%i,%f,%f,%s\n",*year, *month, *day, *temp, 
    *uncertainty, country);
    printf("Result:%i\n", result);
}

void debug_f(char* line, int* year, int* month, int* day, float* temp, float* uncertainty,
char country[100]){
    int result;
    result = sscanf(line, "%i - %i - %i, %f , %f , %s", year, 
    month, day, temp, uncertainty, country);
    printf("%i-%i-%i,%lf,%lf,%s\n",*year, *month, *day, *temp, 
    *uncertainty, country);
    printf("Result:%i\n", result);
}

int main(){
    char* error = "1943-09-01,29.27,0.403,Yemen";
    char* working = "1972-03-01,4.787,0.342,Slovakia";
    int year1, year2, year3, year4;
    int month1, month2, month3, month4;
    int day1, day2, day3, day4;
    double temp1, temp2;
    double uncertainty1, uncertainty2;
    float temp3, temp4;
    float uncertainty3, uncertainty4;
    char country1[100], country2[100], country3[100], country4[100];
    debug(error, &year1, &month1, &day1, &temp1, &uncertainty1, country1);
    debug(working, &year2, &month2, &day2, &temp2, &uncertainty2, country2);
    debug_f(error, &year3, &month3, &day3, &temp3, &uncertainty3, country3);
    debug_f(working, &year4, &month4, &day4, &temp4, &uncertainty4, country4);
}

This is the output I get on my machine:

1943-0-0,0.000000,0.000000,�\��

Result:2

1972-3-1,0.000000,0.000000,Slovakia

Result:6

1943-0-0,0.000000,0.000000,

Result:2

1972-3-1,4.787000,0.342000,Slovakia

Result:6

Upvotes: 1

Views: 55

Answers (2)

chux
chux

Reputation: 153303

"%i" differs from "%d" when scanning

"1943-09-01,29.27,0.403,Yemen"; fails because "09" is not scanned into an int as 9 with "%i".

In the below code, when scanning for month, sscanf(), using "%i", encounters "09". Since it leads with a'0', that switches interpretation to octal. As '9' is not an octal digit, month is assigned 0 and scanning continues with " - %i, %lf , %lf , %s". Since '9' does not match '-', scanning stops and reports 2 successful conversions.

sscanf(line, "%i - %i - %i, %lf , %lf , %s", year,  month, day, temp, uncertainty, country);

Suggested alternative

Use "%d" instead of "%i" to insure decimal interpretation.

Use width limits when saving a string.

Use "%n" to detect end of scan and look for extra junk.

void debug(const char* line, int* year, int* month, int* day, 
    double* temp, double* uncertainty, char country[100]){
  int n = 0;
  int result = sscanf(line, "%d - %d - %d , %lf , %lf , %99s %n", 
      year, month, day, temp, uncertainty, country, &n);
  printf("Result:%i\n", result);

  if (n > 0 && line[n] == '\0') {
    printf("%i-%i-%i,%f,%f,%s\n",
        *year, *month, *day, *temp, *uncertainty, country);
  } else {
    printf("<%s> failed\n", line);
  }
}

Note that %s will not fully read country names like "Sri Lanka", but only the first "word" "Sri". Depending on coding goals, consider:

  int result = sscanf(line, "%d - %d - %d , %lf , %lf , %99[^\n] %n", 

Upvotes: 0

Vinay P
Vinay P

Reputation: 635

Try removing the space used in between date elements in sscanf.

sscanf(line, "%i-%i-%i, %f , %f , %s", 
               &int1, &int2,
               &int3, &double1, &double2,
               s);

As EugeneSh pointed above its signed integer, and reading float to a double.

Upvotes: 1

Related Questions