Why we need stdin as the file version of the input functions? - c

In C, stdin is a valid file pointer, thus we could use stdin (and the 2 others) with the "file" version of the input functions if we want or need to.
Why might us need to (Rather than just pipe in from shell)? Could anyone come up with some examples please?

Here's an example:
FILE * input = argc == 2 ? fopen(argv[1], "r") : stdin;
fgets(buf, sizeof buf, input);
Now you can use your tool as magic data.txt and as magic < data.txt.

If you write a function that works on any FILE *, and at a higher level you decide that you want the output to go to stdout. Or read from any FILE * and instead you decide to read from stdin.
If you at, for example, the program wc which counts characters in a file, you'll see that it can read from stdin or from a file name given as a command line argument. This decision could be made in the main by checking to see if the user provided a file name with $ wc file.txt or called with just wc, or piped input from something else $ ls -l | wc
$ wc # reads from stdin
$ wc file.txt # counts characters in file.txt
$ ls -l | wc # reads from stdin also.
and you can imagine a simple main which says:
int count_chars(FILE *in);
int main(int argc, char *argv) {
if (argc == 2) { // if there is a command line argument
FILE *input = fopen(argv[1], "r"); // open that file
count_chars(input); // count from that file
} else {
count_chars(stdin); // if not, count from stdin
}
return 0;
}
Additionally to print errors one would use fprintf(stderr, "an error occured\n");

Related

Reading text file from terminal line?

So I understand that to read and print out a line of text you can just use printf, scanf and type it out. However what if I want to print out a text file without typing them out in terminal? And I don't mean using fopen(filename, "r") where you can only open a specific file. I think this is called redirection but I'm having trouble understanding it. Something along the line as the below input example:
./myprogram < input.txt
Here is a redirection cheat sheet. The line that interest us is:
cmd < file: Redirect the contents of the file to the standard input (stdin) of cmd.
Here a simple example that will print the content of your input.txt file. Compared to manual input, the program will never wait and will loop until the end of the file is reached (Note: there are cases where there is no end, you might want to add alternative break condition).
#include <stdio.h>
int main(void)
{
char buffer[100];
while (fgets(buffer, 100, stdin))
printf("%s", buffer);
return (0);
}
./myprogram < input.txt will print your input.txt
./myprogram will wait for your manual input and print what you just typed.
This is not exactly what you asked but you can put the filename as argument and get it in argv[1] and then use fopen

It possible to replace file to buffer while pass input to an exe as shell command?

I'm using "system" API calls to run shell commands in my C program, now
there is case where I want to redirect the output generated by an executableto a buffer instead of a file (named recv.mail)
An example of how I write the output to the file:
cmd[] = "mda "/bin/sh -c 'cat > recv.mail'";
system (cmd);
Similarly I want to replace input taken from the file (send.mail) with input taken from a buffer.
An example of how I take input from a file:
cmd[] = "msmtp < cat send.mail";
system (cmd);
NOTE: The send.mail and recv.mail files have formatted data.
Are pipes a better replacement?
Can anyone suggest another alternative?
popen/pclose may do what you want:
FILE *f = popen("program to execute", "r");
if (NULL != f)
{
char buffer[128];
while (fgets(buffer, sizeof buffer, f)
{
printf("Read from program: '%s'\n", buffer);
}
pclose (f);
}
popen/pclose again:
FILE *f = popen("program to execute", "w");
...

How to redirect stdin back within C program (under Windows)

I have a simple C program called a.exe, with main loop like this:
void input_console()
{
printf(">>");
char in_string[256] = {0};
fgets(in_string, 256, stdin);
parse(in_string);
}
It works like this when I start it and enter commands from my keyboard:
>>say_hello
Hello!
>>say_goodbye
Goodbye!
>>
no command found
>>blablablabla
Command blablablabla not recognized
>>
no command found
etc.
Now I would like to read input from file instead of the keyboard so I prepared in.txt like this:
say_hello
say_goodbye
blablabla
After running a.exe < in.txt (this is Windows) I get:
>>Hello!
>>Goodbye!
>>Command blablabla not recognized
>>no command found
>>no command found
>>no command found
... (infinite loop)
I guess fgets keeps getting EOF here and my parser reaction to EOF is to print no command found message.
What I would like to do is to be able to return the input stream back to stdin once the input file I used with "<" redirection is over so I can use keyboard again. Something like:
if (in_string[0] == EOF)
stop_using_a_file_as_stdin_and_go_back_to_normal();
Is there any way to do that ?
EDIT:
Answer given by Harry Johnston in the comments works:
freopen("CON", "r", stdin);
or:
freopen("CONIN$", "r", stdin);
Instead of using input redirection, you could pass the filename as a command-line argument and open it yourself.
int main (int argc, char **argv){
FILE *input = stdin;
if (argc > 2){
input = fopen(argv[1], "r");
}
// ...
Then you can switch back easily.
input = stdin;

Read file from terminal input "cat" on C

I'm making a program that read CSV files based on the arguments of the C program called read-log
example
$ ./read-log file1.csv
$ ./read-log file1.csv file2.csv nofile.csv
But I also need my program to read files when using the unix command cat but when I input:
$ cat file1.csv |./read-log
The program doesn't get any argument.
Just use the FILE *stdin that is open by default:
FILE *fp;
if (argc > 1) {
if (strcmp(argv[1], "-") == 0) // Many utilities accept "-" for the
fp = stdin; // filename to indicate stdin
else
fp = fopen(argv[1], "r");
}
else {
fp = stdin;
}
When you're done using the file, make sure you only close it if you actually opened it: (Closing stdin can lead to some interesting bugs down the road!)
if (fp != stdin)
fclose(fp);

How do I read file into a command line?

Basically what I want to do is have a program with int main(argc, *argv[]) and instead of writing chars into command line, I want to have my program read those words from a file. How could I accomplish this? Is there a special command in Linux for that?
You can use standard redirect operations in a *nix shell to pass files as input:
./myprogram < inputfile.txt
This statement executes your program (myprogram) and pumps the data inside of inputfile.txt to your program
You can also redirect the output of program to a file in a similar fashion:
./myprogram > outputfile.txt
Instead of doing
for(int i = 1; i < argc; i++)
{
insert(&trie, argv[i]);
}
you could doing something like
FILE *input;
char *line;
....
while (fscanf(input, "%ms", &line) != EOF) {
insert(&trie, line);
/* If you make a copy of line in `insert()`, you should
* free `line` at here; if you do not, free it later. */
free(line);
}
Use redirection
yourprogram < youtextfile
will offer the content of yourtextfile as standard input (stdin) to yourprogram. Likewise
yourprogram > yourothertextfile
will send everything the program writes to standard output (stdout) to yourothertextfile
You'll notice when reading man pages that most system calls have a version that works directly with stdin or stdout
For example consider the printf family:
printf ("hello world\n");
is a shorter version of
fprintf (stdout,"hello world\n");
and the same goes for scanf and stdin.
This is only the most basic usage of redirection, which in my opinion is one of the key aspects of "the unix way of doing things". As such, you'll find lots of articles and tutorials that show examples that are a lot more advanced than what I wrote here. Have a look at this Linux Documentation Project page on redirection to get started.
EDIT: getting fed input via redirection ior interactively "looks" the same to the program, so it will react the same to redirected input as it does to console input. This means that if your program expects data line-wise (eg because it uses gets() to read lines), the input text file should be organized in lines.
By default, every program you execute on POSIX-compliant systems has three file descriptors open (see <unistd.h> for the macros' definition): the standard input (STDOUT_FILENO), the standard output (STDOUT_FILENO), and the error output (STDERR_FILENO), which is tied to the console.
Since you said you want read lines, I believe the ssize_t getline(char **lineptr, size_t *n, FILE *stream) function can do the job. It takes a stream (FILE pointer) as a third argument, so you must either use fopen(3) to open a file, or a combination of open(2) and fdopen(3).
Getting inspiration from man 3 getline, here is a program demonstrating what you want:
#define _GNU_SOURCE
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp;
size_t len;
char *line;
ssize_t bytes_read;
len = 0;
line = NULL;
if (argc > 1)
{
fp = fopen(argv[1], "r");
if (fp == NULL)
{
perror(*argv);
exit(EXIT_FAILURE);
}
}
else
fp = stdin;
while ((bytes_read = getline(&line, &len, fp)) != -1)
printf("[%2zi] %s", bytes_read, line);
free(line);
exit(EXIT_SUCCESS);
}
Without arguments, this program reads lines from the standard input: you can either feed it lines like echo "This is a line of 31 characters" | ./a.out or execute it directly and write your input from there (finish with ^D).
With a file as an argument, it will output every line from the file, and then exit.
You can have your executable read its arguments on the command line and use xargs, the special Linux command for passing the contents of a file to a command as arguments.
An alternative to xargs is parallel.

Resources