How to Read from Stdin

How to read from a file or standard input in Bash

The following solution reads from a file if the script is called with a file name as the first parameter $1 and otherwise from standard input.

while read line
do
echo "$line"
done < "${1:-/dev/stdin}"

The substitution ${1:-...} takes $1 if defined. Otherwise, the file name of the standard input of the own process is used.

How can I read from stdin with this specific command?

In C, reading from "standard input", or stdin, is the default. It's the easiest thing there is. You don't have to explicitly open anything; stdin is always opened for you (along with stdout and stderr) before your main function even gets called.

You can read from stdin with a variety of standard library functions. The most common are getchar and scanf. And, to repeat: you can just start calling them, on the first line of main, if you like. They work right away; there are no setup steps required.

getchar reads one character.

scanf reads "formatted input", although this function is full of problems and gotchas, to the point that it's almost not worth using.

To read one line from stdin, the function used to be gets, although it had a fatal problem and has been removed from the language. Today, to read one line from stdin, one way to do it is with the fgets function, which can actually read lines from any stream, so you have to explicitly pass it stdin as its fp argument.

How to continuously read from stdin (not just once input file is done)?

In addition to print(x, flush=True) you must also flush after sys.stdout.write.

Note that the programs would technically work without flush, but they would print values very infrequently, in very large chunks, as the Python IO buffer is many kilobytes. Flushing is there to make it work more real-time.

sys.stdout.write(str(count))
sys.stdout.flush()

How to read input from Stdin with fork()

OK; sounds straight-forward — at least, as long as you're typing the input. In fact, it is hard to make it go wrong. What did you try and what happened when you tried it? Please read up on how to create an MCVE (Minimal, Complete, Verfiable Example).

However, it gets (a lot) trickier when you're reading from a file. The problem is that when you read from the terminal, the standard I/O routines in the child get the first line of data and then let the process work with that. The child exits without reading the second line, so the parent can pick up where the child left off. If, instead, you're reading from a file, the standard I/O routines read a buffer full of data, which can be many lines. And what the child reads, the parent can't. So, what works with terminal input doesn't work with file input.

How can you avoid the problem? 'Tis hard. One possibility, which would probably be regarded as cheating, is to have the initial (parent) process read one character before forking. This fills the buffer with one line if the input is coming from a terminal, or with the initial buffer full if reading from file. After forking, the child process can read the first line (fgets()) and print it and exit. Meanwhile, the parent process also has the first line of data in its copy of the input buffers (remember, the forked child and parent are almost identical after forking), so it can read and ignore the first line (the child is processing that), and then read and print the remaining lines. It can then wait for the child to die in a loop, and finally read the remaining lines. This leads to:

/* SO 4263-5451 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void)
{
pid_t pid;
int c = getchar();
if (c == EOF)
{
fprintf(stderr, "Standard input was empty!\n");
exit(1);
}
ungetc(c, stdin);
//setvbuf(stdin, 0, _IOLBF, 0);

if ((pid = fork()) < 0)
{
fprintf(stderr, "Failed to fork()!\n");
exit(2);
}
if (pid == 0)
{
/* Child */
char line[4096];
if (fgets(line, sizeof(line), stdin) == 0)
{
fprintf(stderr, "Failed to read line in child\n");
exit(3);
}
line[strcspn(line, "\n")] = '\0';
printf("Child: read [%s]\n", line);
exit(0);
}
else
{
int corpse;
int status;
while ((corpse = wait(&status)) > 0 && corpse != pid)
printf("Parent: child %d died with status 0x%.4X\n", corpse, status);
char line[4096];
if (fgets(line, sizeof(line), stdin) == 0)
{
fprintf(stderr, "Failed to read line in parent\n");
exit(4);
}
while (fgets(line, sizeof(line), stdin) != 0)
{
line[strcspn(line, "\n")] = '\0';
printf("Parent: read [%s]\n", line);
}
}
return 0;
}

This yielded:

Child: read [Monday]
Parent: read [Tuesday]
Parent: read [Wednesday]

I tried a variant setting line-buffering with setvbuf(stdin, 0, _IOLBF, 0); but that didn't affect the file input (on a Mac running macOS Sierra 10.12.3 with GCC 6.3.0), though it too worked fine with terminal input.

One option would be to replace the standard I/O functions with file descriptor code, and to use read(STDIN_FILENO, &c, 1) to read characters one at a time. This is slower (lots of system calls) but reliable:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

static int input_char(int fd)
{
char c;
if (read(fd, &c, 1) != 1)
return EOF;
return c;
}

static size_t input_line(int fd, char *buffer, size_t buflen)
{
int c;
size_t bufcnt = 0;
while (bufcnt < buflen - 1 && (c = input_char(fd)) != EOF)
{
if (c == '\n')
break;
buffer[bufcnt++] = c;
}
buffer[bufcnt] = '\0';
return bufcnt;
}

int main(void)
{
pid_t pid;

if ((pid = fork()) < 0)
{
fprintf(stderr, "Failed to fork()!\n");
exit(2);
}
if (pid == 0)
{
char line[4096];
if (input_line(STDIN_FILENO, line, sizeof(line)) == 0)
{
fprintf(stderr, "Failed to read line in child\n");
exit(3);
}

printf("Child: read [%s]\n", line);
exit(0);
}
else
{
int corpse;
int status;
while ((corpse = wait(&status)) > 0 && corpse != pid)
printf("Parent: child %d died with status 0x%.4X\n", corpse, status);
char line[4096];
while (input_line(STDIN_FILENO, line, sizeof(line)) != 0)
{
printf("Parent: read [%s]\n", line);
}
}
return 0;
}

How to read input from the command line's standard input in Python?

This is a very simple loop that stores whatever input you give in lines

when last 2 lines are empty i.e lines[-1]==lines[-2]=="" then break;
[just mak sure that you have taken at least 2 inputs from the user so check len(lines)>2]

lines = []
while True:
inp = input()
lines.append(inp.strip())
if len(lines)>2 and lines[-1]==lines[-2]=="":
break
print('\n'.join(lines))
A
B
C

A B 2
A C 3
C B 4

A B 1


If you don't want to store all the lines

lines = ['temp', 'temp']
while True:
inp = input()
lines[-2], lines[-1] = lines[-1], inp.strip() # this changes the second last element by last one and the last one is updated to the new line that is entered
if lines[-1]==lines[-2]=="":
break


Related Topics



Leave a reply



Submit