End of input linux

How to signal end-of-input to «read -N»?

I’ve been trying to figure out why I get a literal end-of-transmission character (EOT, ASCII code 4) in my variable if I read Ctrl+D with read -N 1 in bash and ksh93 . I’m aware of the distinction between the end-of-transmission character and the end-of-file condition, and I know what Ctrl+D does when using read without -N (it sends EOT, and if the input was empty, the underlying read() returns zero, signalling EOF). But I’m not sure why trying to read a specific number of characters changes this behaviour so radically. I would have expected an EOF condition and that the following loop would exit:

while read -N 1 ch; do printf '%s' "$ch" | od done 
0000000 000004 0000001

-N nchars ; read returns after reading exactly nchars characters rather than waiting for a complete line of input, unless EOF is encountered or read times out.

. but it says nothing about switching the TTY to raw/unbuffered mode (which is what I assume is happening). The -n option to read seems to work in the same way with regards to Ctrl+D , and the number of characters to read doesn’t seem to matter either. How may I signal an end-of-input to read -N and exit the loop (other than testing the value that was read), and why is this different from a «bare» read ?

Very interesting issue . By the way if you use read -e -N 1 ch works fine. -e options involves bash readline for interactive shells. Maybe this means that read -N works in a non interactive way while simple read works interactivelly.

Looking at bash sources, this is exactly what happens: the TTY is put in raw mode, and EOF takes effect only in canonical mode. With -e it’s more complicated, but it’s still not a true EOF (you can see that with read -e -N 2 ch ). I suppose that’s a bug, i.e. the EOF should be emulated in both cases.

1 Answer 1

It might be more helpful if the doc pointed out that there’s no such thing as an ASCII EOF, that the ASCII semantics for ^D is EOT, which is what the terminal driver supplies in canonical mode: it ends the current transmission, the read . Programs interpret a 0-length read as EOF, because that’s what EOF looks like on files that have that, but the terminal driver refusing to deliver character code 4 and instead swallowing it and terminating the read isn’t always what you want.

That’s what’s going on here: control character semantics are part of canonical mode, the mode where the terminal driver buffers until it sees a character to which convention assigns a special meaning. This is true of EOT, BS, CR and a host of others (see stty -a and man termios for alll the gory details).

Читайте также:  Astra linux smolensk iso

read -N is an explicit order to just deliver the next N characters. To do that, the shell has to stop asking the terminal driver for canonical semantics.

By the way, EOF isn’t actually a condition a terminal can set, or enter.

If you keep reading past eof on anything else, you’ll keep getting the EOF indicator, but the only EOF the terminal driver can supply is a fake one—think about it—if the terminal driver actually delivered a real EOF, then the shell couldn’t keep reading from it afterwards either. It’s all the same terminal. Here:

#include #include char s[32]; int main(int c, char**v) < do < c=read(0,s,sizeof s); printf("%d,%.*s\n",c,c,s); >while (c>=0); > 

try that on the terminal, you’ll see that the terminal driver in canonical mode just interprets EOT to complete any outstanding read, and it buffers internally until it sees some canonical input terminator regardless of the read buffer size (type a line longer than 32 bytes).

The text that’s confusing you¸

is referring to a real EOF.

Источник

How to end an input when enter is passed

This program bubble sorts the inputs first and gives the output of the difference between the largest and smallest number. I want to end the input when I type enter . For example, input = 6 4 2 , output= 4 . (end the input by ‘enter’)

How to end an input when enter is passed end of input is already marked by pressing ENTER for almost all the i/p APIs. Please state your problem correctly.

3 Answers 3

To end input when Enter or ‘\n’ occurs is challenging using scanf(«%d». as «%d» first consumes any white-space including ‘\n’ . Need a different way to watch for ‘\n’ first.

or better yet, use fgets() . Easy to catch all sorts of invalid input.

#include #define MAX_INT_SIZE (sizeof(int)*CHAR_BIT/3 + 3) c = 0; char buf[n*(MAX_INT_SIZE + 1) + 2]; if (fgets(buf, sizeof buf, stdin)) < char *p = buf; for (; cif (*p) Handle_Missing_or_Extra_or_Nonnumeric_input(); > 

You need to read a whole line, e.g. with fgets(3), getline(3), or even (if running on a terminal, e.g. under Linux) readline(3) (which offers editing abilities). Then convert each line to a number using sscanf(3) or strtol(3) and test when the conversion fails.

 const int arraysize = sizeof(array)/sizeof(array[0]); // 1000 printf("Enter at most %d integers ended by a blank line\n", arraysize); for (c = 0; c // here c contains the number of actually read integers. 

Read the documentation of every function that you are using. Notice that scanf , fscanf and sscanf are returning the count of successfully scanned items.

The clearing memset(3) is probably unneeded .. but just in case I always clear buffer.

Источник

End of File(EOF) of Standard input stream (stdin)

Does stdin have any EOF? For example, if I start reading from stdin using fread or read , then will the following loop end?

while ((c = read(0, buffer, BUFSIZ)) > 0)

6 Answers 6

Speaking about EOF in stdin: when you redirect input from file, e.g.:

Читайте также:  Alt linux включить wifi

the file already has an EOF , so this is not a problem. In console you can simulate EOF flag. In UNIX systems it is Ctrl + D , in Windows Ctrl + Z . When you type this in the console, program will behave like it has just reached end of input file.

Edit

According to a question asked by OP:

So does it means that stdin don’t have EOF and we have to insert them manually using Ctrl+Z or Ctrl+D?

Actually — yes. One may consider stdin (not redirected, but taken from the console) as infinite file — no one can tell where does it end. The end of input file, where input ist stdin, must be told literally by Ctrl + D or Ctrl + Z .

As I’ve just learned myself, Ctrl+D does not ‘send EOF’ but sends EOT. EOT after not input (or after all input is already sent) makes stdin to have EOF. But when you input «ABC» and then Ctrl+D it will just send the buffer to the process and not ‘signal’ EOF.

I have never programmed C in windows so I can’t tell you but in bash, the program will get an EOF when you type end of data (Ctrl+D)

@Bart van Heukelom so after typing Ctrl+D, what should i do if i want to read more inputs from stdin later on? is it possible?

If you’re using stdio, you can call clearerr(stdin); to clear the EOF status and you will be able to continue reading. (If stdin is a file that hasn’t grown since you got EOF, you’ll just get a new EOF condition as soon as you try to read.) If you’re using low-level read() , it returns 0 on when the terminal has EOF status, but if you try to read again it will block waiting for input.

while ((c = read(0, buffer, BUFSIZ)) > 0)  

You don't say the type of c but using that name implies that it's a char . Note that the EOF value for iosteams is an (int) -1 . Storing that into an unsigned char will get you a value of 255 which will not match EOF.

ok . c is of int type . i was just giving the example . now come back to the original problem and according to you, what is the ans?

The way to test for EOF is to check the return value of fread, and then use feof:

while( fread( . ) ) < // loop so long as fread does not return zero // do something >if ( feof( stdin ) ) < // read failed because of EOF >else < // some other error >

why? . you mean to say the while loop will return after a finite number of iterations . if so the after how many?

@Ravi fread() attempts t read data - if there is nothing to read, it returns zero. So the loop above will read standard input or a file until an EOF is encountered.

@Neil Butterworth ok . i tried your code and it gives some other errors . So does it means that stdin don't have EOF and we have to insert them manually using Ctrl+Z or Ctrl+D?

Your solution is tagged C++, so here's some C++.

std::string lols; while(!(std::cin >> lols).eof()) < // This loop will end when EOF is reached // Process string >

will the loop ends? . that what i am asking . i am not asking different ways of writing the same code.

You have overcomplicated that and in doing so broken it. If the read fails for some other error then the stream will be marked bad and not read anymore but the EOF will not be reached and thus loop forever. The simpler and correct way to loop would be: 'while( std::cin >> lols) <>'

@Martin York: I did originally have it without the EOF, but the OP's comment shows that he could really use the hint about what's going on. @Ravi Gupta: It will keep going until EOF. That's why I put in the EOF function check. So that it's goddamn obvious that the code executes until EOF. And there's a comment there, telling you that the loop will end when EOF is reached. I mean, this code is pretty self explanatory.

First getchar() is really getc(stdin) so getc(FILE) you can read more from that. getchar() gets you last unprocessed character from input stream or stdin pressing enter is '\n'. if the stdin is empty getchar forces a pause to get input. Say in a program I call getchar() at first the stdin is empty so it pauses for input. If I enter ab'\n' the first getchar() will get 97 the ascii of 'a'. the next time i call getchar() i will get b , then again getchar() will have '\n'.

To prove this write this code.

I do believe stdin is a global so until getchar() or similar function gets called it to clear the stream the characters remain there which can cause bugs later if you use getchar() elsewhere. As people have mentioned you can use gets(char[]) which puts all characters until newline into the character array. The problem with this is you need a char[] larger than input or you will get errors. The nice thing is gets(char[]) does clear stdin so you can make a dumby buffer to clear stdin or process it.

I hope this is informative.

Источник

Оцените статью
Adblock
detector