Reputation: 23
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?
Upvotes: 1
Views: 2474
Reputation: 26315
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.strtol()
, which converts the initial part of a string to a long int
, given a base. 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 avoid*
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
.
Upvotes: 2
Reputation: 170044
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 malloc
ed pointer.
Upvotes: 5
Reputation: 8564
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;
}
Upvotes: 1
Reputation: 1961
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.
Upvotes: 0