1

Sorry for my question, I know there are a lot similars but I didn't found any that is simple enaugh to help me.

I've started coding in C and try to solve a simple exercise: Read an integers array from command line, sum the elements using the function array_sum and print result. (input example array of 3 elements: 3 0 1 2)

int array_sum(int *array,  size_t size);
int main(int argc, char **argv){
    int sum=array_sum(argv, argc);
    printf("array_sum: %i\n", sum);
    return 0;
}

my problem is that argv is a char array and the function want an integer array. Should I convert elements one by one in a new int array? There are better ways?

3
  • 2
    Should I convert elements one by one in a new int array? Yes. Commented Feb 12, 2017 at 10:48
  • @adev 3 0 1 2 is an array of four elements is not it? Commented Feb 12, 2017 at 10:53
  • @VladfromMoscow the first element was intended the lenght of the array Commented Feb 12, 2017 at 12:34

4 Answers 4

5

argv is an array of pointers to C strings. You need to convert the strings into integers first. You can do something like this:

int array_sum(int *array,  size_t size);
int main(int argc, char **argv){
    int *num_arr = malloc((argc - 1) * sizeof *num_arr);

    for (int i = 0; i < argc - 1; ++i)
      num_arr[i] = atoi(argv[i+1]);

    int sum = array_sum(num_arr, argc - 1);
    printf("array_sum: %i\n", sum);

    free(num_arr);
    return 0;
}

The only way to make the code in main shorter is by moving the conversion loop into a separate function that returns the malloced pointer.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, there no need to use malloc because I know the array's lenght
@adev - If you refer to argc then the array length is variable, and you most certainly need malloc. Although you can get away with a variable length array if argc isn't "too big".
The call of array_sum(argv, argc) would not compile. Presumably you intended array_sum(num_arr, (size_t)argc-1).
@Peter - I did, thank you. Got distracted before finishing the example proper.
2

In your code, char *argv[] is an array of char* pointers supplied from the command line. In order to convert the numbers supplied, you can use the following:

  • atoi(), which converts string arguement to an integer type.
  • Or strtol(), which converts the initial part of a string to a long int, given a base.
  • Other special functions from C99, alot of which are described in this post.

Since atoi() has no error checking, it is best to use strtol(), which allows extensive error checking.

You should store these converted numbers in a dynamically allocated int* pointer, which will need to be allocated on the heap using malloc(), which was suggested by @StoryTeller in his answer. You could also just declare an array on the stack, such as int arr[n]. The problem arises when you want to return this array in a function, which is not possible. Using a pointer in this case would allow more flexibility for abstraction.

malloc()allocates block of memory on the heap, and returns a void* pointer to it.

Note: malloc() should always be checked, as it can return NULL. You need to also free() this pointer at the end.

Here is some example code:

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

#define BASE 10

/* Guessed that your function would look like this */
int array_sum(int *array, size_t size) {
    int sum = 0;

    for (size_t i = 0; i < size; i++) {
        sum += array[i];
    }

    return sum;
}

int main(int argc, char *argv[]) {
    int *arr = NULL;
    char *endptr = NULL;
    int check, sum;
    size_t ndigits = (size_t)argc-1;

    /* allocate pointer */
    arr = malloc(ndigits * sizeof *arr);
    if (arr == NULL) {
        fprintf(stderr, "Cannot %zu spaces for integers\n", ndigits);
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < ndigits; i++) {

        /* sufficient checking for strtol(), more can possibly be added here */
        check = strtol(argv[i+1], &endptr, BASE);
        if (endptr != argv[i+1] && *endptr == '\0') {
            arr[i] = check;
        }
    }

    sum = array_sum(arr, ndigits);

    printf("array_sum: %d\n", sum);

    /* pointer is free'd */
    free(arr);
    arr = NULL;

    return 0;
}

Example input:

$ gcc -Wall -Wextra -std=c99 -o sumcommands sumcommmands.c
$ ./sumcommands 3 2 1

Output:

array_sum: 6

Note: You can use more error checking for strtol() on the Man page.

Comments

1

Why do you need to pass an int array as argument to the function ? No need to create an extra int array when you can simply do this :

int array_sum(char **argv, int argc){
  int sum = 0;
  for(int i = 0;i < argc - 1;i++){
    sum += atoi(argv[i])
  }
  return sum;
}

2 Comments

True, but that's only viable if the requirement of using array_sum can be relaxed
yes @StoryTeller, I must use provided function. The purpose of exercise I think is the interfacing
0

You can use atoi() function to convert char ** array to **int . what i see here is each integer you type is converting into string rather than char.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.