0

The string is in this form:

123 456\n

My basic idea is to find the whitespace by a for-loop:

int i=0;
for (i=0;isdigit(str[i]);i++){
}
char *dest1;
strncpy(dest1, str, i-1);
dest1[i]='\0';

And for the second int, I did that again:

int j=i+1;
for (;isdigit(str[j]);j++){
}
char *dest2;
strncpy(dest2; (str+j); j-i);
dest2[j-i+1]='\0';
int from = atoi(dest1);
int to = atoi(dest2);

But the second time I did this, Xcode said 'too few arguments provided to function-like macro invocation' && 'expression result unused'.

But they are exactly the same syntax...Someone please tell me where I did wrong?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Abby Meng
  • 13
  • 4
  • 1
    You have not initialized `dest1` or `dest2`, therefore this is undefined. – EOF Mar 21 '16 at 00:01
  • After I initialised them, I still got those two errors – Abby Meng Mar 21 '16 at 00:04
  • 1
    Well, you incorrectly use `;` instead of `,` between arguments to `strncpy()` in the second snippet. But the code has a number of other defects that make it very likely for the program to exhibit undefined behavior. – EOF Mar 21 '16 at 00:07
  • Is there a better way of doing that? Or is there a function that can be used to extract the numbers from a line of char? – Abby Meng Mar 21 '16 at 00:09
  • @AbbyMeng Yes, please look at my answer. – Iharob Al Asimi Mar 21 '16 at 00:10
  • If you know there are two integers in the string (or you expect there to be just two integers in it), then `if (sscanf(str, "%d %d", &from, &to) == 2) { …work with valid values in from and to… } else { …deal with error… }` is simplest. If you don't know how many values there are, or you need to be sure you've used the whole string, or various other possible scenarios, you have to work harder, perhaps with a loop. – Jonathan Leffler Mar 21 '16 at 00:58

3 Answers3

1

No need for that, use sscanf()

int value;
int count;
char *pointer;
char str[] = "123 456";

pointer = str;
while (sscanf(pointer, "%d%n", &value, &count) == 1)
{
    fprintf(stdout, "%d\n", value);
    pointer += count;
}
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • 1
    Won't the first variant loop infinitely if the string contains non-whitespace that cannot be parsed as a number? – EOF Mar 21 '16 at 00:11
  • I see what you mean... – Abby Meng Mar 21 '16 at 00:18
  • See [Correct usage of `strtol()`](https://stackoverflow.com/questions/14176123/correct-usage-of-strtol/14176593?s=2|3.7929#14176593) for a discussion of how to use `strtol()` more accurately. Note that if `sizeof(int) != sizeof(long)`, you have multiple problems. Put succinctly, if you care about error handling, you can't use raw `strtol()` inline; it needs to be called in a function which does delicate checking. If you don't care about error handling, you can get away with it, but consider `atol()` instead. – Jonathan Leffler Mar 21 '16 at 01:02
  • @JonathanLeffler: The only problem I see with assigning the result of `strtol()` to an `int` is the possibly implementation-defined conversion in case the value cannot be represented by an `int`. I don't see how `atol()` is *ever* safer than `strtol()`. – EOF Mar 21 '16 at 01:19
  • I didn't say `atol` was safer; it's simpler. And I said if you don't care about error handling, you may as well use it. If you do, be careful with `strtol()`. It is powerful but tricky to use accurately — witness your loop which fails if the input is not numeric. – Jonathan Leffler Mar 21 '16 at 01:26
  • Better to use `"%d %n"` (Add space) . Makes it easy to test if the entire line was parsed with `if(*pointer)` after the loop. – chux - Reinstate Monica Mar 21 '16 at 02:13
0

If your string has only integers you can use the strtok() function, which returns tokens separated by a delimiter. So you can add for delimiter the white space.

For example:

#include <string.h>

char str[] = "123 456 789";
char *token;
int number;

token = strtok(str, " ");

for(int i=0; i < 2; i++){
   number = atoi(token);
   printf("%d\n", number);
   token = strtok(NULL, " ");
}

This will print you this:

123
456
789

Note that strtok() gets the string only on its first call. Then you have to use NULL until the end of the particular string — either because you counted (guessed, knew) how many entries there are or because strtok() returned a NULL pointer.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
astef
  • 1
  • 1
0

Your way (fixed)

char *str = "123 456\n";

int i=0;
for (i=0; isdigit(str[i]); i++){
}
char dest1[4];
strncpy(dest1, str, i);
dest1[i]='\0';

int j=i+1;
for (;isdigit(str[j]);j++){
}
char dest2[4];
strncpy(dest2, str+i+1, j-i-1);
dest2[j-i-1]='\0';
int from = atoi(dest1);
int to = atoi(dest2);

My way

int from, to;
char *str = "123 456\n";

int ret = sscanf(str, "%d %d", &from, &to);
Daniel
  • 16
  • 1
  • 3