Проблема с корректной работой sscanf с определенными входами - PullRequest
0 голосов
/ 18 мая 2018

Я пытаюсь прочитать значения в этих строках в переменных с помощью sscanf, и я получаю очень странные результаты.Он работает с некоторыми строками, пока я использую числа с плавающей точкой, но с другими подобными строками с плавающей точкой это не работает, и если я использую двойные числа вместо числа с плавающей точкой, он никогда не будет работать должным образом.

#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);
}

Этовывод, который я получаю на своей машине:

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

Результат: 2

1972-3-1,0.000000,0,000000, Словакия

Результат: 6

1943-0-0,0,000000,0,000000,

Результат: 2

1972-3-1,4,787000, 0.342000, Словакия

Результат: 6

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

«% i» отличается от «% d» при сканировании

"1943-09-01,29.27,0.403,Yemen"; не удается, поскольку "09" не сканируется в int как 9 с "%i".

В приведенном ниже коде при сканировании на month, sscanf(), используя "%i", обнаруживается "09".Поскольку он ведет с '0', это переводит интерпретацию на восьмеричное .Поскольку '9' не является восьмеричной цифрой, month присваивается 0, и сканирование продолжается с " - %i, %lf , %lf , %s".Так как '9' не совпадает с '-', сканирование останавливается и сообщает о 2 успешных конверсиях.

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

Предлагаемая альтернатива

Используйте "%d" вместо "%i" для обеспечениядесятичная интерпретация.

Используйте ограничения ширины при сохранении строки .

Используйте "%n", чтобы обнаружить конец сканирования и найти лишний мусор.

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);
  }
}

Обратите внимание, что %s не будет полностью читать названия стран, такие как "Sri Lanka", а только первое "слово" "Sri".В зависимости от целей кодирования рассмотрим:

  int result = sscanf(line, "%d - %d - %d , %lf , %lf , %99[^\n] %n", 
0 голосов
/ 18 мая 2018

Попробуйте удалить пробел, используемый между элементами даты в sscanf.

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

Как указывал EugeneSh над своим целым числом со знаком, и чтение с плавающей точкой удваивается.

...