Как суммировать все аргументы командной строки в 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() преобразует символ в соответствующий ему индекс / значение десятичного символа ASCII.
Вы также можете использовать нулевое значение (argv[] всегда заканчивается значением NULL в argv[argc]), чтобы завершить итерацию. Я предпочитаю использовать предоставленный argc, хотя.
Надеюсь, это поможет вам немного. Если вы ничего не понимаете, я вырвал здесь, прокомментируйте или ищите в Интернете.
Ура!