1

I am looking through a data file containing both words and numbers, and I need to take the numbers out of each row and store them in an array.

Cheryl 2 1 0 1 2 0  
Neal 0 0 2 0 2 0  
Henry 0 2 2 0 2 0  
Lisa 0 0 0 0 2 1

This is how the file is formatted. I start by inputting each line into an array, participants[], and then I need to take the numbers from each line and put them in a separate, two-dimensional array, individually. i.e. the first line would be translated to:

responses[0][0] = 2
responses[0][1] = 1
responses[0][2] = 0
responses[0][3] = 1
responses[0][4] = 2
responses[0][5] = 0

At this point, I detect the first space with char *pointer = strstr(" ", participants[]);, and am able to locate the the beginning of the numbers with strcpy(temp, pointer+1);.
From that point, I run into problems as I am having a hard time translating the string of numbers (still a char string), into individual integer values to be stored in my responses[][] array.

Thanks!

2
  • Try strtoul(). That might even take care of the tokenization for you if you play it right. Commented Nov 8, 2011 at 22:50
  • 1) read the manual, 2) perhaps you can use the optional endptr argument to figure out where the next number starts. Commented Nov 8, 2011 at 22:52

2 Answers 2

1

If that's you're exact format, then perhaps fscanf/sscanf could do the job for you? ie.

#include <stdio.h>

int main(void)
{
   int nums[6]; 
   char line[] = "Cheryl 2 1 0 1 2 0";

   sscanf(line, "%*s %d %d %d %d %d %d", &nums[0], &nums[1], &nums[2], &nums[3], &nums[4], &nums[5]);

   printf("%d %d %d %d %d %d\n", nums[0], nums[1], nums[2], nums[3], nums[4], nums[5]);

   return 0;
}

Output:

2 1 0 1 2 0

And then just check the return value to make sure the right amount of numbers were read.

EDIT: For an arbitrary amount:

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

char *strchr_ignore_start(const char *str, int c)
{
   if (c == '\0') return strchr(str, c); /* just to be pedantic */

   /* ignore c from the start of the string until there's a different char */
   while (*str == c) str++;

   return strchr(str, c);
}

size_t extractNums(char *line, unsigned *nums, size_t num_count)
{
   size_t i, count;
   char *endptr = line;

   for (i = 0, count = 0; i < num_count; i++, count++) {
      nums[i] = strtoul(line, &endptr, 10);
      if (line == endptr) /* no digits, strtol failed */
         break;

      line = endptr;
   }

   return count;
}

int main(void)
{
   unsigned i, nums[9];
   char line[] = "Cheryl 2 1 0 1 2 0 0 1 2";
   char *without_name;

   /* point to the first space AFTER the name (we don't want ones before) */  
   without_name = strchr_ignore_start(line, ' ');

   printf("%u numbers were successfully read\n",
          (unsigned)extractNums(without_name, nums, 9));

   for (i = 0; i < 9; i++)
      printf("%d ", nums[i]);

   putchar('\n');

   return EXIT_SUCCESS;
}
Sign up to request clarification or add additional context in comments.

6 Comments

I need the method to be extensible, so that if there are say, 9 options instead of six, it stores all 9. Is there a way to modify this to meet that criteria? However, what you gave me is exactly what I need other than that! :)
@iKiar how will you be extracting the numbers? Will you have each line already read into a string before trying to extract the numbers? And are they signed or unsigned?
Yes, the string would be something like char line[] = "Cheryl 2 1 0 1 2 0 0 1 2"; as opposed to char line[] = "Cheryl 2 1 0 1 2 0";.. Of course this can also go the other way and have a string like char line[] = "Cheryl 1 2 0";
And the only possible values are 0,1,2. So although they aren't unsigned variable types, they aren't signed.
@iKiar I edited it one more time, I didn't like the potential white space problem.
|
0

strtok() seems like the obvious solution here:

char buf[1024];
int y;
for(y=0;fgets(buf, sizeof buf, file); y++){
     strtok(buf, " "); //burn name;
     char *str;
     int x = 0;
     for(str=strtok(NULL, " "); str; str=strtok(NULL, " ")){
          responses[y][x++] =  atoi(str);
     }
}

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.