-1

I was trying to convert a string given with only numbers separated by a space into an array of int.

int make_array(char s1[]){
    // convert string and puts result into array
    char *endp = s1;
    int sum,i;
    int len=strlen(s1);
    int *array=(int*)malloc((len)*sizeof(int));
    for(i=0;i<len;i++)
        if(s1[i]!=" ")
            array[i]=strtol(s1, &endp, 10);
        s1=endp;
    return array;

The function doesn't work because it gives me a random number. Can someone give me some advice?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Shankher
  • 21
  • 1
  • 3
  • 1
    Have a look to this page on how to split on whitespace. http://stackoverflow.com/questions/4513316/split-string-in-c-every-white-space – Flyingmath Jan 31 '16 at 15:16
  • If you give your code invalid data it will go into an infinite loop. Per the [man page](http://man7.org/linux/man-pages/man3/strtol.3.html): *`strtol()` stores the address of the first invalid character in *endptr.* So if you hit an invalid character - say `'x'` - `endp` will contain the address of that `'x'` character. – Andrew Henle Jan 31 '16 at 15:20

3 Answers3

1

This is a working version of your approach (with still one problem):

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

int * make_array(char s1[], int * arraylen){
    // convert string and puts result into array
    char *endp = s1;
    int i, j=0;
    int len=strlen(s1);
    int *array = malloc(len*sizeof(int));
    for (i=0;i<len;i++)
        if(s1[i]!=' ') {
            array[ j++ ]=strtol(s1, &endp, 10);
            s1=endp;
        }
    *arraylen = j;
    return array;
}

int main() {
        int arraylen = 0, i;
        int * array = make_array( "9 8 7 123", & arraylen );
        for ( i = 0; i < arraylen; i ++ )
                printf( "[%i]: %d\n", i, array[i] );
}

The main changes:

  • set s1 inside the if;
  • add a parameter arraylen - how else will the caller of make_array know the length of the array?
  • change the return type to int * since we're returning array.
  • compare the character s1[i] with the character ' ' (not the string " ").
  • using a separate index for the output array, since the input index counts the spaces aswell, which would end up as random entries in the output array (unless you memset( array, 0, len*sizeof(int)) first).

It outputs

[0]: 9
[1]: 8
[2]: 7
[3]: 123
[4]: 0
[5]: 0
[6]: 0

If you only expect single-digit numbers then it should work fine, but strtol reads multiple digits if they are available. If you only want to read digits, you can just:

   array[ j++ ] = s1[i] - '0';

If the numbers can have more than one digit you would do:

for (i=0;i<len;)
    if ( s1[i] == ' ')
        i++;
    else {
        array[ j++ ]=strtol(s1, &endp, 10);
        i += endp - s1;
        s1=endp;
    }

to get output

[0]: 9
[1]: 8
[2]: 7
[3]: 123
Kenney
  • 9,003
  • 15
  • 21
0

If you don't mind taking up an alternate approach, you can

  1. Copy the incoming content into a local array.
  2. use strtok() to tokenize each int using the space as delimiter.
  3. Convert the token to int and store into the int array.
  4. Continue until strtok() returns NULL.

That said, int *array=(int*)malloc((len)*sizeof(int)); is not the correct approach to calculate the number of integers in the string, anyway.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Sorry but i didn't knew another way to do it, for the part of using strtok, could it be something like this? [http://pastebin.com/56EsfSRK] – Shankher Jan 31 '16 at 15:26
  • Codes are very poorly formatted when pasted as a comment. Barely readable. Paste in pastebin or something and share the link. – Sourav Ghosh Jan 31 '16 at 15:27
0

This is how I would recommend to retrieve space separated integers :

for (int i = 0; i < len && *s1; ++i) {
    array[i] = strtol(s1, &s1, 10);
    s1 += *s1 ? 1 : 0;
}

Note that :

  1. the loop terminates when either you have scanned len-1 elements or reached the end of the string.
  2. s1 the char * to your initial text is incremented at each iteration to skip the space separator (or any single char separator). Unless you have reached the null terminator of the string.
  3. If a char is encountered that is not a number or you have more than 2 spaces between numbers this code will fail.

The way you get the size of array doesn't seem correct. You end up allocating a larger array than you want.

int len=strlen(s1);

If you have n single digit numbers space separated numbers, len will be 2*n-1. You may want an extra variable, to store how many numbers you actually found in the string.

I would also to bring your attention to the lack of braces in this part of your code :

for(i=0;i<len;i++)
    if(s1[i]!=" ")
        array[i]=strtol(s1, &endp, 10);
    s1=endp;

s1 will not be updated at each iteration, it's actually out of the body of the for loop.

Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82