2

I'm working in a program in C and I have a char string of numbers like this:

5 13 12 7 3 0

I want to scan it and put each of these integers in an array of int. How do I do that? Is that a way to use sscanf for this?

I tried the following code with no success:

 fgets(datatemp, N*3, stdin);

 k = 0; garb = 'c';
    while(garb != '\0'){
      garb = strtok(datatemp, " ");
      array[k] = garb;
      k++;
    }

NOTE: I have to use it in a function which will do the same for many data in which 'datatemp' string will have a unknown number of integers (and only integers).

Thanks for any help.

5
  • Take the whole input into a string using getline() and then split the string with the character " " and you will have an array of your numbers as strings. Convert your numbers from string to integer. This will give you your desired integer array. Commented Jun 23, 2014 at 11:00
  • array[k] = atoi(garb); Commented Jun 23, 2014 at 11:01
  • 1
    Why don't you directly read from stdin into array, till scanf is successfully Commented Jun 23, 2014 at 11:02
  • Is the count of int limited by N or is it an "unknown number" such as 0,1,2,3,... Commented Jun 23, 2014 at 16:48
  • At the end I just did what @P0W said. But I still trying to do the other way, since it can be usefull in other situations. Commented Jun 25, 2014 at 13:45

4 Answers 4

1
// Adapted from strtok(3) example.

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

int
main(int argc, char *argv[])
{
  char *str1, *str2, *token, *subtoken;
  char *saveptr1,*saveptr2;
  int j;
  char datatemp[ 120 ];
  char delim = ' ';

  fgets(datatemp, 119, stdin);

  /*
   * strtok has to be called with a pointer to the input
   * the first time then with a pointer to the string
   * subsequently
   */

  for(j=1, str1 = datatemp;; j++, str1 = NULL)
  {
    token = strtok_r(str1, &delim, &saveptr1);

    if(token==NULL)
      break;

    for (str2 = token; ; str2 = NULL)
    {
      subtoken = strtok_r(str2, &delim, &saveptr2);
      if (subtoken == NULL)
        break;
      printf(" --> %s\n", subtoken);
    }
  }

  exit(0);

}

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

2 Comments

Thanks for your answer. Seeing as the code is rather complex, it would surely be of help to the OP if you could add some explanation, via inline comments or a text besides the code.
Note: No need to subtract 1, use fgets(datatemp, 120, stdin); or even better fgets(datatemp, sizeof datatemp, stdin);. fgets() already accounts for the '\0'.
0

To use fgets()/sscanf() as requested by OP, see below.

Using fgets()/strtol() offers better error handling than sscanf(). Recommend strtol()

To get the best answer, OP needs to provide info like how data is to be store (VLA, malloc, 1 at-a time), error handle concerns, etc.

Hard to tell why OP code did not work as the defalcation of array[] is missing, but it may have been too small for the test data and certain was not resized as needed for various data input.

void foo() {
  char buf[100];
  if (fgets(buf, sizeof buf, stdin) == NULL) Handle_EOForIOError();

  int i = 0;
  int n = 0;
  int number;
  // Count the numbers
  while (sscanf(&buf[i], "%d %n", &number, &i) == 1) {
    n++;
  }

  int num[n];
  i = 0;
  int j;
  // scan again, this time save the numbers
  while (sscanf(&buf[i], "%d %n", &num[i], &j) == 1) {
    i = j;
  }

  // use the numbers
  bar(num, n);
}

Above code could use likely skip the j and use while (sscanf(&buf[i], "%d %n", &num[i], &i) == 1);, but I need to double check some code-point issues.

strtol() is better than sscanf(). To use, suggest a helper function:

// return non-zero on failure 
static int user_strtoi(char **s, int *result) {
  char *endptr;
  errno = 0;
  long num = strtol(*s, &endptr, 10);
  if (endptr == *s) return 1; //  fail as nothing was parsed
  if (errno != 0) return 2; //  fail due to overflow
  if (num < INT_MIN || num > INT_MAX)  return 2; //  fail due to overflow
  *result = (int) num;
  *s = endptr;
  return 0;
}

2 Comments

array[] is a array of integers dynamically allocated with malloc to fit a maximum size of numbers defined in the input file. Also, array[] is inside a struct vector that is dynamically allocated too.
@user3442466 Suggest updating your post so the code includes this important clarification. Also post a larger example of sample data. 1) Multi-line? 2) Each lines same number of int? 3) Given you appear to want an array of "array of integers", Do all the "array of integers" need to be the same length? 4) how do you want to denote the length of int in the "array of integers"? 5) How do you want to denote the length of the array of "array of integers"?
0

You can use standard function strtol declared in header <stdlib.h>. For example

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


int main( void ) 
{
    char s[] = "5 13 12 7 3 0";
    size_t l = strlen( s );

    size_t n = 0;

    char *end_ptr = s;
    char **next_ptr = &end_ptr;

    errno = 0;

    while ( end_ptr != s + l )
    {
        strtol( *next_ptr, next_ptr, 10 );
        if ( errno != 0 ) break;
        ++n;
    }

    int a[n];
    memset( a, 0, n * sizeof( int ) );

    end_ptr = s;
    size_t i = 0;
    while ( end_ptr != s + l )
    {
        int value = ( int )strtol( *next_ptr, next_ptr, 10 );
        if ( errno != 0 ) break;
        a[i++] = value;
    }

    for ( i = 0; i < n; i++ ) printf( "%d ", a[i] );
    puts( "" );

    return 0;
}

The output is

5 13 12 7 3 0

6 Comments

Note: Before 2nd while loop, suggest another errno = 0;. Not confident about the the benefit of checking for errno and not checking if (int) loses range. Suggest simply using long instead of int.
@chux In C atoi is defined as (int) strtol(...).:)
atoi() loses information should sizeof(long) > sizeof(int) just like (int) strtol(). If code is concerned with errno (overflow), it is reasonable to also be concerned with losing data due to an (int) cast. IAC, these issues are likely beyond OP's major concern.
Is it just me, or does your input not match your output? 0 is still and integer right?
@David C. Rankin It is a good remark! The condition has to be changed to endptr != s + strlen( s )
|
0

I suggest to use strtol in a loop, is faster (direct convert without an intermediate buffer) and you can check for errors

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

int main(void)
{
    char s[128], *p, *q;
    int i, n, *v;

    /* get user input */
    fgets(s, sizeof s, stdin);
    /* count integers */
    for (p = s, n = 0; ; p = q, n++) {
        strtol(p, &q, 10);
        if (p == q) break;
    }
    v = malloc(sizeof(int) * n);
    /* populate array */
    for (p = s, i = 0; i < n; i++) {
        v[i] = strtol(p, &p, 10);
    }
    /* print array */
    for (i = 0; i < n; i++) {
        printf("%d\n", v[i]);
    }
    free(v);
    return 0;
}

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.