2016-03-01 3 views
1
int getLineCount() { 
     int ret = 0; 
     char c; 
     while ((c = fgetc(stdin)) != EOF) 
      if (c == '\n') 
       ret++; 
     return ret + 1; 
    } 

    void fill(char *WORD) { 
     int charIndex = 0; 
     char c; 
     while ((c = fgetc(stdin)) != EOF) { 
      *(WORD + charIndex++) = c; 
     } 
    } 

    int main() { 
     int lineNum = getLineCount(); 
     char *WORD = (char*)calloc(lineNum * 18,sizeof(int)); 

     fill(WORD); 
     return 0; 
    } 

Вот часть моего кода, и мой вопрос (как вы можете видеть):Чтение из STDIN Дважды C

Я пытаюсь читать содержание STDIN дважды, но после getLineCount функция, она остается на EOF, и я не могу прочитать ее снова в заполните функции.

Im принимает stdin от пользователя с помощью этой команды в Linux;

$./output < text_file.txt 

Есть ли способ отбросить stdin до начального символа? Если нет, как я могу исправить эту проблему?

Спасибо.

+0

Попробуйте 'man fseek'. ** Обновление **: К сожалению. Это 'stdin' .. нет, вы не можете. Он не доступен для поиска. –

+5

@ user3121023: Плохой стиль, чтобы предположить, что вы можете перемотать 'stdin'. – Olaf

+0

@ user3121023 Интересно ... Это действительно работает? –

ответ

1

Вы можете использовать rewind(stdin), чтобы установить поток обратно в начало файла, но имейте в виду, что он не гарантированно работает, особенно если поток является трубой, терминалом или устройством.

Ваша схема размещения неверна: вы можете вычислить размер файла, а затем выделить столько байтов, но ваш текущий (char*)calloc(lineNum * 18,sizeof(int)); выделяет в 18 раз больше размера типа int для каждой строки. Некоторые файлы с короткими строками будут вписываться в этот массив, а другие вызовут неопределенное поведение.

Обратите внимание, что c должен быть определен как int для c = fgetc(stdin); правильно хранить все значения, включая EOF особого значения.

+0

Это всего лишь часть кода (не полная), это должно быть 18 из-за требований решения. –

+0

@ DoğaCanYanıkoğlu: '18' что? Если строки имеют фиксированную ширину и 18 байтов, включая '\ n', вы должны выделить' calloc (lineNum * 18,1) ' – chqrlie

+0

Это массив 2D String. 18 - длина слова и имеет 1 символ в каждой ячейке памяти. @chqrlie –

1

Не использовать rewind.

Вы можете, конечно, сохранить данные, которые вы читаете из stdin (потенциально в файле, если он слишком велик для основной памяти) и работать над этим.

Другая возможность заключается в следующем:

struct callback { 
    void (*call) (char, void *); 
    void * data; 
}; 

void with_characters_from(FILE * file, struct callback const * callbacks, size_t count) { 
    int c; 
    while ((c = fgetc(file)) != EOF) { 
    char character = c & 0xFF; 
    for (size_t i = 0; i < count; ++i) { 
     callbacks[i].call(character, callbacks[i].data); 
    } 
    } 
} 

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

A small test:

struct counter_data { 
    char const character; 
    unsigned count; 
}; 

void counter (char character, void * vptr) { 
    struct counter_data * data = vptr; 
    if (character == data->character) { 
    ++(data->count); 
    } 
} 

int main() { 
    struct counter_data data [2] = { 
    {'a', 0}, {'x', 0}}; 
    struct callback callbacks [2] = { 
    {&counter, &(data [0])}, 
    {&counter, &(data [1])}}; 
    with_characters_from (stdin, callbacks, 2); 
    printf("Counted %c %u times \n", data [0].character, data [0].count); 
    printf("Counted %c %u times \n", data [1].character, data [1].count); 
    return 0; 
} 

Как уже отмечалось, для вашего конкретного примера, вы должны рассмотреть совершенно иной подход: если это возможно вычислить необходимый размер заранее. Если вы превысите этот размер (который вы должны всегда тестировать), используйте realloc, чтобы получить больший объем памяти.

Смежные вопросы