#c #shell #io #stdin #console-input
#c #оболочка #io #стандартный интерфейс #консольный ввод
Вопрос:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void eat() // clears stdin upto and including n OR EOF
{
int eat;while ((eat = getchar()) != 'n' amp;amp; eat != EOF);
}
int main(){
printf("n COMMAND : "); char cmd[21]=""; scanf(" s",cmd);
if(strcmp(cmd,"shell")==0||strcmp(cmd,"sh")==0)
{
getchar(); // absorb whitespace char separating 'shell' and the command, say 'ls'
while(1)
{
printf("n sh >>> "); // print prompt
char shellcmd[1024]=""; // str to store command
scanf("23[^n]",shellcmd); eat(); // take input of command and clear stdin
if(strcmp("close",shellcmd)==0||strcmp("x",shellcmd)==0)
break;
else
system(shellcmd);
}
}
}
В коде происходит некоторое аномальное поведение, которое я не могу уловить.
После ввода sh ls
и нажатия [ENTER]
ожидаемый ответ:
- 1-й
scanf()
сохраненsh
cmd[]
и выходитlsn
stdin
. getchar()
занимаетprintf()
выводитn sh >>>
на терминал- второй
scanf()
сохраняетls
shellcmd[]
, оставляетn
в stdin eat()
считываетn
из stdin, оставляя его пустымsystem("ls")
выполняется
Т.е. Результаты должны быть такими:
COMMAND : sh ls
sh >>>
file1 file 2 file3 ...
sh >>> | (cursor)
НО
Что я получаю:
COMMAND : sh ls
file1 file2 file3 ...
sh >>>
sh >>> |
По-видимому, 2-й scanf()
и shell()
выполняется раньше printf()
, или, по крайней мере, это мое предположение.
Что не так?
Скомпилирован на Clang и GCC с cc -Wall -Wextra -pedantic
помощью и протестирован на bash как на macOS, так и на Linux
Ответ №1:
Как вы можете найти на странице руководства:
Если поток ссылается на терминал (как обычно делает стандартный вывод), он буферизуется по строке
Таким образом, вы можете столкнуться с задержкой при просмотре сообщения, напечатанного printf
, когда оно не содержит новой строки. На другом конце отображается сообщение previos, как только отправляется начальная новая строка следующего printf
.
Решения:
-
Добавьте новую строку в конце вашего сообщения
printf("n sh >>> n");
-
Принудительно отобразите текущий буфер даже при отсутствии новой строки, вызвав
flush()
функцию (fflush(stdout)
) -
Измените текущее поведение буферизации стандартного вывода с помощью
setvbuf()
функцииsetvbuf(stdout,NULL,_IONBF,0);
Комментарии:
1. О, я вижу 0 0 … так что это не ошибка в моей программе точно 🙂
2. @user13863346 попробуйте (я бы начал с варианта 2) и дайте мне знать, если это сработает
3. Да, это сработало … исправлено! flush() работает, как и
'n'
в конце моей строки формата.. Я обескуражен 3-м, поэтому не буду пробовать;)4. @user13863346 Просто позвоните
setvbuf(stdout,NULL,_IONBF,0);
перед печатью чего-либо.5. Ошибка связана с безумно неинтуитивным базовым консольным API C…