Command Line argument in C not printing correctly - c

im trying to test how my program is receiving a users command line input:
my command line input to test is:
"./concordance 15 < input.txt"
the rest of the program works but to test the arguments. so in my main function i have this:
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < argc; i++)
{
printf("%s\n", argv[i]); //runs through command line for arg
}
printf("%d\n", argc); //prints total arguments
return 0;
}
The problem is when I enter my command line, the program prints:
./concordance
15
2
for my program to work I need to open the input.txt file so my question is, why is the program only printing "./concordance", and "15" aswell as only seeing 2 arguments if I have "<" and "input.txt" in the command line?
Thanks

< is not interpreted as a command line argument but is instead interpreted by the shell to redirect standard input to be the specified file instead of the parent standard input, typically the shell.

There is a difference between the command line and "stdin" - "15" is a command line argument. The shell sees the '<' and "redirects" the file to your program on it's stdin stream.
If you don't want to use stdin to process the file, just pass it's name and open yourself: ./concordance 15 input.txt (argv[2] will be input.txt)

Related

Why isn't redirected input considered a command line argument?

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.

Trouble redirecting .txt file to stdin

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.

Piping a file from the command line in C

I need to access a file provided to the program from the command line in the following fashion: ./myProgram < filename
I figured you could do this with command line arguments (argv and argc), but now realize that this is not the case. I was just wondering where this file is inputted to (name or otherwise) so I can access it.
Thanks in advance!
If you're in a unix shell (zsh, bash, etc.) and do something like ./myProgram <filename, the program dosn't receive <filename in argv array. Instead, the shell parses the part with < and redirects the program's input so that it come from the file filename.
More on i/o redirection here
So, you write exactly as if you were reading from stdin (because you are reading from stdin):
#include <stdio.h>
int main()
{
char str[200];
int i;
scanf("%s", str);
scanf("%d", &i);
printf("%s %d\n", str, i);
}

Executing a separated command using execvp in C

I've separated a given command from the user into substrings , here's the code :
int i;
char *line = malloc(BUFFER);
char *origLine = line;
fgets(line, 128, stdin); // get a line from stdin
// get complete diagnostics on the given string
lineData info = runDiagnostics(line);
char command[20];
sscanf(line, "%20s ", command);
line = strchr(line, ' ');
printf("The Command is: %s\n", command);
int currentCount = 0; // number of elements in the line
int *argumentsCount = &currentCount; // pointer to that
// get the elements separated
char** arguments = separateLineGetElements(line,argumentsCount);
// here we call a method that would execute the commands
if (execvp(*arguments,*argumentsCount) < 0) // execute the command
{
printf("ERROR: exec failed\n");
exit(1);
}
When I execute the command in execvp(*arguments,*argumentsCount) , it fails .
What's wrong ?
Thanks .
EDIT :
The input from the user is : ls > a.out , hence I have 3 strings , which are :
ls , > , a.out , and it fails .
Shell redirection won't work if you aren't invoking a shell. You also won't have path searching to find the ls program. Some options
use system() instead, and exit when it returns
exec a shell and have it run your command
setup redirection as a shell would, then fork and execute each required child program.
Also your command doesn't make a lot of sense, you probably want ¦ instead of > and may need to specify the directory of a.out if it is not in your path. Consider giving it a meaningful name as well.
From man page of execvp command:
int execvp(const char *file, char *const argv[]);
The second argument is a list of null-terminated C-strings as arguments to the command to be executed by execvp. But in your code, you pass an int as the second argument which is wrong.
If you have list of arguments in the variable arguments then call execvp as:
execvp(arguments[0],arguments);
When you run ls > a.out at the command-line, > and a.out are not arguments passed to the application; they're interpreted by the shell to redirect stdout.
So in short, it is not possible to do what you want to do.1
1. Well, it is, but not this way. Your application would need to interpret the arguments, create the file, and set up a stream redirect.

How to use UNIX terminal input redirection in C?

I have this C program that gets the input from the user and sends it to a method:
#include <stdio.h>
#include <string.h>
#include "constants.h"
#include "lines.h"
#include "compare.h"
//gets arguments and sends to compare.c
int main() {
int op = 1;
char filename[20];
scanf("%d ", &op);
gets(filename);
if ((char) op + '0' < 49 || (char) op + '0' > 57) {
printf("Error: Invalid input");
exit(0);
}
readstdin(filename, op);
return 0;
}
but instead of executing the program and reading from stdin, I want it to read from the unix terminal so that:
./sort [field] < input_file
will read into the file. ([field] is option if no input is put in, default is 1).
For example the command to execute the C program in UNIX would look like this:
./sort 1 < test.txt
How do I go about doing this?
Any help is much appreicated
Thanks!
For a start, you're getting your arguments the wrong way in your code. If what you're wanting is to run your program such as ./sort <option> <filename>, then you don't use stdin to retrieve these arguments.
The arguments in a C program are passed to main using the following function signature:
int main(int argc, char *argv[])
argc is the number of command line arguments passed to the program, and argv is the array of strings of those arguments.
With a run of ./sort 5 test.in:
argc will equal 3
argv[0] will be "./sort"
argv[1] will be "5"
argv[2] will be "test.in"
You should check that the value of argc is 3 to ensure that 2 arguments have been passed ("5", "test.in"), as well as the filename ("./sort") for a total of 3.
If you want to have optional fields, it would be better to have them after the compulsory ones, or better yet is to use something like getopt where you could instead have something like: ./sort --file test.in or ./sort --opt 5 --file test.in. It's probably unnecessary for this case, but it's an option.
You can parse the integer option using atoi or strtol, however you like, to convert it from a string (char*) to an integral type and fopen, fgets, fclose to read from the input file.

Resources