What is the definition of an "argument in C" - c

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

Related

Segmentation fault when file is not found even if I try to create it in C

I'm writing a code that appends text to a file.
It uses fopen in the beginning of WriteToFile so even if the file does not exist, it creates it.
But, what happens when I enter no file at all? no arguments at all? Just ./a.out?
Segmentation fault.
I don't know why, it seems to me I did everything fine to avoid any problems.
int main(int argc, char **argv)
{
char file_name[30] = "file.txt";
printf("%s",file_name); /* for debugging : doesn't print it */
if (0 != argc)
{
strcpy(file_name, argv[1]);
}
WriteToFile(file_name);
}
OR
(in case I can't really put a string literal into char array):
char file_name[30];
if (0 == argc)
{
strcpy(file_name, "file.txt");
}
else
{
strcpy(file_name, argv[1]);
}
For both of the cases i'm getting
Segmentation fault (core dumped)
if (0 != argc)
The argc value is normally(a) the count of arguments including the program name. Hence, running ./a.out will have an argc of one rather than zero. And, since argv[argc] is usually NULL, dereferencing it is not going to end well :-)
If you want to ensure another argument is available, you can use:
if (argc > 1) { // Have both argv[0] AND argv[1].
nowSafeToUse(argv[1]);
}
In more detail, the C11 standard states:
If they are declared, the parameters to the main function shall obey the following constraints:
The value of argc shall be nonnegative.
argv[argc] shall be a null pointer.
If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup. The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment. If the host environment is not capable of supplying strings with letters in both uppercase and lowercase, the implementation shall ensure that the strings are received in lowercase.
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.
The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
As an aside regarding this line:
printf("%s",file_name); /* for debugging : doesn't print it */
If this is not printing, it's probably because standard output is line buffered (default if it's determined to be an interactive device, otherwise fully buffered).
By not outputting a \n at the end, the characters are probably still sitting in a buffer somewhere, ready to be written. The crash will probably kill off the process without flushing the buffer. So a simple solution may be just to use one of:
printf("%s",file_name);
puts(file_name);
As another aside, you're going to get into trouble if the filename you enter is larger than 29 characters since it will overflow file_name, allowing for the \0 at the end as well.
A better approach may be just to use either your default string or argv[1] directly (without copying), something like:
int main(int argc, char **argv) {
char *file_name = (argv > 1)
? argv[1]
: "file.txt";
printf("%s\n", file_name); // for debugging : probably does print it :-)
WriteToFile(file_name);
}
(a) Not required by the standard since it allows for implementation-specific differences, but it's the usual case. Specifically, the phrase:
... which are given implementation-defined values by the host environment prior to program startup. The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment.
pretty much means it can do whatever it wants :-)
A related answer (though a non-duplicate question) can be found here.
When argc is 1, argv is treated as an array of 2 pointers to char. The first is a valid pointer (typically to the program name), the second is NULL.
argv[1] accesses the second element of argv. With no arguments supplied, argc will be 1 and argv[1] will be NULL. You're therefore dereferencing a NULL pointer.
The condition 0 != argc should instead be argc >= 2 or argc > 1, and the condition 0 == argc should be argc < 2 or argc <= 1.
You have to account for the program's name so you should write if (argc >= 2) instead. See the man
The value of the argc argument is the number of command line arguments. The argv argument is a vector of C strings; its elements are the individual command line argument strings. The file name of the program being run is also included in the vector as the first element; the value of argc counts this element. A null pointer always follows the last element: argv[argc] is this null pointer.
argv[1] means index 1 but in C you start at index 0.
Fixed code
int main(int argc, char **argv)
{
char file_name[30] = "file.txt";
printf("%s",file_name); /* for debugging : doesn't print it */
if (argc >= 2)
strcpy(file_name, argv[1]);
else
return 1; // exit program with error code.
WriteToFile(file_name);
return 0; // exit with success
}

One command line argument in C

write c program that accepts one command line argument (your first name) and prompts the user for user input (your last name), then print ""Welcome to operating systems, "" to the screen.
Can anyone help me with this question? I know its using something like this from the below, but I dunno how to print out the thing? Can anyone help by giving the full answer? Thanks in advance.
int main (int argc, int *argv[])
argc is an integer that represents the number of command line arguments passed in to the program. It is the argument count, hence the name. *argv[] (or **argv depending on developer preference) represents the actual arguments. The proper name for argv is argument vector, which makes sense if you're familiar with that particular data type.
The first argument passed in, argc = 1 is the program's name. Argc is always at least one because argv will always contain at a minimum the name of the program.
To answer your question, you need to pass in a second command-line argument, argc = 2, where argv[1] equals the user's first name. We can accomplish that like this:
int main(int argc, char** argv)
{
// This line will print out how many command line arguments were passed in.
// Remember that it will always be at least one because the name of the program
// counts as an argument.
printf("argc: %d", argc);
// Remember that you want the second argument in argv,
// so you have to call argv[1] because arrays in C
// are 0-index based. Think of them as offsets.
printf("\nWelcome, %s", argv[1]);
return 0;
}
This should get you started. All you need to do now is write the code to read the string from the standard input and output it to the console.

Command line argument condition pset2 caesar

I'm just started with a course for learning C, and am bumping in a problem with command line arguments. The assignment is this (there is more, but this is the part about the command line argument at the start):
- Your program must accept a single command-line argument, a non-negative integer.
- If your program is executed without any command-line arguments or with more than one command-line argument, your program should print an error message of your choice and return 1.
- You can assume that, if a user does provide a command-line argument, it will be a non-negative integer (e.g., 1). No need to check that it’s indeed numeric.
So I came up with this code:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int main(int key, string plain[]) {
if (key < 0 || plain[key] > 1)
{
printf("error\n");
return 1;
}
else
etc...code continues.
Now I've tried several things, but I'm running into a wall.The compiler doesn't want to accept the if-condition I came up with, saying there is an error with comparison between pointer and integer which refers to the bold condition on the list of the assignment. So I understood that the argv part of the command line argument is the array of strings that the user put in. So my thought was to tell the compiler that when the user gives more than one string it should give an error message, so I wrote "plain[key] > 1)". Or is my understanding of command line arguments completely off here? Thanks.
plain[key] access the key element of plain array of string pointers (argv).
The size of that array is expressed by key (argc).
So what you want is
if (key > 1)
{
//..
}
Moreover plain last element is key-1, 'cause is 0 based index.
You misunderstood the purpose of the arguments to main. The first int argument (usually named argc) is the number of items in the array argument.
And the array argument (usually called argv) contains all the arguments to your program (including the executable name) as text.
So if your executable is called foo, and you invoked it as foo 1 a bar, the arguments to main will be as follows:
int argc == 4
char **argv => {"foo", "1", "a", "bar"}
So if your program must accept a single argument, it must hold that argc == 2 and argv[1] is the argument, that you must convert to a number from a string.

C: strcmp and stdin arguments with input size

I'm writing a program that does certain functions depending on what argv[0] corresponds to
For example.
else if(strcmp(argv[1],"wait") == 0 )
Works perfectly when I type 'wait 2', it executes the code located in that if-statement, BUT if I try to type just 'wait' (only one argument), it doesn't recognize it and doesn't go to this function.
Why is it not working, despite the fact that argv[0] DOES match 'wait'? Thank you!
argv[0] is the name of the executable.
Probable want argv[1] where (after checking argc)
argv[0] is your program name. You must type argv[1] instead.

OpenCV argc and argv confusion

I'm checking some OpenCV tutorial and found this line at the beginning (here is the link, code is under the CalcHist section http://opencv.willowgarage.com/documentation/c/histograms.html)
if (argc == 2 && (src = cvLoadImage(argv[1], 1)) != 0)
I've never seen this before and really don't understand it. I checked some Q&A regarding this subject but still don't understand it.
Could someone explain to me what is the meaning of this line?
Thanks!
The line does the following, in order:
Tests if argc == 2 - that is, if there was exactly 1 command line argument (the first "argument" is the executable name)
If so (because if argc is not 2, the short-circuiting && will abort the test without evaluating the right-hand-side), sets src to the result of cvLoadImage called on that command-line argument
Tests whether that result (and hence src) is not zero
argc and argv are the names (almost always) given to the two arguments taken by the main function in C. argc is an integer, and is equal to the number of command-line arguments present when the executable was called. argv is an array of char* (representing an array of NULL-terminated strings), containing the actual values of those command-line arguments. Logically, it contains argc entries.
Note that argc and argv always have the executable's name as the first entry, so the following command invocation:
$> my_program -i input.txt -o output.log
...will put 5 in argc, and argv will contain the five strings my_program, -i, input.txt, -o, output.log.
So your quoted if-test is checking first whether there was exactly 1 command-line argument, apart from the executable name (argc == 2). It then goes on to use that argument (cvLoadImage(argv[1], 1))
Checking argc and then using argv[n] is a common idiom, because it is unsafe to access beyond the end of the argv array.

Resources