1

I have a string, like "101 1 13" and I need to split it to a int aux[3] --> resulting in aux[0] = 101, aux[1] = 1 and aux[2] = 13 (in this case). How can I do that?

In the example of the code below I get op as a String and want to get the value of the INTs in there. Each int is divided in the string by a white space(" ").

Another detail: I need the code to compile with flag -std=c99, so the answer that was accepted would not work.

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


//example of str = "101 1 14" (char *)
// example of output = {101, 1, 14}(int *)
 int* stoi(char *str) {
     // function to split str into 3 ints

}
    int main() {
        char op[10];
        int num[3];

        scanf("%s\n", op);

        num = stoi(op);
        printf("%d %d %d", num[0], num[1], num[2]); 

        return 0;
    }
lcsvcn
  • 1,184
  • 3
  • 13
  • 28
  • Are you sure `scanf()` is not getting hung up with a carriage return? – ryyker Feb 29 '16 at 20:36
  • `strncpy` is your friend. (e.g. `strncpy (tmp, str, 3)` and then either `aux[0] = atoi (tmp);` or `aux[0] = (int)strtol (tmp, NULL, 10);`. Or, `scanf`. Also See: [**Do I cast the result of malloc?**](http://stackoverflow.com/q/605845/995714) – David C. Rankin Feb 29 '16 at 20:37
  • `scanf("%s\n", op); while(op != EOF) ...` `EOF` is a possible return value of `scanf`, not a possible value for a conversion. That should read `while (scanf("%s\n", op) == 1) ...`. Also, `op` is six chars long, which can hold up to five characters. Your example string won't fit. What's more, you'll likely experience buffer overflow. – M Oehm Feb 29 '16 at 20:39
  • String to 3 `int`: `if (3 == sscanf(buf,"%d%d%d", &aux[0],&aux[1],&aux[2])) puts("Success");` is a good start. – chux - Reinstate Monica Feb 29 '16 at 20:47
  • @ryyker You are correct. Errant comment removed. – chux - Reinstate Monica Feb 29 '16 at 20:47
  • I see that you have edited your question. The function signature that you propose isn't ideal. I suggest to use `int stoi3(int res[], const char *str)` where the number of integers that were actually read is returned. Your design means that you have to use either a static buffer or dynamically allocated memory, which is cumbersome. – M Oehm Feb 29 '16 at 20:48

5 Answers5

2

First you need to tokenize your input (break apart the input into distinct elements). Then you need to parse/integerize the individual tokens by converting them from strings to the desired format.


Sample Code


#include <stdio.h>
#include <string.h>
#define BUF_LEN     (64)

int main(void)
{
    char buf[BUF_LEN] = { 0 };
    char* rest = buf;
    char* token;
    int i = 0;
    int iArr[100] = { 0 };

    if ( fgets(buf, BUF_LEN, stdin) != NULL )
    {
        strtok(buf, "\n"); // Remove newline from input buffer in case we want to call fgets() again.
        while ( (token = strtok_r(rest, " ", &rest)) != NULL )
        {
            iArr[i] = strtol(token, NULL, 10);
            printf("Token %d:[%d].\n", i, iArr[i]);
            i++;
        }
    }

    return 0;
}

Sample Run


1231 12312 312 1232 1312
Token 0:[1231].
Token 1:[12312].
Token 2:[312].
Token 3:[1232].
Token 4:[1312].

Community
  • 1
  • 1
Cloud
  • 18,753
  • 15
  • 79
  • 153
  • Does `strtok(buf, "\n");` remove the `'\n'` if it is the initial `char`? – chux - Reinstate Monica Feb 29 '16 at 20:51
  • @chux Nope, it remains in the input buffer, so the buffer is effectively `0x0A 0x00 0x00 0x00 ... 0x00`. It causes the above example to detect a single input: 0, which is wrong in general. If that's a concern, OP should do a check for `if(buf[0] == '\n') return -1;` or something similar. – Cloud Feb 29 '16 at 20:55
  • 1
    @Dogbert, I have forgot to put that I need the code to work with the flag -std=c99, but your answer would solved my problem if there's not need to compile with this flag! Thanks. – lcsvcn Mar 01 '16 at 02:36
1

Try to replace your code by following code.

The new code works only if input contains only single space between integers.

Your code:

while(op[cont] != '\0') {
                for(i = 0; op[cont] != ' '; i++, cont++) {

                    num[i] += op[cont];
                }
                printf("num[i] = %d\n", num[i]);
            }

New code:

while(op[cont] != '\0')
            {
                if(op[cont] != ' ')
                    num[i] = num[i]*10 + (op[cont]- '0');
                else 
                    i++;
                cont++;
            }
0

See this example of how to do that:

char string [10] = "101 1 666"
int v [3], n=0, j=0;
int tam = strlen(string);
int current_Len = 0;

for(i=0; i<tam; i++){
    //32 = ascii for White space 
    if(string[i] != 32){
          n = n*10 + string[i] - '0';
          current_len++;
    } else if (current_len > 0){
          v[j++] = n;
          current_len = 0;
          n=0;
    }
}
if (current_len > 0){
          v[j++] = n;
}
Han Arantes
  • 775
  • 1
  • 7
  • 19
0

This answer is assuming you know how much integers your string contain at the time of writing your code. It also uses specific clang/gcc extension (typeof) and may not be portable. But it may be helpful to someone (I mainly wrote it because I had nothing good to do).

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

struct {int _[3];} strToInt3(const char (*pStr)[])
{
    int result[3] = {0}, *pr = result;

    for(register const char *p = *pStr; *p; ++p)
    {
        if(*p == ' ') ++pr;
        else
            *pr *= 10,
            *pr += *p - '0';    
    }

    return *(__typeof__(strToInt3(0)) *)result;
}

int main()
{

    char op[10];
    int num[3];

    scanf("%10[^\n]", op),

    //memcpy(num, strToInt3(op)._, sizeof(num));
    //or
    *(__typeof__(strToInt3(0)) *)num = strToInt3(op);

    printf("%d %d %d", num[0], num[1], num[2]);  
}

I've commented the copying of returned array using memcpy and added a structure assignment. Although both must be valid (not standard I guess but working in most cases) I prefer the second option (and maybe some compiler optimizers will).

Also I assume ASCII character set for chars.

AnArrayOfFunctions
  • 3,452
  • 2
  • 29
  • 66
0

I found an easier approach to the problem. I insert a scanf, that don't catch the space blanket and convert it using atoi. As it is just 3 ints it doesn't become so bad to use this simple, repetitive way of catching the values. And it work with the -std=c99 flag, that I needed to use.

    scanf("%s[^ ]\n", op);
    num[0] = atoi(op);

    scanf("%s[^ ]\n", op);
    num[1] = atoi(op);

    scanf("%s[^ ]\n", op);
    num[2] = atoi(op);

    printf("%d\n", num[0]); 
    printf("%d\n", num[1]); 
    printf("%d\n", num[2]); 
lcsvcn
  • 1,184
  • 3
  • 13
  • 28