Incorrect command line arguments number when passing `*` [duplicate] - c

This question already has answers here:
The issue of * in Command line argument
(6 answers)
Closed 3 years ago.
I'm writing a C program about Reverse Polish Notation, which takes its operands and operators through the command line arguments. But things go wrong when the multiply operator '*' occurs, and I don't know why.
Here is the little program to debug.
test.c
int main(int argc, char **argv)
{
printf("%d\n", argc);
return 0;
}
// run case result
./test a b 3
./test * 66
So why the '*' argument makes a wrong result ?

The * does a shell glob. So it'll expand to all the files in your current directory, which will be the arguments to your program, you have 65 files in your directory. You can see what's happening if you run echo *
You need to single quote the * as in ./test '*' (double quotes would work too) , this will prevent the shell expanding *. A * is given to your program in this case, the shell removes the single quotes.
If you want to evaluate expressions, you could do
./test 3 2 '*'
In this case your program receives 3 additional arguments separated so argv[1] is 3, argv[2] is 2 and argv[3] is *
Or you could do:
./test '3 2 *'
In this case, your program receives 1 additional argument, argv[1] will be the string 3 2 *

Your command shell is treating * as a wildcard. It's probably including every file in the current directory: 60ish in your case.

Related

How exactly does argc work when I don't use quotation marks?

My code is very simple :
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%d\n", argc);
return 0;
}
It prints 17 after I input
./a.out 1 2 3 + *
Shouldn't it print 6 instead? The program's behavior is as expected if I put '' around every argument except ./a.out. This is strange, because I can use some programs with flags without using quotation marks('', "").
If you don't quote or escape *, it's expanded as a wildcard by the shell when forming the program arguments. It's replaced with all the names in the current directory (except the ones that begin with .).
You must have had 12 files and subdirectories in your directory when you ran this.

command line arguments argv and argc

I understand that argc counts the number of arguments and argv takes in the argument, but is their a way I can determine if my argument from argv was inputted in a certain format like in parentheses and not in parenthesis. Such as ./a.out "Hello Word" and ./a.out Hello World?
Yes and no. Basically the only way to do this is to do a string comparison with a function like strcmp. However, one thing that complicates the matter is that the shell you are using might remove the quotes before your program has a chance to see them. To make things worse, how this is handled depends on the shell, so what works for one shell might fail for another one. Posix shells (sh, bash, ksh and so forth) handles quotes the same way and do not offer any way of detecting it.
This program:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("Number of arguments: %d\n", argc);
for(int i=0; i<argc; i++)
printf("Argument %d: %s\n", i, argv[i]);
}
yields this output for an asterisk as argument when using the shell bash:
/tmp/test$ ./a.out *
Number of arguments: 3
Argument 0: ./a.out
Argument 1: a.out
Argument 2: main.c
This is because the * expands to all files in the current directory by the shell. Quotes usually group things that would otherwise be seen as two different arguments. If you want to pass quotes to bash you can escape them.
/tmp/test$ ./a.out "Hello world"
Number of arguments: 2
Argument 0: ./a.out
Argument 1: Hello world
/tmp/test$ ./a.out \"Hello world\"
Number of arguments: 3
Argument 0: ./a.out
Argument 1: "Hello
Argument 2: world"
So the answer is unfortunately no. There is no general method to do this. Some shells might provide tools to do this, but there is no guarantee for that, and even if they do, there is no standard way to do it.

Incorrect argc value when executing with "*"

#include<stdio.h>
int main(int argc,char* argv[]){
printf("\n argc : %d \n",argc);
return 0;
}
Output:
[root#aman]# ./a.out *
argc : 8
I have passed two arguments, so the argc value has to be 2, but it is showing as 8.
I wanted to store the * in a array and compare the inputted '*' string.
I was writing a tool to remove all the entries in the list. Hence I need to verify the * from the "./a.out *" whether its inputted .
If inputted I need to do actions corresponding to it.Is there a way to use as ./a.out * and take the * the user has inputted.
Your shell is expanding * to a list of files in the current folder. Try quoting the * by enclosing it in double or single quotes.
You could have found out yourself by iterating over argv and printing all the parameters.
On a UNIX like operating system the system shell expands operators like "*" before executing the command. The * operator will list all files in the current directory and supply it as a list of parameters to your program. It is very likely that you have exactly 8 files in your working directory. Try to put the star in "*" if you really want to provide a * as input parameter to your program.
When you are running the binary, the input argv[] is considered as the number of the files present in that directory.
The * in a shell environment usually denotes all files present in that directory. Maybe using " " can be a good idea to consider the input * as you want it[string].

How to pass command line arguements to my main function? [duplicate]

This question already has answers here:
What does int argc, char *argv[] mean?
(12 answers)
Closed 9 years ago.
So my main function looks like this:
int main(int numberOfArguments, char* argumentArray[]) {
if (assemble(numberOfArguments, argumentArray)) {
return 0;
} else {
return -1;
}
}
I want to be able to give to the command line the arguement
./program inputFile.txt outputFile.txt // PROBLEM IS that this is being interpreted as 3 command line arguments somehow when it is only 2.
where inputFile.txt is argumentArray[0] and outputFile.txt is argumentArray[1]
The generation of arguments from the text command line is platform-specific, but the first element of the argv array is almost always the name used to find your program.
If you want to discard this first argument, simply add to the beginning of main:
-- numberOfArguments;
++ argumentArray;
every word you type into the command line (beginning with the executable name) is passed to the main function at begin. related question
The first argument argumentArray[0] is the as readable in the realted question reserved.
After that you get each word (seperated by whitespaces in the commandline) as an element in the argumentArray.
The size of the argumentArray is given by numberOfArguments.
So if you insist on having your input file on [0] you should work with some pointer arithmetics like argumentArray++; otherwise you have the given data at [1] and [2] automatically.

Arguments to main in C [duplicate]

This question already has answers here:
Pass arguments into C program from command line
(6 answers)
Closed 6 years ago.
I don't know what to do! I have a great understanding of C basics. Structures, file IO, strings, etc. Everything but CLA. For some reason I cant grasp the concept. Any suggestions, help, or advice. PS I am a linux user
The signature of main is:
int main(int argc, char **argv);
argc refers to the number of command line arguments passed in, which includes the actual name of the program, as invoked by the user. argv contains the actual arguments, starting with index 1. Index 0 is the program name.
So, if you ran your program like this:
./program hello world
Then:
argc would be 3.
argv[0] would be "./program".
argv[1] would be "hello".
argv[2] would be "world".
Imagine it this way
*main() is also a function which is called by something else (like another FunctioN)
*the arguments to it is decided by the FunctioN
*the second argument is an array of strings
*the first argument is a number representing the number of strings
*do something with the strings
Maybe a example program woluld help.
int main(int argc,char *argv[])
{
printf("you entered in reverse order:\n");
while(argc--)
{
printf("%s\n",argv[argc]);
}
return 0;
}
it just prints everything you enter as args in reverse order but YOU should make new programs that do something more useful.
compile it (as say hello) run it from the terminal with the arguments like
./hello am i here
then try to modify it so that it tries to check if two strings are reverses of each other or not then you will need to check if argc parameter is exactly three if anything else print an error
if(argc!=3)/*3 because even the executables name string is on argc*/
{
printf("unexpected number of arguments\n");
return -1;
}
then check if argv[2] is the reverse of argv[1]
and print the result
./hello asdf fdsa
should output
they are exact reverses of each other
the best example is a file copy program try it it's like cp
cp file1 file2
cp is the first argument (argv[0] not argv[1]) and mostly you should ignore the first argument unless you need to reference or something
if you made the cp program you understood the main args really...
For parsing command line arguments on posix systems, the standard is to use the getopt() family of library routines to handle command line arguments.
A good reference is the GNU getopt manual
Siamore, I keep seeing everyone using the command line to compile programs. I use x11 terminal from ide via code::blocks, a gnu gcc compiler on my linux box. I have never compiled a program from command line. So Siamore, if I want the programs name to be cp, do I initialize argv[0]="cp"; Cp being a string literal. And anything going to stdout goes on the command line??? The example you gave me Siamore I understood! Even though the string you entered was a few words long, it was still only one arg. Because it was encased in double quotations. So arg[0], the prog name, is actually your string literal with a new line character?? So I understand why you use if(argc!=3) print error. Because the prog name = argv[0] and there are 2 more args after that, and anymore an error has occured. What other reason would I use that? I really think that my lack of understanding about how to compile from the command line or terminal is my reason for lack understanding in this area!! Siamore, you have helped me understand cla's much better! Still don't fully understand but I am not oblivious to the concept. I'm gonna learn to compile from the terminal then re-read what you wrote. I bet, then I will fully understand! With a little more help from you lol
<>
Code that I have not written myself, but from my book.
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
printf("The following arguments were passed to main(): ");
for(i=1; i<argc; i++) printf("%s ", argv[i]);
printf("\n");
return 0;
}
This is the output:
anthony#anthony:~\Documents/C_Programming/CLA$ ./CLA hey man
The follow arguments were passed to main(): hey man
anthony#anthony:~\Documents/C_Programming/CLA$ ./CLA hi how are you doing?
The follow arguments were passed to main(): hi how are you doing?
So argv is a table of string literals, and argc is the number of them. Now argv[0] is
the name of the program. So if I type ./CLA to run the program ./CLA is argv[0]. The above
program sets the command line to take an infinite amount of arguments. I can set them to
only take 3 or 4 if I wanted. Like one or your examples showed, Siamore... if(argc!=3) printf("Some error goes here");
Thank you Siamore, couldn't have done it without you! thanks to the rest of the post for their time and effort also!
PS in case there is a problem like this in the future...you never know lol the problem was because I was using the IDE
AKA Code::Blocks. If I were to run that program above it would print the path/directory of the program. Example: ~/Documents/C/CLA.c it has to be ran from the terminal and compiled using the command line. gcc -o CLA main.c and you must be in the directory of the file.
Main is just like any other function and argc and argv are just like any other function arguments, the difference is that main is called from C Runtime and it passes the argument to main, But C Runtime is defined in c library and you cannot modify it, So if we do execute program on shell or through some IDE, we need a mechanism to pass the argument to main function so that your main function can behave differently on the runtime depending on your parameters. The parameters are argc , which gives the number of arguments and argv which is pointer to array of pointers, which holds the value as strings, this way you can pass any number of arguments without restricting it, it's the other way of implementing var args.
Had made just a small change to #anthony code so we can get nicely formatted output with argument numbers and values. Somehow easier to read on output when you have multiple arguments:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("The following arguments were passed to main():\n");
printf("argnum \t value \n");
for (int i = 0; i<argc; i++) printf("%d \t %s \n", i, argv[i]);
printf("\n");
return 0;
}
And output is similar to:
The following arguments were passed to main():
0 D:\Projects\test\vcpp\bcppcomp1\Debug\bcppcomp.exe
1 -P
2 TestHostAttoshiba
3 _http._tcp
4 local
5 80
6 MyNewArgument
7 200.124.211.235
8 type=NewHost
9 test=yes
10 result=output

Resources