Чтение целых чисел в файле смешанных типов, feof не работает

Я получаю ошибки в своей программе (которая должна найти все целые числа и файл символов и целых чисел), где «feof» не работает (пока цикл никогда не заканчивается) или целые числа не читаются/находятся, если весь файл не полный инт.

Мой код...

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

  int main(void)
  {
   FILE *ptr;
   int val;
   int i = 0;
   char myChar;
   int chc;
   int result = 0;

     ptr = fopen("stuff.txt", "w");

     if(ptr == NULL)
       {
        printf("Could not open file \n");
       }

    for(; i < 5; ++i)
       {
        printf(" Char(0) or int(1)? ");
        scanf("%d", &chc);

       if(chc == 0)
         {
          printf(" Enter a char: ");
          scanf(" %c", &myChar);

          fprintf(ptr, " %c \n", myChar);
         }
       else
         {
          printf(" Enter an int: ");
          scanf("%d", &val);

          fprintf(ptr, " %d \n", val);
         }
      }

     fclose(ptr);

 FILE *rp;

 rp = fopen("stuff.txt", "r");

 if(ptr == NULL)
   {
    printf("Could not open file \n");
   }
 else
   {

    while(!feof(rp))
         {
           if(isdigit(fgetc(rp)))
             {
              ++result;
             }
          }
   }

  printf(" Total numbers in file: %d\n", result);


 return 0;
}

Редактировать:

Я забыл повторно добавить «результат int», и это новая ошибка. Вероятно, это связано с fgetc, как кто-то упомянул. Я получаю дополнительную единицу, добавленную к моей общей сумме.

Решено: я читаю 34 как "3" и "4", так что это считается за два. Не уверен, как пометить как решенный или удалить это.

 Char(0) or int(1)? 0

 Enter a char: e

 Char(0) or int(1)? 1

 Enter an int: 34

 Char(0) or int(1)? 0

 Enter a char: p

 Char(0) or int(1)? 0

 Enter a char: d

 Char(0) or int(1)? 0

 Enter a char: u

 Total numbers in file: 2

person Community    schedule 20.05.2017    source источник
comment
stackoverflow.com/q/5431941/7761980   -  person ThingyWotsit    schedule 21.05.2017
comment
См. while (!feof(file)) всегда неправильно. Этот код является своего рода исключением; когда fgetc() возвращает EOF, последующее feof(rp) будет точным, и вы не ошибетесь, считая EOF цифрой.   -  person Jonathan Leffler    schedule 21.05.2017
comment
Не воспроизводить. Петля заканчивается.   -  person BLUEPIXY    schedule 21.05.2017
comment
@JonathanLeffler fgetc, должно быть, поэтому я добавляю лишнюю единицу к моей сумме? Я видел вопрос, который вы указали. Я попробовал if(fscanf(rp, %d, &v) == 1) и он либо зависает, либо не завершает цикл.   -  person    schedule 21.05.2017
comment
'3' и '4' Итак, 2.   -  person BLUEPIXY    schedule 21.05.2017
comment
34 использует две цифры, поэтому счет должен быть равен 2. Использование scanf() для чтения целых чисел, когда во входных данных есть буквы, не будет работать хорошо.   -  person Jonathan Leffler    schedule 21.05.2017
comment
@BLUEPIXY Я добавил недавний запуск, в котором я ввожу только одно число, и оно считается как два числа. Может быть, fgetc и feof не лучшая комбинация?   -  person    schedule 21.05.2017
comment
fgetc читать один символ, а не один int.   -  person BLUEPIXY    schedule 21.05.2017
comment
Это две цифры, составляющие 34. Вы вводите два символа, чтобы ввести его; fgetc() возвращает две отдельные цифры — сначала '3', а затем '4'.   -  person Jonathan Leffler    schedule 21.05.2017
comment
@JonathanLeffler Теперь понятно, спасибо!   -  person    schedule 21.05.2017
comment
@BLUEPIXY Теперь я понимаю, что вы имеете в виду, спасибо!   -  person    schedule 21.05.2017
comment
при вызове любой из функций семейства scanf() всегда проверяйте возвращаемое значение (а не значения параметров), чтобы убедиться, что операция прошла успешно.   -  person user3629249    schedule 22.05.2017
comment
относительно блока кода, начинающегося с: if(ptr == NULL) 1) всегда размещайте литерал слева, чтобы ошибка нажатия клавиш, например: if(ptr = NULL), не испортила вам день. 2) сообщения об ошибках должны выводиться на stderr, а не на stdout, поэтому используйте perror(), а не printf(). Примечание: perror() также выводит причину, по которой система считает, что произошла ошибка. 3) нет открытого файла, поэтому НЕ продолжайте выполнение программы, а вызовите `exit(EXIT_FAILURE);   -  person user3629249    schedule 22.05.2017
comment
что происходит, когда пользователю предлагается: printf(" Char(0) or int(1)? "); и пользователь вводит: 3 или a или '\n'? т.е. НИКОГДА не доверяйте пользователю делать правильные вещи, всегда проверяйте ввод (и, если он недействителен, повторите попытку   -  person user3629249    schedule 22.05.2017
comment
относительно: scanf("%d", &val); что произойдет, если пользователь введет: a или '\n' или <ctrl><d>``? I.E. always check the returned value from scanf()`, чтобы убедиться, что все прошло успешно.   -  person user3629249    schedule 22.05.2017
comment
при вызове fgetc() всегда проверяйте возвращаемое значение на не равное EOF, чтобы убедиться, что операция выполнена успешно.   -  person user3629249    schedule 22.05.2017


Ответы (1)


относительно блока кода:

while(!feof(rp))
     {
       if(isdigit(fgetc(rp)))
         {
          ++result;
         }

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

int ch;
while(EOF != (ch = fgetc(rp)) )
{
    if(isdigit(ch))
    {
        ++result;
    }
}

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

person user3629249    schedule 22.05.2017