Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sum all command line arguments in C?

I have an assignment. The program is to print the sum of all command line arguments in C. I tried this code it compiles but throws an error after passed arguments in the console. Below is the code.

/* Printing sum of all command line arguments */
#include <stdio.h>

int main(int argc, char *argv[]) {
    int sum = 0, counter;

    for (counter = 1; counter <= argc; counter++) {
       sum = atoi(sum) + atoi(argv[counter]);
    }
    printf("Sum of %d command line arguments is: %d\n", argc, sum);
}

After compiling it outputs a Segmentation fault (core dumped) error. Your experience may solve my problem.

Below is my edited code:

/* Printing sum of all command line arguments*/
#include <stdio.h>
#include <stdlib.h> // Added this library file

int main (int argc, char *argv[]) {
    int sum = 0, counter;

    for (counter = 1; counter < argc; counter++) {
        // Changed the arithmetic condition
        sum = sum + atoi(argv[counter]);
        // Removed the atoi from sum variable
    }
    printf("Sum of %d command line arguments is: %d\n", argc, sum);
}
like image 410
Anudeepsyamprasad Avatar asked Feb 01 '18 14:02

Anudeepsyamprasad


People also ask

How many arguments SUM () has in C?

SUM can handle up to 255 total arguments. Arguments can be supplied as constants, ranges, named ranges, or cell references.

Can I write a program to add 2 numbers given at command line and print total using C program?

printf("Enter two integers: "); scanf("%d %d", &number1, &number2); Then, these two numbers are added using the + operator, and the result is stored in the sum variable. Finally, the printf() function is used to display the sum of numbers. printf("%d + %d = %d", number1, number2, sum);

What is used for all command line arguments?

Command line arguments are passed to the main function as argc and argv. Command line arguments are used to control the program from the outside. argv[argc] is a Null pointer. The name of the program is stored in argv[0], the first command-line parameter in argv[1], and the last argument in argv[n].


2 Answers

Because you are iterating until counter == argc, you are passign a NULL pointer to atoi(), It's simple, just rely on the fact that the argv array has a NULLsentinel, and do this

/* Printing sum of all command line arguments*/
#include <stdlib.h> /* For `atoi()' */
#include <stdio.h>  /* For `printf()' */

int main(int argc, char *argv[])
{
    int sum;
    sum = 0;
    for (int counter = 1; argv[counter] != NULL; ++counter)     {
        sum += atoi(argv[counter]);
    }
    printf("Sum of %d command line arguments is: %d\n", argc, sum);
}

Note that atoi(sum) is undefined behavior because sum is an int and is not a valid pointer. While atoi() will try to dereference it. Also aoti() stands for ascii to integer and sum is already an integer so the conversion doesn't make sense.

Finally, include stdlib.h for atoi(). I know you didn't include it because I have warnings enabled on my compiler and it warned me that atoi() was implicitly defined. It might work, but just because undefined behavior is that, UNDEFINED.

Also, note that there is no way to know whether the passed argument is an integer, because atoi() cannot perform error checking. You might want to use strtol() instead and check if all the values are integers.

So ... this is how you would write a more robust version of this program

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int sum;
    sum = 0;
    for (int counter = 1; argv[counter] != NULL; ++counter)     {
        char *endptr;
        sum += strtol(argv[counter], &endptr, 10);
        if (*endptr != '\0') {
            fprintf(stderr, "error: the `%d-th' argument `%s', is not a valid integer\n", counter, argv[counter]);
            return EXIT_FAILURE;
        }
    }
    printf("sum of %d command line arguments is: %d\n", argc, sum);
    return EXIT_SUCCESS;
}

EDIT: To address this comment

There is a possibility that argc == 0, for instance if you execute the program through one of the exec*() functions. In that case you must check before starting the loop or argv[counter] will be one element after the last, i.e. out of bounds.

like image 76
Iharob Al Asimi Avatar answered Sep 23 '22 17:09

Iharob Al Asimi


It is specified that argv[argc] will always be a null pointer. You loop once too many, and pass this null pointer to atoi, leading to undefined behavior.

Change your loop conditions to be counter < argc.

And sum already is an integer, you do not need to convert it to an integer with atoi. That atoi(sum) will also lead to undefined behavior as the very first iteration will pass zero to atoi, which could be seen as a null pointer as well.

like image 23
Some programmer dude Avatar answered Sep 21 '22 17:09

Some programmer dude