2010-02-03 13 views
6

мне нужно прочитать входной файл, как:чтение неизвестное количество целых чисел со стандартного ввода (C)

1 
19 20 41 23 
2 
41 52 43 
3 
90 91 941 
4 
512 
5 

6 
51 61 

Каждая нечетная строка представляет собой целое число. Каждая четная строка - это неизвестное число целых чисел.

Это очень легко в C++

while(cin >> k){ 
............ 
} 

Я не так привыкли к C, так что я не мог сделать это в C. Любые способы сделать это?

+1

ли Вы должны обратить внимание на линию, или это просто ряд целых чисел, поступающих? В вашем примере это выглядит как нечетные строки - это порядковые номера, а четные - другое. –

+0

Давид Мне нужно обратить внимание на линии. поэтому я не мог этого сделать. Мне нужно прекратить получать новые значения в конце каждой четной строки. Потому что у меня есть структура с идентификаторами атрибутов и списком. Каждая нечетная строка - это идентификатор, а каждая четная строка - это список. Я хочу заполнить структуру двумя строками данных и перейти к другой структуре и заполнить ее еще двумя строками данных и т. Д. – huhuhuuu

+0

Прочитайте по всей строке за раз, а затем просто проанализируйте ее как строку –

ответ

9

То, как я бы сделать это, чтобы разбить его на две операции: прочитать строку, а затем прочитать целые числа в этой строке. Вот ленивая реализация с использованием стандартной библиотеки C:

char line[1024], *p, *e; 
long v; 
while (fgets(line, sizeof(line), stdin)) { 
    p = line; 
    for (p = line; ; p = e) { 
     v = strtol(p, &e, 10); 
     if (p == e) 
      break; 
     // process v here 
    } 
} 
+2

Большое спасибо. Я попробую сейчас. Но что, если я не могу взять фиксированную максимальную длину линии? – huhuhuuu

+2

Что делать, если входной поток содержит более 1024 - 2 символа, а 'fgets()' разделяет входной поток в числовом литерале? В итоге вы получите два числовых значения вместо одного. Например, с 12345 вы можете получить 123 в последней итерации цикла for и 45 в первой итерации цикла for после следующего вызова 'fgets()'. Следовательно, я бы предпочел 'scanf()' и 'fscanf()' для этой задачи, как показал Шон. –

+1

@RobinKlose: Решение 'scanf()', отправленное Sean, не решает проблему, так как не отличает разрывы строк от других пробелов. –

11

Запуск входного файла через:

#include <stdio.h> 

int main() { 
     int k; 
     while (scanf("%d", &k) == 1) { 
       printf("read number: %d\n", k); 
     } 
     return 0; 
} 

Результаты в:

 
read number: 1 
read number: 19 
read number: 20 
read number: 41 
read number: 23 
read number: 2 
read number: 41 
read number: 52 
read number: 43 
read number: 3 
read number: 90 
read number: 91 
read number: 941 
read number: 4 
read number: 512 
read number: 5 
read number: 6 
read number: 51 
read number: 61 

Это аналог C кода вы ссылаетесь в вашем оригинальный вопрос.

+0

Я могу правильно прочитайте строку, но цикл scanf бесконечно печатает первое число для меня. – tarabyte

1

Я бы сделать одно из следующих:

  • fgetc() для чтения отдельных символов и разобрать их самостоятельно (аккумулировать цифры, пока вы не нажмете пробел и у вас есть целое число для преобразования с atoi(), если whitespace является новой строкой, то оно завершает список целых чисел)

  • fgets() читать строку за раз, а затем анализировать строку (опять же, искать пробелы, разделяющие значения), которые он возвращает.

3

Я бы разорвал программу в разных задачах.

Первый шаг должен состоять в том, чтобы прочесть пару строк, первую строку, в которой указывается количество чисел для чтения, а затем вторая строка для чтения фактических чисел. Для этого может оказаться полезной функция, называемая read_set. Он должен иметь возможность возвращать прочитанные числа, а также передавать конец файла, а также ошибки. Для этого, мы можем определить структуру данных, таких как:

struct numbers { 
    long *data; /* or choose a type depending upon your needs */ 
    size_t len; 
}; 

, а затем мы можем объявить нашу функцию с прототипом:

int read_set(FILE *fp, struct numbers *num); 

Функция будет выделять память для num->data и установите num->len в правильное значение. Он возвращает 0 для успеха, а также набор условий ошибки. Мы могли бы получить фантазию и использовать enum для статуса возврата позже. На данный момент, допустим, 0 = успех, 1 = конец файла, а все остальное - ошибка.

Вызывающий затем вызывает read_set() в цикле:

struct numbers numbers; 
int status; 
while ((status = read_set(fp, &numbers)) == 0) { 
    /* process numbers->data, and then free it */ 
} 
if (status == 1) { 
    /* hit end of file, everything is OK */ 
} else { 
    /* handle error */ 
} 

Для реализации read_set(): он должен прочитать две строки. Существует много implementations of reading a full line in C, поэтому вы можете использовать любой из них и сначала прочитать строку, затем sscanf()/strtoul() для одного номера (проверьте его возвращаемое значение!). Если у вас есть количество чисел, n, вы можете прочитать следующую строку в памяти, и сделать:

num->data = malloc(n * sizeof *num->data); 
num->len = n; 

Вы можете повторно позвонить sscanf()strtol() или хранить числа в num->data. Вы должны ввести чеки, чтобы точно указать n номеров.

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

0

Я придумал решение, как это:

while(scanf("%d%c", &n, &ch)!=EOF) 
{ 
    if(ch=='\n') break; 
    /* rest of your code */ 
} 
+0

/* остальной код yout */должен быть после цикла. –

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