C printf не работает должным образом от терминала - PullRequest
0 голосов
/ 14 сентября 2018

Я максимально уменьшил проблему до следующих минимальных фрагментов кода.Если вам нужна дополнительная информация, пожалуйста, спросите.

Допустим, у меня есть класс Java с именем A, основной метод которого таков:

public static void main (String args[])throws Exception{
    Process p = new ProcessBuilder(args).redirectErrorStream(true).start();
    Scanner in = new Scanner(new InputStreamReader(p.getInputStream())); 
    System.out.println(in.nextLine());
}

По сути, он запускает программу из терминала, читает встрока из этой программы, и повторяет ее.Очень просто.

Теперь у меня есть вторая программа, написанная на c ++, например:

int main() 
{
    string s;
    cout << "example2 in c++"<<endl;;
    cin >> s;
    return 0;
}

Когда я вызываю:

java A pathToC++Program

, программа запускается, как ожидается, с выводомстрока, отправленная из программы cpp и завершающаяся.

У меня есть эквивалентная программа на c:

int main()
{
   char s[10];
   printf("example1 in c\n");
   fgets(s,10,stdin); 
   return 0;
}

Когда я вызываю:

java A pathToCprogram

, программа останавливается,и ничего не распечатывается.

Когда я удаляю строку fgets из программы c, чтобы она выглядела следующим образом:

int main()
{
   printf("example1 in c\n");
   return 0;
}

, тогда программа Java может распознать строку и напечататьэто из.Таким образом, может показаться, что fgets является проблемной строкой, но когда была включена функция fgets, даже строка до того, как она не сработала.

Что здесь происходит?

(Понятия не имеюесли это особенность Java или C, поэтому я включил оба тега.)

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Запись в stdout (где printf запишет свой вывод) по по умолчанию с буферизацией строки, что означает, что буфер будет сброшен на новой строке.

Но - это значение по умолчанию при запуске непосредственно из терминала.Если вывод не терминал, то stdout будет полностью буферизован, то есть он будет сброшен только при заполнении буфера.Или к явному вызову fflush(stdout).

В вашей программе на C ++ вы делаете явно сбрасываете выходные данные, используя std::endl (он записывает символы новой строки и сбрасываетбуферизованный вывод).В вашей C-программе нет такой очистки выходного буфера.

Это действительно очень зависит от платформы, но для платформ POSIX (таких как Linux или macOS) это как описано выше.Я думаю, что это очень похоже на Windows.

Что касается того, почему это работает, когда вы удаляете оператор fgets, это возможно потому, что fgets будет блокировать выполнение до конца файла илинекоторый (завершенный переводом строки) ввод был прочитан.Без fgets программа завершит работу сразу после printf, что приведет к очистке буфера stdout.

0 голосов
/ 14 сентября 2018

Передача std::endl в std::cout в C ++ приведет к сбросу буфера вывода.

Чтобы очистить буфер вывода в C, вы должны добавить fflush(stdout); после строки printf.

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