I am learning the redirect symbol in Unix.I want to use redirect symbol '<' to transmit parameter for main to automatically change argv[1] in main.
Code in main is shown below
`
int main(int argc, char* argv[])
{
switch (atoi(argv[1]))
{
case 1:
.....
break;
default:
break;
}
return 0;
}
`
If i type ./a.exe 1,the main function will work in case 1 and argv[1] is 1.However, if i create a script.txt,the content of which is 1 and type ./a.exe < script.txt,case 1 will not work.And i check the argv[1] is null,which is supposed to be 1.
My code is running under Windows10 msys2 and compiler is gcc. Could anyone tell me how can i use '<' or other method.
If my understanding of '<' is wrong or there is something special for use this way to send argv[1] of main
The redirect operator is different from arguments. Actually, the redirect operator moves the content of the given file into stdin or move the output into a file. Let me explain it more. Consider the following example:
./a.out > out.txt
This redirects your stdout (printf output written into stdout for example) and writes it into out.txt.
./a.out < in.txt
This redirects in.txt into your stdin (scanf reads from stdin for example).
As you can see, these are different thing and not related to your arguments. If you want, following script reads the arg.txt and put its content as arguments for your code.
./a.out $(cat hello.txt)
Related
I know, if ran in bash, my program is supposed to able to handle arguments like (where a.out is the name of file):
$ a.out <inputFile
Does this mean that inputFile is argv[1]? If so, what is the data type of argv[1] in case I need to pass it in to some other function? Would I read it using something like:
FILE *fopen( const char * filename, const char * mode );
OR
Does that mean I have to accept input from user getchar() or something?
How do I deal with such situations?
There's two ways to receive input:
Via STDIN, which is a pre-defined filehandle (fd 0 or STDIN_FILENO) you can read from at any time.
Via command-line arguments passed by argv
The shell interprets redirection operators to adjust what STDIN actually is, so by the time the program runs the only arguments left are:
"a.out"
The redirection is gone. It's just "piped" into STDIN.
Shell operators like <, > and | are interpreted by the shell before your program is run. The same goes for interpolation like $ variables and other shell-specific functions.
The command
./a.out < inputFile
isn't passing arguments to the program, instead if does redirection.
That means the shell will set up standard input (stdin, which e.g. scanf reads from) in your program to read from the redirected file.
To pass an actual argument to the program you need to run it as:
./a.out inputFile
In this case argc will be equal to 2, and argv[1] will be the string "inputFile". Which you can then pass on to e.g. fopen.
You need to pass a path to the c program then use fopen()
Using "<" means you are redirecting standard input of your process to be read from inputFile. So, all the standard read routines (getchar(), cin << ...) can be used.
If you omit "<", then inputFile becomes command argument and it is passed as part of char* argv[] to your main. After checking argc, validating file exists etc., you can use file reading routines, like fopen.
I'm trying to read command line arguments that have been redirected from a file. The command I'm using is ./a.out < test.txt
And the contents of test.txt is: Hello world.
But the output of my program below isn't printing Hello
world. Instead it is only showing ./a.out. Why is this?
int main(int argc, char* argv[], char* envp[]) {
for (int i = 1; i < argc; i++) {
printf("%s\n", argv[i]);
}
}
The shell intercepts the redirection commands before preparing the command line for the program:
myProg <infile -t >outfile
will pass to the program
myProg -t
with stdin and stdout already rerouted before the pogram starts. So the program never sees the rediretion.
There a lot of cases, besides simple derirection:
dir > myfile.txt
Especially you can pipe output from one program to another:
dir | more
It will send output if dir command to more command. Since program launch handled by OS shell, it handles a redirection too.
Because the language is defined that way. Suppose what you say is true —
All the user input will have to come from command line arguments, but text redirected from a file can satisfy input required in different functions. This can be achieved if the input appears as command line arguments.
Consider this program:
#include <stdio.h>
int is_dict(char *word)
{
/* code to look up a dictionary */
int result = 1;
return result;
}
int main(int argc, char *argv[])
{
if(argc == 2 && is_dict(argv[1]))
printf("%s found", argv[1]);
return 0;
}
If the program is written that way to accommodate it, then the input would have to come from the command line arguments. How would you take input when it is not redirected? It would require more program overhead to detect the missing inputs.
Moreover, imagine a text file containing a million words: it is unfeasible to expect each word to arrive as an argv[n].
There are other objections too. Suppose the program prints a series of prompts for responses. The user would have to know in advance what the prompts are, to supply the answers before the prompts appear.
Lastly, if the program is run from a GUI, then all the program's input will have to be edited into its properties before it is run.
I want to redirect file to stdin
So I use .txt to test and practice. The tutorial says that redirection is like copying the content of the file to the stdin, and wrtie what should appear in the command window to another file
So, here is my code
int main(int argc, char ** argv) {
printf("%d arguments\n", argc);
for(argv; *(argv); printf("%s\n", *(argv)), argv++);
return 0;
}
in the command shell I typed $a < in.txt > out.txt
inside in.txt, the content is
Hello World
Test File
Here we go
I'm expecting the out.txt to have
4 arguments
a
Hello World
Test File
Here we go
but it turns out that it is
1 arguments
a
why the redirection from txt to stdin doesn't work?
It seems like < in.txt didn't copy the content to the console at all.
Redirecting input and output with pipes does not populate argv; it simply points stdin and stdout elsewhere, from within the execution environment. This is transparent to your program.
argv contains command-line arguments that are passed to the program itself, not the execution environment.
I am trying to pass File1.txt ">" File2.txt as terminal arguments to my program in order to override the cat command. But for some reason, the program is not working. Although the argc is 4 in above defined case but still the condition in the program is not getting true. Here is the code:
int main(int argc, char *argv[])
{
int readbytes,fp;
char buf[1024];
if(argc==2)
{
fp=open(argv[1],O_RDONLY);
dup2(0,fp);
close(fp);
readbytes=read(STDIN_FILENO,buf,1024);
write(STDOUT_FILENO,buf,readbytes);
}
if(argc==4)
{
printf("inside4");
fp=open(argv[1],O_RDONLY);
dup2(fp,0);
close(fp);
fp=open(argv[3],O_WRONLY|O_CREAT|O_TRUNC,S_IRWXU);
dup2(fp,1);
close(fp);
readbytes=read(STDIN_FILENO,buf,1024);
//printf("%c",buf);
write(STDOUT_FILENO,buf,readbytes);
}
return 0;
}
I couldn't find a solution to this issue so I leave it to experts now.What is the reason for this problem?
NOTE:
For some reason when I send ./prog File1.txt > File2.txt to program, argc==2 condition is selected, however argc is 4. Why is that?
Regards
This is likely being caused by how you are running your program. Typing
./myProg foo > bar
will instruct most shells to run myProg with argument foo and save whatever is printed to stdout in a file named bar. To pass foo, >, and bar as command line arguments, use
./myProg foo \> bar
or
./myProg 'foo' '>' 'bar'
Side note: Because piping output into a file using > is part of the shell, not a program like cat itself, you likely shouldn't have to worry about it. Just write to stdout and the shell will handle the rest.
What do you mean by the condition in the program is not getting true? Are you saying that you don't see "inside4" printed to the terminal? There are a few things to consider. First, you do no error checking. We will have to assume that all of your open and dup2 calls succeed. I would expect that "inside4" is getting printed to the end of the output file. The reason for that is simply that printf does not actually write anything. It just stores the string "inside4" in a buffer, but that buffer is not written to the output until your program exits, and by that time the underlying file descriptor has been changed to the output file. The simplest fix is to append a newline to the output, and write printf( "inside4\n" ); In the normal setup, printing a newline causes the internal buffer to be flushed. You can also explicitly flush the buffer after calling printf by calling fflush.
Let me start by saying this is associated with a homework assignment. However, this is a very small and relatively insignificant part of the assignment.
The C program receives input via command line arguments but it needs to be in the form:
$ ./program < input
How, would I go about receiving that input as a string? Each time I try to print out the 3rd argument from argv I receive this message:
input: No such file or directory.
< is a shell redirect - it is handled outside your program. What you'll see is the contents of the file name 'input' being send to your standard input stream. This is a common way for programs to operate, although they usually also handle being given a file name e.g. sed.
If I had to guess I would think the:
input: No such file or directory.
is coming from the shell, as it is unable to open the file specified: "input".
On the other hand, if you actually want the < input as arguments to your program, you can escape or quote them so the shell won't interpret them. (Escaping left as an exercise for the reader :-)).
The ./program < input syntax is a special shell syntax saying "Redirects everything in the file named input to the standard entry of the program".
To read the input, your program just have to use standard input reading functions, line fgets or scanf.
On *nix systems, there won't be a third element of argv. If you execute that command on almost any Unix-like shell, it will be similar to doing this:
cat input | ./program
So your ./program has only one element in argv, but it's stdin is the file input, so to read the file you would just read from stdin. Note that this is a perfectly valid way to design your program. Many Unix programs read from standard input if no files are given, so that you may pipe in input from other programs (or in this case, from files).
What comes after the < is not a command-line argument. The contents of the file will be piped into your program by the shell.
All you need to do is read from stdin and you'll get the contents of the file.
You need to escape the '<', otherwise shell will parse it, and program won't receive it in command-line.
If you're using bash, then:
./program '<' input
or
./program \< input
Other shells might do it differently (e.g. Windows' default, cmd.exe, uses ^ as escape character, not \).
This is a Unix shell thing. The form someprogram < somefile tells someprogram to run using somefile as its input. If you want to do something different involving the < symbol, you'll need to quote it.
The < means that the program will read it's standard input (stdin) from the named file (input). So just read from stdin (using fgets, fread, etc).
Leave off the '<'. You want command line arguments do this:
$ ./program -Dflag seven=ixnay FromDinger
In your application, try this:
int main( int argc, char **argv )
{
int i;
for( i = 0 ; i < argc ; ++i )
printf( "Arg %d = %s\n", i, argv[i] );
return 0;
}
You'll notice that the first argument is the name of the executable (at index 0), and your second argument (at index 1) will be "-Dflag"
Actually, this is a very common technique used in programming tournaments. The data your program needs is stored in a file, let's say data.txt , and then redirected to your application using the "<" on the shell, like this: ./program < data.txt
So, in your source code, what you need to do is something like this:
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string tmp;
string full_content;
while (cin >> tmp)
full_content += " "+tmp;
cout << full_content << endl;
}
.. and you'll get all the data from the file on a string (and separated by spaces).
That's one way to do it, I hope it helps.
[]'s
You can get it by reading stdin.