Как заставить fgetc печатать все символы файла внутри цикла

Я играю с fgetc и задаюсь вопросом, как заставить цикл печатать раздел строки один раз, а затем печатать первые 16 символов.

Вот мой код:

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

    if((fp = fopen(argv[1], "rb+")) == '\0')
    {
        perror("fopen");
        return 0;
    }

    getchar(fp);

    return 0;
}

void getchar(FILE *fp)
{
    int c;
    size_t linecount = 0;

    while((c = fgetc(fp)) != EOF)
    {
        printf("line : ");
        printf("%c ", c);
        linecount++;

        if(linecount == 16)
        {
            printf("\n");
        }
    }
}

Я хочу, чтобы мой вывод был примерно таким:

 line: ? 5 d s d a d 0 0 0 0 0 0 0 0 0 0 0
 line: a d s x c v d 0 0 0 0 0 0 0 0

Я попытался напечатать символы, используя этот цикл for:

for(i = 0; i < 16; i++)
{
   printf("%c ", c);
}

Но это не привело к другим символам, потому что цикл все еще был сосредоточен на первом символе.


person user798774    schedule 08.07.2011    source источник
comment
вы уверены, что ваш входной файл имеет не менее 17 символов?   -  person Vinicius Kamakura    schedule 08.07.2011


Ответы (2)


Во-первых, уже есть стандартная функция с именем getchar(), определенная в <stdio.h> — вы должны изменить имя своей функции, иначе вы можете получить очень странное поведение.

Во-вторых, мне кажется, что вы хотите сделать следующее:

  • Распечатать "line: ";
  • Прочитайте символ и распечатайте его до конца файла или до тех пор, пока вы не напечатаете 16 символов;
  • Распечатайте "\n".

Это будет переведено в форму кода как:

printf("line : ");

while (linecount < 16 && (c = fgetc(fp)) != EOF)
{
    printf("%c ", c);
    linecount++;
}

printf("\n");
person caf    schedule 08.07.2011
comment
Можно изменить, чтобы печатать "line:", а затем %c в цикле, если лишний пробел в конце каждой строки нежелателен. - person Chris Lutz; 08.07.2011

if((fp = fopen(argv[1], "rb+")) == '\0')

Символ ASCII NUL не совпадает с указателем NULL. Это должно быть == NULL или if(!(fp = fopen(argv[1], "rb+"))) /* ... */, в зависимости от того, как вам удобнее читать. return 0 в этом предложении, вероятно, должно быть return 1, чтобы с вашей программой было легче работать в стандартных конвейерах. (Ошибки в программах становятся очевидными благодаря ненулевому возвращаемому значению. Да, это немного наоборот, но есть уважительная причина.)

void getchar(FILE *fp)

Упс. getchar(3) уже существует в заголовке <stdio.h>. Переопределять - не лучшая идея. (Это может работать сейчас, но будущая модификация может полностью не работать по неочевидным причинам.)

Я немного переработал цикл в подпрограмме gc(), он должен делать то, что вам нужно:

#include <stdio.h>

void gc(FILE * fp);

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

    if ((fp = fopen(argv[1], "rb+")) == NULL) {
        perror("fopen");
        return 1;
    }

    gc(fp);

    return 0;
}

void gc(FILE * fp)
{
    int c;
    size_t linecount = 0;

    while ((c = fgetc(fp)) != EOF) {
        if (linecount == 0)
            printf("line : ");

        printf("%c ", c);

        if (++linecount == 16) {
            printf("\n");
            linecount = 0;
        }
    }
}

Вывод при запуске сам по себе:

$ ./printer printer.c | head
line : # i n c l u d e   < s t d i o . 
line : h > 

 v o i d   g c ( F I L E 
line :   *   f p ) ; 

 i n t   m a i 
line : n ( i n t   a r g c ,   c h a r 
line :   * a r g v [ ] ) 
 { 
person sarnold    schedule 08.07.2011
comment
Обратите внимание, что '\0' представляет собой целочисленное константное выражение со значением 0 и, следовательно, является допустимой константой нулевого указателя (но все же указывает на значительную путаницу). - person caf; 08.07.2011