C – Passing a variable amount of arguments to main - c

I’m not sure if this is the correct way to do this. See my code below.
I want to be able to pass a list of arguments to main, which would then get stored in another array.
So, I want to be about to start the program with at least 1 argument… or as many arguments as I like. I might set a max amount of arguments to 32.
Eg.
./foo 3
Or
./foo 3 56 12 34 56 111 2222 33
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
int numbersEntered[argc];
if (argc <= 1){
printf("Not enough arguments entered\n");
exit(1);
}
printf("Arg count %i\n",argc-1);
for (i=1;i<argc;i++)
numbersEntered[i]=atoi(argv[i]);
for (i=1;i<argc;i++)
printf(" numbersEntered %i\n", numbersEntered[i]);
}

That is already the case, argv is an array of pointers, one pointer for each argument on the command line (plus two, actually, the first one is the name of the program, then the arguments, and then a terminating NULL-pointer).
Regarding the array, the problem is that traditional C requires a size that is known at compile time, you can't just use argc; that said, some compilers like GCC, and more recent C standards, do allow it.

Related

How do I deal with segfault ? C language

Suppose we are given a task to write a function that add 2 numbers.
#include <stdio.h>
int main(int argc, char ** av) {
int a = atoi(av[1]);
int b = atoi(av[2]);
add_and_print(a, b)
return 0;
}
It works fine untill I pass following code:
./a.out
Just passing empty strings. Then it writes the following:
1495 segmentation fault (core dumped)
Could you please explain what is the problem and how do I deal with it ?
argc contains the number of arguments provided to the program, and if you don't check it then you might get a segfault trying to read from argv. You can display an error message and exit if there aren't enough arguments:
if (argc < 3) {
puts("Please provide 2 numbers as command line arguments.");
return 1;
}
How do I deal with segfault
The segfault happens because of a bug in your code.
So, you prevent it happening in the first place, by not writing buggy code.
In general though, the segfault makes it easy to find out exactly what bug triggered it: just run your program under the debugger, and it will stop exactly where the segfault occurs.
Could you please explain what is the problem
In this code:
int a = atoi(av[1]);
the expression av[1] is only legal if there are at least two elements in array av (since we start indexing at zero). If there is only one element, this code attempts to read beyond the end of the array.
Since the array is based on the command-line arguments, you must check it. You need to do this for all inputs from users, files, even other parts of your own code. Don't just assume the user did what you expected (or the file contained what you expected, or the caller passed the right values). This is a bug.
if (argc >= 2) {
// now it is safe to refer to av[1]
a = atoi(av[1]);
}
You have to do something similar for av[2], for the same reason.
A common solution might be instead
int main(int argc, char **argv) {
if (argc < 3) {
printf("Syntax: %s a b\n"
"\n"
"Two integer arguments are required.", argv[0]);
return -1;
}
int a = atoi(argv[1]);
int b = atoi(argv[2]);
add_and_print(a, b)
}
I'm just assuming that argc is at least 1, and that argv[0] is the name of the program. You can check this too if you want perfectly portable code.
Note that you might also want to check whether the arguments are really integers.

Pass argument to main function with command line but the value is always 2

This is my main function code
os2.c
#include <stdio.h>
int main( int argc, char *argv[]){
int item;
item = argc;
printf("%d", item);
return 0;
}
I run the following command line in Ubuntu's terminal
gcc -o test os2.c
./test 5
The result printed is equal to 2 instead of 5, What's wrong with my code?
First, your question is not just for Ubuntu/Linux.
It works in Windows and Macintosh too including every OS using the terminal.
argc = argument count: the number of argument that are passed to a program
argv = argument vector: passed arguments
argc is an int that count the arguments of your command line.
I run the following command line in Ubuntu's terminal: gcc -o test os2.c
./test 5
Here your arguments are
argv[0] == ./test
argv[1] == 5
So we conclude that:
argc is 2 based on the number of arguments above.
argv contains the arguments that we've passed to the program.
This is an example of how you use arguments in the right way:
source.c
#include <stdio.h>
int main(int argc, char **argv){
for(int i = 0;i < argc;i++)
printf("arg %d : %s\n",i,argv[i]);
return 0;
}
Command Line
gcc -o test source.c
./test this is a test
Output
arg 0 : ./test
arg 1 : this
arg 2 : is
arg 3 : a
arg 4 : test
But anyways, I recommend to never use the first argument; It'd be a gap in your software cause it can be hacked easily. There're many ways to do whatever you want in C.
Now; You should know what you've to do if you want to get the value 5 instead of counting the number of arguments that you've passed to your application which in the OP case were 2.
argc means the number of argument that are passed to the program. not printed which value you have passed.
Use argv[1] to print value of 5.
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc >= 2)
printf("%d\n", atoi(argv[1]));
return(0);
}
argc (argument count) and argv (argument vector) are how command line arguments are passed to main() in C and C++.
argc is number of arguments passed to program (number of strings pointed to by argv), which is correct in your case. First string is program name, second string is "5" (so you have to convert "5" to int).
This might be a useful reading for you.
If you want to convert second argument to int try this
if (argc < 2)
{
return -1;
}
int item = atoi(argv[1]);
atoi may lead to undefined behavior so you should use strtol instead.
Or you may loop through all arguments
for(int i = 0; i < argc; i++)
{
// argv[i] is the argument at index i
// You may print them
printf("%s", argv[i]);
// Convert them, ...
}
Nothing wrong with code. You are passing two arguments ./test and 5. So it shows 2. It is the number of arguments passed to the program.
argc : argument count.
To get the argument passed you can do this.
printf("%s",argv[1]);
In general you check it like this:
if(argc!=2)
{
printf("Usage: ./program-name argument\n");
return EXIT_FAILURE; // failure-considering you are writing this in main.
}
// do your work here.
But in argv[1] you will get the char string. To get an integer out of it, you have to convert it using something like atoi or your custom conversion function. Also you can use strtol() which is useful in conversion from string to long.
1. In case of main return EXIT_FAILURE works but not in other functions but exit(EXIT_FAILURE) works in all the functions
argc is the count of arguments, which is 2 here. If you intend to print 5, you need to print argv[1] (or if you always want the last argument, argv[argc-1]) instead.

How do I write a program in C that counts the number of numbers as an argument?

I'm just toying with the
int main(int argc, int *argv[void])
function, and im trying to make a program that reads the number of number arguments.
Theoretically (in my own crazy delusional mind), this should work:
#include <stdio.h>
int main(int argc, char *argv[])
{
int count;
printf("%d\n", sizeof(int));
}
but no matter what i put as the argument in the command line, i always get 4 (4 bytes in a word?)
How can I tweak this code a little so that when i type
./program 9 8 2 7 4 3 1
i get:
7
much appreciated!
argc represents the number of command line arguments passed in. You can use that as an index into the second argument to main, argv. If you want all the arguments not including the first one (the program name), then you'll need to decrement argc, and increment argv.
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
/*
* forget about the program name.
*/
argv++;
argc--;
int i;
unsigned int totalNumbers = 0;
printf("Total number of arguments: %d\n", argc);
for(i = 0; i < argc; i++) {
printf("argv[%d]=%s\n", i, argv[i]);
errno = 0;
long num = strtol(argv[i], NULL, 10);
if(!(num == 0L && errno == EINVAL))
totalNumbers++;
}
printf("Total number of numeric arguments: %u\n",
totalNumbers);
return 0;
}
As others have pointed out in the comments, sizeof doesn't do quite what you think it does.
You are given argc and argv. The second of these is an array of string corresponding to the things on the command line. This argv array of strings is argc long, and the first element of it is likely to hold the name of the executable program.
You need to loop through the remaining elements of argv (if there are any) and see which ones are numbers, as opposed to non-numbers.
To check if a string is a number or not, we can use strtol() (from stdlib.h) to try to convert it into a long. If the conversion fails, it's not a number. If you'd like to accept floating point values, then use strtod() instead, it works almost in the same way (doesn't take the last argument that strtol() does). EDIT: I actually changed the code to use strtod() instead since it accepts a larger variety of "numbers".
The conversion fails if the string is empty from the start, or if the pointer that we supply to the function (endptr) doesn't point to the very end of the string after calling it.
Then, if the argument is a number, simply count it, and at the end tell the user what he or she probably already knew.
What you're doing here is called validating user input and it's a really good thing to know how to do. Don't trust users to give you numbers just because you ask them to. Check to see if they really are numbers by reading in strings and trying to convert them.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
bool is_number(const char *string)
{
char *endptr;
strtod(string, &endptr);
return (*string != '\0' && *endptr == '\0');
}
int main(int argc, char **argv)
{
int i;
int numcount = 0;
for (i = 1; i < argc; ++i) {
if (is_number(argv[i]))
numcount++;
}
printf("There were %d numbers on the command line\n", numcount);
return EXIT_SUCCESS;
}
Running it:
$ /a.out 1 2 3 a b c -.5 +20 1e20
There were 6 numbers on the command line
$ ./a.out nt 12 ,e2 2 21n 1 -8
There were 4 numbers on the command line

Reading integers into a ADT from stdin

This is my abstract data structure
typedef struct {
int *items;
int size;
} List;
I would like the user to enter integers on a single line such as
a.out
12 14 2 8 9
and read them into the List. I understand how to add to a list, i guess the thing i don't get is getting the integers from a single line input
Edit: Sorry but I meant using something like scanf not with command line arguments
1. Definition of your main should be int main(int argc,char **argv)
2. The numbers will command line arguments (check value of argc greater than 1 before using argv ).
3. argv[1] , argv[2] will have these numbers , but as string .
4. Convert these to integers using atoi or sscanf functions and store in structure members as you desire.
EDIT
Edit: Sorry but I meant using something like scanf not with command line arguments
You can use fgets , tokenize string using strtok and then convert and store into integer variable.
You have to use input arguments like:
Your main function will look like: int main (int argc, char *argv[] )
In this case you can add your argument at command line as you would
./a.out 12 14 2 8 9
And you can access those argument by argv[1], argv[2], argv[3], ...
and you can loop over the number of arguments the user provided which is contained in the argc variable
example to access the first argument:
int i;
i= atoi(argv[1]);

How to read in numbers as command arguments?

How can make it where the program reads any two integers input before the program is run?
I want the output to look like this, with x and y being any variables typed in (I am using Cygwin):
$ ./a x y
product of x and y
sum of x and y
I used int main(int argc, char *argv[]). I tried to assign argv[2] to x and argv[3] to y, but when I compile the program it says assignment makes integer from pointer without cast. What does this mean and how do I fix it?
Assuming the C language:
Command line arguments are found in the argv array - argv[1], argv[2] etc.
Converting a string argument to an integer can be done with the atoi function.
Output can be done with the printf function.
[Trying to teach you to fish, rather than providing a fish. Good luck!]
Assuming that you are using bash, you can use $1, $2, etc for those arguments. If, however, you are useing C, you're code should looks something more like this:
#include <stdio.h>
#include <stdlib.h>
main(int argc, char *argv[]) {
if(argc<=1) {
printf("You did not feed me arguments, I will die now :( ...");
exit(1);
} //otherwise continue on our merry way....
int arg1 = atoi(argv[1]); //argv[0] is the program name
//atoi = ascii to int
//Lets get a-crackin!
}
Hope this helps.
Firstly, if you run your C program as
./a x y
then a is argv[0], x is argv[1], and y is argv[2], since C arrays are 0 based (i.e. the first item in the array is indexed with 0.
Realize that argv is an array (or I've always thought of it as an ARGument Vector, though you might think of it as an array of ARGument Values) of character string pointers. So, you need to convert the strings to integers. Fortunately, C has library functions to convert ASCII to integer. Look at the stdlib.h documentation.
Good luck!
My code would look like this.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
// argc is number of arguments given including a.out in command line
// argv is a list of string containing command line arguments
int total = 0;
int i;
char *value;
for(i = 1; i < argc; i++)
{
// The integers given is read as (char *)
value = argv[i];
printf("Command line index: %d value: %s in ascii: %d\n", i, value, *value);
// Convert ascii to integer.
// atoi function is defined in stdlib.h
total += atoi(value);
}
// .2f limits the decimals to two digits after '.'
printf("Total of given integers is %d\n", total);
}
int arg1 = argv[1];
Will not work because it is an array of pointers which holds all the addresses of argv[0]....argv[n] to get the value of argv[..] suppose argv[1] you have to write:
int n=*argv[1]-'0'; // Direct atoi
Simply using atoi() will convert the char type console input into int
int main(argc, char* argv[])
{
int first = atoi(argv[1]);
printf("%i", first);
}
If you ask why argv[1] instead argv[0], the answer is the first ever argument is the name of your executable file ./some 2 int this case argv[0] will point to 'some'.
In command line arguments, char*argv[] is string type. We need to convert it into integers. We do this by type casting but in oop we do this by the atoi function(method), it works like typecasting(means method of convert one data type to other)

Resources