How to pass ints and char variables to function in command line - c

I wrote a function where you pass two integers and an operator character (+-*/) and give a result of the two numbers. The code takes the character and checks it using its ascii value. If I pass a number in place of the operator (42 instead of *) then it works, but I don't know how to pass it as a char because the function has int argc and int * argv parameters (the function prototype was written by an instructor.) How do I make it so I can pass the char straight from the command line?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int result;
int main(int argc, char *argv[]){
printf("main_add pid: %d\n", getpid());
int a = 0;
int b = 0;
char c;
//printf("%s\n", argv[1]);
//printf("%s\n", argv[2]);
//printf("%s\n", argv[3]);
a = atoi(argv[1]);
b = atoi(argv[2]);
c = atoi(argv[3]);
if (c=='*'){
result = a * b;
printf("%d * %d = %d\n", a, b, result);
}
else if(c=='+'){
result = a + b;
printf("%d + %d = %d\n", a, b, result);
}
else if(c=='-'){
result = a - b;
printf("%d - %d = %d\n", a, b, result);
}
else if(c=='/'){
result = a / b;
printf("%d / %d = %d\n", a, b, result);
}
else{
printf("fail");
}
}
```[enter image description here][2]
[1]: https://i.stack.imgur.com/X0eiN.png
[2]: https://i.stack.imgur.com/ij5FR.png

the function has int argc and int * argv parameters (the function prototype was written by an instructor.)
That was not written by an instructor, in the sense of having been devised by one of your instructors. int main(int argc, char *argv[]) is one of only two standard variants for the signature of the entry point to a C program, and the only one of them that provides for handling command-line arguments.
How do I make it so I can pass the char straight from the command line?
Your program already receives character data from the command line, in the form of C strings. Why else do you think it makes sense to convert some of those strings to numbers via atoi()?
But what purpose do you think is served by applying atoi() to an argument that you do not expect to have the form of a numeric string? That is exactly what produces ...
If I pass a number in place of the operator (42 instead of *) then it works
... which is not what you want.
The argv array contains pointers to strings from which the characters of the command-line arguments can be read. If you want to read the characters of the arguments then do so directly. For example,
c = argv[3][0];
You would be wise, however, to first verify, by checking the value of argv, that at least 3 arguments were actually passed. Since argv also provides the program name, that means you're looking for argv to be at least 4.

The C standard defines only two valid declarations for the main function. They are int main(void), which is for programs that do not accept command-line inputs and int main(int args, char *argv[]) for programs that do.
In the second case int args will represent the number of elements in the C-string array char *argv[], which is an array of pointers to C-string representations of each of the arguments. As to the how do I pass a character to my program directly from the command line question, you are forced to use the string representation, but this is of little consequence.
Let's assume you compile the program and call it "calculator.elf"
If you were to run: ./calculator.elf 2 7 *
Your main function would be informed of these arguments by being passed a args with the value 4, and an argv[] with four pointers to C strings. The first one would be "./calculator.elf", the second "2", the third "7", and the fourth "*".
You are correct by looking in indices 1, 2 and 3 to look for your arguments because you have no need for the name of your program as an argument, and atoi("2") and atoi("7") should give you 2 and 7 respectively, but atoi("*") is not going to give you a useful result because "*" is not a numerical string.
Keep in mind that "*" is a string, not a single character, so argv[3] is going to be a pointer to a '*' character which is immediately followed by a '\0' character.
A valid check to see if you were passed "*" in argv[3] would be strcmp(argv[3],"*") == 0 or argv[3][0] == '*' && argv[3][1] == '\0', but atoi(argv[3]) should return 0 in accordance with the C specification for atoi in the case that it is passed a pointer to a non-numerical string

Related

How do you convert parameters from char to int in the main function for C?

I have this code:
int main(int argc, char *argv[]) {
int num = *argv[1];
When I run the function in terminal with a parameter: for example, if I were to call ./main 17, I want num = 17. However, with this code, num = 49 (ASCII value for 1 because argv is an array of characters). How would I get it to read num = 17 as an int? Playing around with the code, I can get it to convert the parameter into an int, but it will still only read/convert the first value (1 instead of 17).
I'm new to C and the concept of pointers/pointers to arrays is still confusing to me. Shouldn't *argv[1] return the value of the second char in the array? Why does it read the first value of the second char in the array instead?
Thanks for help!
How do you convert parameters from char to int?
Can be done by a simple cast (promotion), but this isn't your case.
In your case *argv[] is array of pointer to char (You can use this for breaking down complex C declarations), meaning that argv[1] is the 2nd element in the array, i.e. the 2nd char* in the array, meaning *argv[1] is the first char in the 2nd char* in the array.
To show it more clearly, assume argv holds 2 string {"good", "day"}. argv[1] is "day" and *argv[1] is 'd' (note the difference in types - char vs char*!)
Now, you are left with the 1st char in your input string i.e. '1'. Its ascii is indeed 49 as, so in order to get it's "int" value you should use atoi like this:
int i = atoi("17");
BUT atoi gets const char * so providing it with 17 is a good idea while sending it a char would not. This means atoi should get argv[1] instead of *argv[1]
int main(int argc, char *argv[]) {
int num = atoi(argv[1]);
// not : int num = *argv[1]; --> simple promotion that would take the ascii value of '1' :(
// and not: int num = atoi(*argv[1]); --> argument is char
note: atoi is considered obsolete so you may want to use long int strtol(const char *str, char **endptr, int base) but for a simple example I preferred using atoi
Shouldn't *argv[1] return the value of the second char in the array?
Look at the signature:
int main(int argc, char *argv[])
Here, argv is an array ([]) of pointers (*) to char. So argv[1] is the second pointer in this array. It points to the first argument given at the command line. argv[0] is reserved for the name of the program itself. Although this can also be any string, the name of the program is put there by convention (shells do this).
If you just dereference a pointer, you get the value it points to, so *argv[1] will give you the first character of the first argument. You could write it as argv[1][0], they're equivalent. To get the second character of the first argument, you'd write argv[1][1].
An important thing to note here is that you can never pass an array to a function in C. The signature above shows an array type, but C automatically adjusts array types to pointer types in function declarations. This results in the following declaration:
int main(int argc, char **argv)
The indexing operator ([]) in C works in terms of pointer arithmetics: a[x] is equivalent to *(a+x). The identifier of an array is evaluated as a pointer to the first array element in most contexts (exceptions include the sizeof operator). Therefore indexing works the same, no matter whether a is an array or a pointer. That's why you can treat argv very similar to an array.
Addressing your "core" problem: You will always have strings in argv and you want numeric input, this means you have to convert a string to a number. There are already functions doing this. A very simple one is atoi(), you can use it like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2)
{
// use program name in argv[0] for error message:
fprintf(stderr, "Usage: %s [number]\n", argv[0]);
return EXIT_FAILURE;
}
int i = atoi(argv[1]);
printf("Argument is %d.\n", i);
return EXIT_SUCCESS;
}
This will give you 0 if the argument couldn't be parsed as a number and some indeterminate value if it overflows your int. In cases where you have to make sure the argument is a valid integer, you could use strtol() instead (note it converts to long, not int, and it can handle different bases, so we have to pass 10 for decimal):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char **argv)
{
if (argc != 2)
{
// use program name in argv[0] for error message:
fprintf(stderr, "Usage: %s [number]\n", argv[0]);
return EXIT_FAILURE;
}
errno = 0; // reset error number
char *endptr; // this will point to the first character not read by strtol
long i = strtol(argv[1], &endptr, 10);
if (errno == ERANGE)
{
fprintf(stderr, "This number is too small or too large.\n");
return EXIT_FAILURE;
}
else if (endptr == argv[1])
{
// no character was converted. This also catches the case of an empty argument
fprintf(stderr, "The argument was not a number.\n");
return EXIT_FAILURE;
}
else if (*endptr)
{
// endptr doesn't point to NUL, so there were characters not converted
fprintf(stderr, "Unexpected characters in number.\n");
return EXIT_FAILURE;
}
printf("You entered %ld.\n", i);
return EXIT_SUCCESS;
}
I'm new to C and the concept of pointers/pointers to arrays is still confusing to me.
In C strings are represented by null terminated ('\0') character arrays. Let's consider the following example:
char str[] = "Hello world!"
The characters would lie contiguous in memory and the usage of str would decay to a character pointer (char*) that points to the first element of the string. The address of (&) the first element taken by &str[0] would also point to that address:
| . | . | . | H | e | l | l | o | | W | o | r | l | d | ! | \0 | . | . | . |
^ ^
str null terminator
Shouldn't *argv[1] return the value of the second char in the array?
First of all in the argv is an array of character pointer char* argv[], so that it could be interpreted like an array of strings.
The first string argv[0] is the program name of the program itself and after that the arguments that are passed are coming:
argv[0] contains a pointer to the string: "program name"
argv[1] contains a pointer to the argument: "17"
If you dereference argv[1] with the use of * you get the first character at that address, here 1 which is 49 decimal in the Ascii code. Example:
p r ("program name")
^ ^
argv[0] (argv[0] + 1)
--------------------------------------------
1 7 ("17")
^ ^
argv[1] (argv[1] + 1)
How would I get it to read num = 17 as an int?
Check the number of passed arguments with argc which contains also the program name as one (read here more about argc and argv). If there are 2 you can use strtol() to convert argv[1] to the an integer. Use strtol() over atoi() because atoi() is considered to be deprecated because there is no error checking available. If atoi() fails it simply returns 0 as integer instead of strtol() that is setting the second argument and the global errno variable to a specific value.
The followig code will use the pointer that strtol() set the second argument to, to check for conversion errors. There are also overflow and underflow errors to check like it's described here on SO. Moreover you have to check if the returned long value would fit into an int variable if you want to store it into an int variable. But for simplicity I've left that out:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{
/* At least 1 argument passed? */
if (argc >= 2)
{
char* endptr;
long num = strtol(argv[1], &endptr, 10);
/* Were characters consumed? */
if (argv[1] != endptr)
{
printf("Entered number: %ld\n", num);
}
else
{
printf("Entered argument was not a number!\n");
}
}
else
{
printf("Usage: %s [number]!\n", argv[0]);
}
return 0;
}
Here's what you want to do:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv []) {
int num = atoi (argv[1]);
printf ("Here's what you gave me: %d", num);
return 0;
}
Here's the documentation for atoi ().
argv is an array of strings, so argv[x] points to a string. atoi () accepts an ASCII string as input and returns an int.
Bonus: This is still a bit unsafe. Try running this program without passing it a parameter and see what happens.
Also, you must take a look at the documentation for strtol (), which is a safe way of doing this.

compare two numbers in c using char and strcmp

I am trying to compare two set of data using strcmp. This first set of data are var1 which is get from fgets(var1, 100, stdin). The second set of data are generate randomly by rand. When I complie it, I get two same errors. They both come from char f.
warning: assignment makes pointer from integer without a cast printf(f);
warning:assignment makes pointer from integer without a cast if (strcmp(var1,f)==0)
i already declare the randomly generated number char f = rand() % 38; in char, why will it not work?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main()
{
char var1[100];
int result;
fgets(var1, 100, stdin);
srand(time(NULL));
char myArray[38] = { 1,5,3,4};
char f = rand() % 38;
printf(var1);
printf(f);
if (strcmp(var1,f)==0) {
result = 1;
printf("It work\n");
}
else {
printf("It didn't work!\n");
result = 0;
}
return 0;
}
EDITED CODE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main()
{
char var1[100];
int result;
scanf("%s",var1);
srand(time(NULL));
char myArray[7] = { 0,28,9,26,30,11,7 };
int randomindex= 1 + (rand() % 100);
char f = myArray[randomindex];
char str_f[2] = { f, '\0' };
printf("var1: %s\n",var1);
printf("%s",str_f);
printf("\n");
if (strcmp(var1,str_f)==0) {
result = 1;
printf("It work\n");
}
else {
printf("It didn't work!\n");
result = 0;
}
return 0;
}
As commented above, in C Langage, functions from Library have a strict format and using not that expected format will occur warning or error at compilation time or runtime.
Function 1 - the printf() is the common function to write C strings to the standard output stdout (declared in <stdio.h>).
See the C library function - printf()
int printf(const char *format, ...)
In the provided source code, the printf() function has been used in the following cases:
printf("It work\n"); to write a fixed string which complies with the const char * expected format of the first parameter ==> OK,
printf(var1); to write the content of the entered string var1 (declared as char var1[100];) which not exactly complies with const char * of the first parameter but will be cast during compile time. A proposed format to write the var1 string could be printf("%s",var1); (or more verbose printf("var1: %s",var1);) where the first parameter "%s" will specify that the following argument var1 will be a string.
printf(f); to write the content of the random value (declared as char f;) which doesn't comply with const char * of the first parameter and doesn't compile at all. The minimal expected format to write the f character is printf("%c",f); (or more verbose printf("f=%c",f);) where the first parameter "%c" will specify that the following argument f will be a character.
Function 2 - the strcmp() is a function to compare two C strings parameters (declared in <string.h>.
See the C library function - strcmp()
int strcmp(const char *str1, const char *str2)
In the provided source code, the strcmp() function has not been used as specified. The function expects two input parameters:
First parameter of strcmp(var1,...)==0 is var1 (declared as char var1[100];) which not exactly complies with const char * but will be cast during compile time.
Second parameter of strcmp(...,f)==0 is f (declared as char f;) which doesn't comply with const char * and doesn't compile at all.
To compare the character f with var1, it shall be necessary to
convert it to a string (In C, a string is an array of char ended by
a character).
Solution 1 - how to convert the character char f; to a string.
A C string is an array of characters: char str_f[]= { '<char>', ... , '<NUL>' };. Meaning that a minimal array of 2 characters is necessary to convert the character char f; to a string.
char f = rand() % 38;
// use a 2 characters string
char str_f[2] = { f, '\0' };
// Could be also initialised as str_f[0] = f; str_f[1] = '\0';
// compare the strings using `str_f`
if (strcmp(var1,str_f)==0) {
Warning 1 - be careful to the random value range.
When printing characters, a C string is supposed to be filled by ASCII
characters different from which is used to end the string.
In the provided source code, the assignment of f, char f = rand() % 38;, will generate values from 0 to 37 which include the character and the first 31 non-printable characters (ctrl-characters). Only characters greater than 31 will be displayed.
In will be more easy to generate: char f = ' ' + (rand() % 38);
where ' ' is the first printable ASCII character = 32.

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

compare char with int in loop

my program is taking an argument which says how many prints that should be used.
example of arguments: prints 2.
I then want to loop through the value after prints, the number 2. and then print that many times. I tried like this:
for(i = 0; i < argv[2]; i++)
{
....
The problem is that argv is a char and i is an int. So when I run this loop, argv[2] aquire the value: 123123123 or something, instead of just 2. Is there any way around this or to compare the value in a char with an int. Thanks in advance
argv[2] is a char* not a char. argv[2] points to a string( array of null terminated characters ). When you pass an arguments to you program, the argument is in that form.
You will have to convert it, you can use atoi() ;
argv[2] is char*, is string in C language, if you want to change it to int, you must
convert it. Convert String to int.
Here is an example:
int atoi(char *str){//Just suit for int
int ans = 0,i=0;
while(str[i]){
ans = ans*10 + (str[i]-'0');
i++;
}
return ans;
}
You can call it like this atoi(argv[2]);

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