Не могу понять, почему мой оператор печати продолжает распечатываться дважды

#c

#c

Вопрос:

эй, ребята, итак, у меня есть этот код, с которым я работаю, и он делает все, что мне нужно, однако я не могу понять, почему мой printf печатается дважды для level . вот код.

 while(fgets(str_read, sizeof(str_read)-1 , fptr)!= NULL)
    sscanf(str_read, "%d ", amp;somearray->level);
    printf("level: %dn", somearray->level);
  

также, если есть что-то еще, над чем я мог бы поработать, я открыт для обратной связи. я работаю с файлом .txt, который имеет следующие настройки:

 int
name
int
name
int
name
  

Комментарии:

1. «вот код»? Я думаю, что нет, если только это каким-то образом не закодировано в точке в конце этого предложения 🙂

2. извините, у меня возникли проблемы. все еще новый, так что я все еще получаю свои морские ноги.

3. кроме того, если кто-нибудь хочет научить меня тому, как делать эти классные фрагменты кода с моими собственными комментариями, я тоже открыт для этого.

4. Райан, ты можешь либо поставить как минимум четыре пробела в начале каждой строки кода (и пустую строку до и после), либо окружить свой код тройными обратными метками. Для этого первого варианта вы можете пометить текст без отступов, а затем просто использовать CTRL-K.

5. Предполагается str_read , что это массив, sizeof(str_read)-1 просто должен быть sizeof(str_read) , нет -1 with fgets() , это гарантирует, что результирующая строка завершается нулем. Также printf("level: %dn", somearray->level); НЕ является частью вашего цикла. C — это не Python….

Ответ №1:

Вам нужно проверить возвращаемое значение из sscanf . В строках, которые не содержат целого числа, оно будет возвращено 0 . В этом случае somearray->level он не изменится, поэтому вы распечатаете его во второй раз.

Одним из возможных решений является:

 while(fgets(str_read, sizeof(str_read)-1 , fptr)!= NULL)
    if (sscanf(str_read, "%d ", amp;somearray->level) == 1)
        printf("level: %dn", somearray->level);
  

Это пытается sscanf выполнить для каждой строки, но выводит результат только в том случае, если было найдено значение.

Другим решением было бы отслеживать четные и нечетные строки и пытаться использовать только sscanf нечетные строки.

Комментарии:

1. Спасибо Тому за помощь. Ценю это

2. @Ryanv048 — ваши выводы здесь: (1) вы проверяете КАЖДЫЙ пользовательский ввод и (2) вы проверяете КАЖДОЕ преобразование. Вы делаете это, чтобы знать, что у вас есть допустимое значение, прежде чем продолжить использовать это значение в своем коде. Сбой проверки вызывает неопределенное поведение .

Ответ №2:

Во-первых, я собираюсь предположить, что ваш код имеет фигурные скобки вокруг него, поскольку в противном случае он будет печатать только один раз в конце (фигурные скобки управляют тем, что находится в теле цикла, а не отступом):

 while(fgets(str_read, sizeof(str_read)-1 , fptr)!= NULL) {
    sscanf(str_read, "%d ", amp;somearray->level);
    printf("level: %dn", somearray->level);
}
  

Это соответствует тому, что вы видите. Если ваш текстовый файл состоит из чередующихся целых чисел и нецелых имен, каждую секунду sscanf будет происходить сбой, потому что имя нельзя рассматривать как целое число. Поскольку вы не проверяете возвращаемое значение, вы просто слепо предполагаете, что преобразование сработало, и печатаете значение, которое было введено ранее somearray->level .

Вызовы scanf семейства функций обычно должны включать проверку, чтобы убедиться, что все было правильно отсканировано, что-то вроде:

 if (sscanf(str_read, "%d ", amp;somearray->level) != 1) {
    handleBadScan();
}
  

Комментарии:

1. Спасибо, Пакс, Это действительно приятно знать. Я буду работать над этой проверкой.

2. Привет, Пакс, вопрос к тебе. куда мне следует обратиться, чтобы узнать больше о возвращаемых значениях thing, как в этом примере 1. Я знаю, что 0 в return означает, что он выполняется просто отлично и без ошибок, и возвращает, как 1 и -1 возвращает ошибки. Они имеют ту же концепцию, что и в операторе if? Надеюсь, это имеет смысл. лол

3. Райан, я использую для этого стандарт C, но в основном это довольно сухое чтение, поэтому вы можете подумать о том, чтобы просто посмотреть справочные страницы, или cplusplus.com . Однако в качестве окончательного источника того, что делают функции, я предпочитаю стандарт.