fopen замораживает программу

#c #terminal #fopen

Вопрос:

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

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

void    find_word (void);    

int     main (int argc, char *argv[])
{

        find_word();

        return 0;    
}     

void    find_word (void)
{

        FILE *file;
        int character;
        int line_number;

        file = NULL; 
        character = 0;
        line_number = 0;
    
        file = fopen ("word_source.txt", "r");

        if (file == NULL)
        {
            printf("Errorn");
            exit (0);
        }

        printf("%c", character);
        character = fgetc(file);
        while (character != EOF)
        {
            if (character == 'n')
            {
                line_number  ;
            }
        }

        fclose(file);

        printf("%d", line_number);

}

 

Я понятия не имею, в чем проблема, поэтому я создал еще один файл, и этот работает:

 #include <string.h>
#include <stdio.h>

int     main (int argc, char *argv[])
{
        FILE *file = fopen ("word_source.txt", "r");
        
            if (file == NULL)
                printf("No");
        
            else
                printf("Yes");

            return 0;
}
 

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

1. символ @user3121023 уже является fgetc(файл)

2. @zelph14 ваш код считывает ровно один символ из файла. Вы хотите прочитать все символы файла.

3. «Ошибка» не является полезным сообщением об ошибке, вы записываете его в неправильный поток, и это кажется странным exit(0) и утверждает об успехе при этой ошибке. Попробуй: const char *path = "word_source.txt"; if( (file = fopen(path, "r")) == NULL) { perror(path); exit(EXIT_FAILURE);}

4. @user3121023 о да, это было так просто… спасибо !!

Ответ №1:

fopen здесь не бесплатно. Ваш код, похоже, замерзает, потому что у вас здесь бесконечный цикл:

 character = fgetc(file);   // read one char from file

while (character != EOF)   // this loop is repeated indefinitely
{                          // because character never changes inside the loop
  if (character == 'n')  
  {
    line_number  ;
  }
}
 

Ты хочешь этого:

 while (1)
{
  character = fgetc(file);   // reads a character from the filee

  if (character == EOF)      // if end of file
    break;                   // stop the loop

  if (character == 'n')     // is character read a newline?
  {
    line_number  ;           // increment line number
  }
}
 

или более компактным:

 while ((character = fgetc(file)) != EOF)
{
  if (character == 'n')     // is character read a newline?
    line_number  ;           // increment line number
}
 

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

1. @JonathanLeffler добавил более короткую версию. Я полагаю, что это более идиоматично, но, возможно, труднее понять новичку.

2. @JonathanLeffler Первая версия была понятной и понятной. «Идиоматический» C с назначением, втиснутым в while инструкцию, является конструкцией, настолько подверженной ошибкам, что отраслевые стандарты кодирования, такие как MISRA, касающиеся надежности кода и безопасности человека, запрещают его использование в совместимом коде. MISRA C:2004, 13.1, MISRA C :2008, 6-2-1, MISRA C:2012, 13.4 и сертификат, EXP45-C применяются все и, вероятно, немало других. Видишь wiki.sei.cmu.edu/confluence/display/c/… только для одного примера.

3. Подсказка: если ваша программа «останавливается», проверьте использование процессора. Если 0, он заблокирован, если 100%, он зацикливается.