Как суммировать все аргументы командной строки в C?

У меня есть задание. Программа должна напечатать сумму всех аргументов командной строки в C. Я попробовал этот код, который он компилирует, но выдает ошибку после передачи аргументов в консоли. Ниже приведен код.

/* 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);
}

После компиляции отображается ошибка Сегментация (ядро сброшено). Ваш опыт может решить мою проблему.

Ниже мой отредактированный код:

/* 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 arthematic condition
    {
       sum = sum + atoi(argv[counter]);
       //Removed the atoi from sum variable
    }
  printf("Sum of %d command line arguments is: %d\n", argc, sum);
}

5 ответов

Потому что вы итерируете до counter == argcВы - пароль NULL указатель на atoi(), Это просто, просто полагаться на то, что argv массив имеет NULLСтраж, и сделай это

/* 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);
}

Обратите внимание, что atoi(sum) неопределенное поведение, потому что sum является int и не является действительным указателем. В то время как atoi() постараюсь разыменовать это.

Наконец, включите stdlib.h для atoi(), Я знаю, что вы не включили его, потому что у меня включены предупреждения на моем компиляторе, и он предупредил меня, что atoi() был неявно определен. Это может сработать, но только потому, что неопределенное поведение - это НЕ УКАЗАНО.

Также обратите внимание, что нет способа узнать, является ли переданный аргумент целым числом, потому что atoi() не может выполнить проверку ошибок. Вы можете использовать strtol() вместо этого и проверьте, что все значения являются целыми числами.

Итак... вот как бы вы написали более надежную версию этой программы

#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;
}

РЕДАКТИРОВАТЬ: Чтобы ответить на этот комментарий

Существует вероятность того, что argc == 0Например, если вы выполняете программу через один из exec*() функции. В этом случае вы должны проверить перед началом цикла или argv[counter] будет один элемент после последнего, то есть за пределами.

Указано, что argv[argc] всегда будет нулевым указателем. Вы делаете слишком много циклов и передаете этот нулевой указатель atoi, что приводит к неопределенному поведению.

Измените ваши условия цикла, чтобы быть counter < argc,

А также sum уже является целым числом, вам не нужно преобразовывать его в целое число с atoi, Тот atoi(sum) также приведет к неопределенному поведению, так как самая первая итерация пройдет ноль в atoi, который также можно рассматривать как нулевой указатель.

Последний элемент argv определяется как NULLи первым всегда является имя программы. Поэтому вы можете уменьшить свой код до

#include "stdio.h"

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

В вашем коде поведение atoi(sum) и что сводится к argv[argc] на последней итерации будет неопределенным.

Рекурсивная версия, черт побери:)

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

int main(int argc, char **argv)
{   
    static int sum;

    if (*++argv == NULL)
        return !printf("sum: %d argc %d\n", sum, argc - 1);

    sum += atoi(*argv);
    return main(argc, argv);
}
/* My example. Should work, though untested. */
#include <stdio.h>

int main(int argc, char *argv[])
{
    int sum, index;    // Generally considered better form to put them on separate lines.
    sum = 0;

    if(argc > 1) {    
        for(index = 1; index < argc; index++) {
            sum += atoi(argv[index]);
        }
        printf("%d Command-line args\nSum = %d\n", argc, sum);
    } 
    else {
        printf("Not enough command-line args\n");
    }
}

Старайтесь изо всех сил придерживаться определенного стиля форматирования для вашего кода. Поиск руководств по стилю, если вы хотите определить свой по имени. GNU C - хорошая отправная точка. Они сделают ваш код более читабельным для вас, облегчат отладку и помогут другим понять, что в нем происходит.

Несколько исправлений для вашего вышеупомянутого кода.

/* Your code with corrections */
#include "stdio.h"

int main(int argc, char *argv[])
{
   int sum=0,counter; 
   // 1. Normally you want to give each variable it's own line. Readability is important.
   // 2. Don't initialize on declaration either. Refer to my example.
   // 3. Always add spaces between operators and at the end of statements for better readability.
    for(counter=1;counter<=argc;counter++)
    {
       // 4. atoi(sum) is unneccessary as it interprets your int sum as a const char*, 
       // which as far as I can tell should just give you back it's ascii value. 
       // It might be undefined however, so I would remove it regardless.
       // 5. Your segfault issue is because you iterate over the end of the array.
       // You try to access the [argc] value of the array (remember 0-based
       // indexing means a size val is always 1 greater than the greatest index).
       // Make 'counter<=argc' into 'counter < argc'

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

atoi () документация формы.

Будьте предупреждены, ваш код все еще будет функционировать, если вы введете символы или строки в командную строку, но поведение будет странным. atoi() преобразует символ в соответствующий ему индекс / значение десятичного символа ASCII.

Вы также можете использовать нулевое значение (argv[] всегда заканчивается значением NULL в argv[argc]), чтобы завершить итерацию. Я предпочитаю использовать предоставленный argc, хотя.

Надеюсь, это поможет вам немного. Если вы ничего не понимаете, я вырвал здесь, прокомментируйте или ищите в Интернете.

Ура!

Другие вопросы по тегам