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.
Related
This is a sample code from a book. This program prints a given string to repeat given number of times.
#include <stdio.h>
#include <stdlib.h>
void usage(char *program_name)
{
printf("Usage: %s <nessage> <# of times to repeat>\n", program_name);
exit(1);
}
int main(int argc, char *argv[]) {
int i, count;
if(argc < 3)
usage(argv[0]);
count = atoi(argv[2]);
printf("Repeating %d times..\n", count);
for(i=0; i < count; i++)
printf("%3d - %s\n", i, argv[1]);
}
It does what it should do:
kingvon#KingVon:~/Desktop/asm$ ./convert 'Stackoverflow is the best place to ask questions about programming' 6
Repeating 6 times..
0 - Stackoverflow is the best place to ask questions about programming
1 - Stackoverflow is the best place to ask questions about programming
2 - Stackoverflow is the best place to ask questions about programming
3 - Stackoverflow is the best place to ask questions about programming
4 - Stackoverflow is the best place to ask questions about programming
5 - Stackoverflow is the best place to ask questions about programming
kingvon#KingVon:~/Desktop/asm$
Q. Now although main takes two arguments in this specific order: (int argc, char *argv[]), why is that when I ./convert 'string' (number) it works fine but other way around `./convert (number) 'string' does not work?
kingvon#KingVon:~/Desktop/asm$ ./convert 5 'Stackoverflow is the best place to ask questions about programming'
Repeating 0 times..
Q. This line
if(argc < 3) usage(argv[0]);
I have 2 questions about: This line specifies that if the integer argument given is less than 3, the program should output the usage. ./convert 'string' 2 does not print the usage? So what is happening here? Also usage takes char *program_name as an argument(what is meant by char *program_name?) But in line above is given argv[0] as an argument. Why is this and what does this do?
argc is the number of arguments on the command line, not the value of any particular argument. argv contains the actual arguments, which are passed as strings. argv[0] is the command used to invoke the program, argv[1] is the first argument, etc.
When you call the program as
./convert 'Stackoverflow ...' 6
then
argv[0] == "./convert"
argv[1] == "Stackoverflow ..."
argv[2] == "6”
argc == 3
The code assumes that the number is passed in argv[2] and uses the atoi function to convert it from a string representation of an integer to an integer value, which is why the code didn’t behave as expected when you switched the order of the arguments. If you want to be able to switch up the order of the arguments, then your code has to know how to detect which argument is which.
The argc variable is the number of elements in the argv array. And the actual command line arguments will be in the argv array.
The first argument on the command line will always be in argv[1], the second in argv[2], etc.
If you change the order when running the program, the program doesn't know about that, and will think that the string to print will still be in argv[1] and the number in argv[2]. If that's not true the program will fail to work properly.
The argc check only check the number of arguments, not their order.
The name of the program ("./convert" in your question) is always passed as argument zero, i.e. in argv[0].
I'm having some trouble reading a line of the code, and understanding what constitutes an argument in the context of this line of code. This is saved in a file called argv0.c
#include <cs50.h>
#include <stdio.h>
int main(int argc, string argv[])
{
if (argc == 2)
{
printf("hello, %s\n", argv[1]);
}
else
{
printf("hello, world\n");
}
}
I compile the code as follows:
make argv0
./argv0
following which I am prompted for an input. Herein lies the issue:
if I type in "Dion Lim" in the terminal, is Dion Lim considered an argument? If so, is it two arguments?
Why is it that if I type in "Dion Lim" in the terminal, I get "Hello, World", but if I type in "Dion" i get "Hello,Dion"
Q1) Yes, they are two arguments.
Q2) Because argc consider the name of executable it's the first parameter. So:
./argv0 Dion Lim // argc == 3
./argv0 Diom // argc == 2
./argv0 // argc == 1
You can get more detail here.
if I type in "Dion Lim" in the terminal, is Dion Lim considered an
argument? If so, is it two arguments?
It depends on how your shell handles it of course, but usually "Dion Lim" would be one argument while Dion Lim (without the quotation marks) would be two arguments. The space delimits the arguments, and with the quotes you can work around that if you want space in your input (sometimes you can also escape the space, like Dion\ Lim).
Why is it that if I type in "Dion Lim" in the terminal, I get "Hello,
World", but if I type in "Dion" i get "Hello,Dion"
The argc parameter tells you how many arguments you have (I think of it as standing for "argument count"). The program's name also counts as an argument, so if you only pass Dion, then argc will be 2 already. If you pass Dion Lim, it will be 3.
To see the number of arguments check the value argc (arguments count). There is always at least one input argument, which is the program name.
So with./argv0 Dion Lim there are three input arguments.
If you are wondering make compiles the program using Makefile so if look in the directory you from which you are running make you will find a file named Makefile containing the compilation instructions.
According to the C Standard (5.1.2.2.1 Program startup)
— If the value of argc is greater than zero, the string pointed to
by argv[0] represents the program name; argv[0][0] shall be the null
character if the program name is not available from the host
environment. If the value of argc is greater than one, the strings
pointed to by argv[1] through argv[argc-1] represent the program
parameters.
So if you "manually" supply the argument Dion then argc will be exactly equal to 2. The first program parameter will be the program name (as it is followed from the quote) and the second program parameter will be the word Dion.
If you will type Dion Lim then the host system considers them as two program parameters and together with the program name argc will be equal to 3.
However if you enclose the input Dion Lim in parentheses like "Dion Lim" then the system will consider the input as one parameter and your program will output
hello Dion Lim
How can i recognize if a parameter is passing with or without " ".
For example:
$ ./a.out "Hello I am chain of characters with spaces"
$ ./a.out Hello I am not a chain of characters with spaces
The quotes are parsed and handled by (in this case) the Linux shell.
In the first case, the shell is essentially doing this:
execl("./a.out","a.out","Hello I am chain of characters with spaces", NULL);
While in the second case, the shell is doing this:
execl("./a.out","a.out","Hello", "I", "am", "chain", "of", "characters", "with", "spaces", NULL);
Once your program gets called, the shell has already done the argument handling. All you can do at that point is to look at argc to see how many arguments you have, and to look at each inidividual argument to see if it contains spaces and handle them accordingly.
Look at argc (count of arguments). In the first case it'll be 2, in the second it'll be much higher. (2 because element 0 of argv will be a.out, element 1 will be the quoted string).
I have written this program in C which takes command line arguments and displays it along with argument count. But the arguments one more than the number of arguments typed.
#include<stdio.h>
void main(int argc, char *argv[])
{
int i=0;
for(i=0;argv[1][i]!='\0';i++)
{
if(argv[1][i]>='a' && argv[1][i]>='z')
{
argv[1][i]=argv[1][i];
}
}
printf("%s",argv[1]);
printf("\n");
printf("%d",argc);
}
The argument I pass: upper abracadabra . It gives me a count as 3. Any reason. Thanks in advance
Remember that C arrays are zero-based so valid indices run [0..argc]. Your program skips checking argv[0].
In addition to the arguments you specify, argv[0] is set to your program name (or NULL if the platform can't determine the name).
If you wanted to check the command line args, you could do something like
int i;
for (i=0; i<argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
Ever wondered what printf("%s",argv[0]) would do? C array indexing start with 0. That's the solution to your question.The argv[0] holds the program name that's being executed,and is the first argument(for eg, a.out)
Actually argv[0] holds the name of the program and uses it when your program forks a child.
Whenever you call fork() in C,it produces a child process with the same name as the parent process e.g a.out. Child takes the name of its parent from argv[0]. So every thing comes with a purpose right.
This is because argv does not hold command line arguments. It holds full command line. First one is the command and the rest are arguments.
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