read () из stdin не игнорирует перевод строки - PullRequest
4 голосов
/ 06 августа 2009

Я использую следующее условное выражение для чтения из стандартного ввода.

if ((n = read(0,buf,sizeof(buf))) != 0)

При вводе данных из стандартного ввода, как правило, пользователь нажимает ввод по завершении. Но read() также рассматривает '\ n' как входные данные, в этом случае n = 1 и условное выражение не оценивается как ложное. Есть ли способ сделать условную оценку ложной, когда пользователь нажимает ввод (без ввода чего-либо) на стандартном вводе, кроме проверки содержимого buf. Есть ли какая-либо другая функция, кроме read(), которую я мог бы использовать для этой цели?

В таком случае, каким может быть способ чтения, чтобы определить конец ввода, когда вход поступает со стандартного ввода (stdin)?

Ответы [ 5 ]

8 голосов
/ 06 августа 2009

Вы спрашиваете:

При вводе данных из стандартного ввода, как правило, пользователь нажимает ввод по завершении. Но read () также рассматривает '\ n' как входные данные, в этом случае n = 1 и условное выражение не оценивается как ложное.

Первое утверждение, безусловно, верно. Клавиша ввода эквивалентна клавише новой строки, поэтому, когда пользователь нажимает клавишу ввода, клавиатура генерирует символ новой строки, и поэтому функция read() возвращает этот символ. Очень важно, чтобы он это сделал.

Следовательно, ваше условие ошибочно - пустая строка будет содержать новую строку, и, следовательно, количество байтов будет равно единице. Действительно, есть только один способ получить вызов read(), возвращающий 0, когда стандартным вводом является клавиатура, и это ввести символ 'EOF' - обычно это control-D в Unix, control-Z в DOS. В Unix этот символ интерпретируется драйвером терминала как «отправить предыдущие входные данные в программу, даже если еще нет новой строки». И если пользователь ничего больше не набрал в строке, то возврат от read() будет нулевым. Если входные данные поступают из файла, то после считывания последних данных последующие чтения вернут 0 байтов.

Если входные данные поступают из канала, то после прочтения всех данных в канале вызов read() будет блокироваться до тех пор, пока не будет закрыт последний дескриптор файла, который может записать в канал; если этот дескриптор файла находится в текущем процессе, то read() будет зависать вечно, даже если зависший процесс никогда не сможет write() к дескриптору файла - при условии, конечно, однопоточного процесса.

2 голосов
/ 16 июня 2011

просто введите >1 вместо !=0

единственные ложные срабатывания - односимвольные ответы с последующим прерыванием (EOF)

1 голос
/ 06 августа 2009

Вы должны проверить буфер самостоятельно. например

while((n = read(0,buf,sizeof(buf))) > 0) {
  if(buf[0] == '\n') // won't handle pressing 9 spaces and then enter
    continue;
  ... process input

}

или используйте, например, fgets, и просто удалите \ n

while(fgets(buf,sizeof buf,stdin) != NULL) {
  char *ptr;
  size_t len;

  if((ptr = strchr(buf,'\n')) != NULL) //strip newline
    *ptr = 0; 
  len = strlen(buf);
  if(len == 0)
   continue;
  ... process input 
}
0 голосов
/ 06 августа 2009

Я совершенно уверен, что нет способа сделать это без проверки содержимого буфера. Даже readline () делает именно это. В любом случае, почему вы против этого?

0 голосов
/ 06 августа 2009

Лучше использовать fgets() для своей задачи (перехват пользовательского ввода), но даже fgets() сохраняет символ новой строки в буфере.

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

...