2015-03-05 4 views
0

Я хочу прочитать из двух файлов, один из которых содержит поплавки в трех столбцах, а другой содержит ints в двух столбцах. У меня есть следующий код для чтения из стандартного ввода:Прочтите два файла из stdio

int main() { 
    while (scanf("%lf %lf %lf\n",&x,&y,&z) != EOF) { 
     // do stuff 
    } 

    puts("foo"); 

    int a,b; 
    while (scanf("%d %d\n",&a,&b) != EOF) { 
     puts("bar"); 
    } 
} 

Тогда я вызываю программу с cat ortho.dat pairs.dat | ./angles, ortho.dat и pairs.dat быть два файла. Однако вывод равен foo, что указывает на то, что второй файл никогда не читается, по-видимому, потому, что он считывает EOF и немедленно завершает второй цикл. Это верно?

Как я мог прочитать эти два файла, фактически не открыв их в программе, просто прочитав их из stdin?

+2

1. Принятие решения о языке программирования. 2.Pass имена файлов в приложении не могут использовать 'cat'. 3. Прочитайте эти файлы - это зависит от языка программирования. –

+0

Я забыл упомянуть об этом в самой записи, но язык - это C++, как указано в заголовке и тегах. Я также специально сказал, что хочу знать, как это сделать из оболочки, без файлов. Что я знаю, как это сделать :) – andrepd

+0

Итак, почему C в заголовке и тегах, если это C++? –

ответ

3

Вопрос:

Как я мог читать эти два файла, не открывая их в программе, просто читая их из stdin?

Одно из решений:

Вставьте манекен, недействителен, содержание между содержанием двух файлов. Используйте его для разделения данных из первого файла и второго файла.

Содержание файла "манекена":

===Separator=== 

Изменить ваш код:

int main() { 
    while (scanf("%lf %lf %lf\n",&x,&y,&z) == 3) { 
     // do stuff 
    } 

    // Skip the line that contains the separator. 
    scanf("%*[^\n]"); 

    puts("foo"); 

    int a,b; 
    while (scanf("%d %d\n",&a,&b) == 2) { 
     puts("bar"); 
    } 
} 

Изменение призывание:

cat ortho.dat dummy pairs.dat | ./angles 

Update

A C++ версия:

int main() { 
    while (std::cin >> x >> y >> z) { 
     // do stuff 
    } 

    // Skip the line that contains the separator. 
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 

    puts("foo"); 

    int a,b; 
    while (std::cin >> a >> b) { 
     puts("bar"); 
    } 
} 
2

Когда вы делаете «кошка F1 F2 | программа», кот будет конкатенация файлов и программа будет получать один непрерывный поток данных.

С точки зрения программы невозможно найти, где заканчивается один файл и вторые начинаются не если некоторых маркерным вставлены в файлы

Например, вы можете вставить одну строку после первого файла, говоря:. FILE1ENDS Тогда, если такая линия никогда не будет найдено в самом файле вы можете использовать, чтобы завершить первый цикл .

В качестве альтернативы ative pass file names в качестве аргументов вашей программы и открыть/прочитать/закрыть их самостоятельно.

2

Вы не можете сделать это надежно. Читайте о fscanf(3) (он обрабатывает каждый пространственно-подобный символ, включая символы новой строки). Кстати, вам лучше проверить, что scanf возвращает фактическое количество (например, 3 для первого случая, 2 для второго).

Однако у вас может быть больше ограничений на вход. Возможно, три удвоения и два целых числа всегда находятся на одной и той же линии, например.ortho.dat содержащие линии как

1.0 2.0 3.0 

и pairs.dat, содержащие линии, как

23 45 

, то вы можете прочитать каждую строку с помощью getline(3) (или, возможно, fgets) и использовать sscanf разобрать его (и вы будете использовать его возвращение счета для разделения строк с 3-мя плавающими точками от строк с целыми целыми числами). Формат управления %n может быть удобен (он дает текущую позицию курсора).

Однако, я бы вместо того, чтобы предложить, чтобы передать два имени файла ortho.dat & pairs.dat как отдельные аргументы (т.е. использовать обычные argc & argv аргументы main(int argc, char**argv))

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