2016-04-19 2 views
4

Хотя есть простой способ использования как файла Перенаправление и трубопроводов, а также интерактивный пользовательский ввод, чтение, с основной(), как показано в этом коде C сниппета ...unix: main() интерактивный, командная строка, трубопровод и перенаправление в C?

#define SIZ 1024 
#include <stdio.h> 
extern void do_something_with_the_array(float *a[], int *n); 

int main(int argc, const char * argv[]) 
{ 
    float f[SIZ]; 
    int k = 0; 
    while ((scanf("%f", &f[k]) == 1)&&(k < SIZ)) { 
     k++; 
    } 
    do_something_with_the_array(f, k); 
    return 0; 
} 

... Я не уверен, если есть современный источник UNIX совместим и простой способ программно достижения любой из трех возможностей в main() в C, в зависимости от контекста?

  • интерактивное чтение строки чисел в качестве входных данных пользователя
  • чтение той же строки чисел в качестве аргументов командной строки
  • перенаправления файлов и трубопроводов

Я понимаю, что трубопроводы и перенаправление «принадлежит» оболочке, которая перехватывает программу, прежде чем она даже начнет выполнение, в то время как аргументы командной строки и интерактивное чтение «принадлежат» к main() сам, и поэтому может быть нелегкий способ сделать это.

Я вижу, используя или стандартный ввод файла входа или труб входа довольно очевидно. Однако чтение аргументов командной строки - это совсем другая история. Вот демо, как я обычно его кодирую, но он выглядит тяжело и взломан для меня. Кроме того, в более сложных сценариях с вариантами это может стать довольно грязным фрагментом кода. Я также не знаю, насколько это безупречное или безупречное доказательство ...

#define SIZ 1024 
#include <stdio.h> 
#include <stdlib.h> 
extern void do_something_with_the_array(float *, int); 

int main(int argc, const char * argv[]) 
{ 
    float f[SIZ]; 
    int k = 0; 
    if(argc > 2){ 
     for(k = 0; k < argc - 1; k++) 
      f[k] = (float)atof(argv[k+1]); 
    } 
    else while ((scanf("%f", &f[k]) == 1)&&(k < SIZ)) 
     k++; 

    do_something_with_the_array(f, k); 
    return 0; 
} 

Заранее благодарен!

+1

Обрезанные вы, возможно, потенциально могут переполняться. – Leandros

+6

Почему это невозможно? Просто напишите оператор switch для обработки трех условий. –

+0

Программа обычно не знает, относится ли 'stdin' к терминальной консоли, к файлу, сокету или любому другому потоку, о котором вы могли бы подумать. – EOF

ответ

1

Я не знаю, что из библиотеки C, которая сделает три конкретных случая, о которых вы упомянули, выглядит одинаково (хотя кто-то, кто это делает, ответим, потому что я тоже хотел бы знать!). Я думаю, что вы ищете что-то не похожее на the diamond <> operator in Perl, но на отдельные аргументы, а не на файлы, содержащие аргументы.

Я думаю, что @David Hoelzer имеет правильную идею: обрабатывать три случая отдельно. Например, при обработке аргументов командной строки или файла не генерируйте подсказки «Введите значение», которые вы можете распечатать для интерактивного ввода. Для обработки в командной строке getopt - хорошее место для начала.

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

+0

спасибо @cxw. Я знал, что 'getopt()' используется как часть gnu-C. Я проверил, это часть NetBSD (Дарвин, OSX). Некоторые тесты дают многообещающие результаты. Я принимаю этот ответ как наиболее полезный для поиска решения моего вопроса. Если у меня есть шанс успешно написать предлагаемую библиотеку, я обязательно опубликую ее с открытым исходным кодом! – user3078414

+0

@ user3078414 Огромное спасибо и удачи вам! Если вы думаете об этом, как только вы опубликуете, прокомментируйте ссылку, и я проверю ее :). – cxw

1

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

Давайте возьмем/bin/sh в качестве нашего первого примера. Если вы вызываете его напрямую, он запускает интерактивную оболочку, но если вы что-то в ней что-то вставляете, она начинается как неинтерактивная оболочка чтения. Основное различие между ними состоит в том, что если оно не является интерактивным, оно не отображает подсказку $.Однако на всякий случай, если это действительно интерактивно, его можно запустить с опцией -i, чтобы он предположил, что он интерактивен, когда он обычно принимает иное решение.

Магия здесь - isatty(); см. man 3 isatty.

Кроме того, некоторые программы любят получать ввод с клавиатуры при обработке перенаправленного стандартного ввода. Есть два общепринятых способа сделать это; либо открытие и чтение с /dev/tty, либо чтение стандартной ошибки, в зависимости от контекста. Большинство материалов в интерактивно запущенном конвейере не имеют стандартного перенаправления ошибок, поэтому это имеет тенденцию работать хорошо (чтение перенаправленной стандартной ошибки дает ошибку сразу, поскольку дескриптор не открыт для чтения). Если вы хотите, чтобы это потенциально полностью автоматизировалось, вы читаете стандартную ошибку, иначе вы читаете /dev/tty.

+0

Спасибо за ваш ценный вклад. Я также «на этом треке». На данный момент я изучаю обработку сигналов во всех случаях, так как некоторые из программ, которые я пишу, чтобы выполнить это требование, также выполняют очень интенсивный хруст числа и имеют потоки с приоритетом в реальном времени. – user3078414

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