read() from stdin doesn't ignore newline

2019-01-19 23:38发布

I am using the following conditional statement to read from standard input.

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

When inputting data from standard input, generally the user presses enter when done. But read() considers '\n' as input too in which case n = 1 and the conditional doesn't evaluate to false. Is there a way to make the conditional evaluate to false when the user presses enter (without entering anything) on standard input apart from checking the contents of buf. Is there any other function other than read() that I might use for this purpose??

For that matter, what can be a way for read to determine end of input when the input comes from standard input (stdin)?

5条回答
做自己的国王
2楼-- · 2019-01-19 23:53

just type >1 instead of !=0

the only false positives are single character responses followed by an interrupt (EOF)

查看更多
来,给爷笑一个
3楼-- · 2019-01-19 23:53

I'm quite positive there's no way to do it without examining the buffer contents. Even readline() does just that. Why are you opposed to it, anyways?

查看更多
4楼-- · 2019-01-19 23:56

You have to check the buffer yourself. e.g.

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

}

or use e.g. fgets, and just strip off the \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 
}
查看更多
看我几分像从前
5楼-- · 2019-01-19 23:58

You ask:

When inputting data from standard input, generally the user presses enter when done. But read() considers '\n' as input too in which case n = 1 and the conditional doesn't evaluate to false.

The first point is certainly true. The enter key is equivalent to the newline key, so when the user presses enter, the keyboard generates a newline character, and the read() function therefore returns that character. It is crucial that it does do that.

Therefore, your condition is misguided - an empty line will include the newline and therefore the byte count will be one. Indeed, there's only one way to get the read() call to return 0 when the standard input is the keyboard, and that's to type the 'EOF' character - typically control-D on Unix, control-Z on DOS. On Unix, that character is interpreted by the terminal driver as 'send the previous input data to the program even if there is no newline yet'. And if the user has typed nothing else on the line, then the return from read() will be zero. If the input is coming from a file, then after the last data is read, subsequent reads will return 0 bytes.

If the input is coming from a pipe, then after all the data in the pipe is read, the read() call will block until the last file descriptor that can write to the pipe is closed; if that file descriptor is in the current process, then the read() will hang forever, even though the hung process will never be able to write() to the file descriptor - assuming a single-threaded process, of course.

查看更多
▲ chillily
6楼-- · 2019-01-20 00:13

You better use fgets() for your task (catching user input), but even fgets() stores newline character in buffer.

However if newline is there, you can be sure it is last character in the string so it is easy to strip it.

查看更多
登录 后发表回答