exceltior
exceltior

Reputation: 103

Variable input read from stdin

I have a doubt for example if i have an input like this :

5 4
1 2 3 4 5
2 3 4
2 3
1 2 3

Where the first number means the different "toys" there are to attribute to each kid which corresponds to the second number which is four and by consequence to the number of lines that represents each kid and the toys they want ...

How would i read an input like this in ansi C? With the use of strtok? or is there any other simpler way to do it?

i could do it with something like this

char line [250];
char * tok;
char *ptr = line;


while((scanf("%s",line)!= EOF){

    while ((tok = strtok(ptr, " ")) != NULL)
    {
        pseudo part
        //convert to int
        //add to array

    }

}

but is there any easier way to do this input without using tok? Thanks ...

Upvotes: 1

Views: 218

Answers (2)

chux
chux

Reputation: 154582

Recommend a classic fgets()/sscanf() combination.

Read in one line at a time. Good error checking available. Use "%n" to know where to begin the next scanning for the next toy.

char buffer[250];
if (fgets(buffer, sizeof buffer, stdin) == NULL)
  HandleEOF();
int toys, kids;
int cnt = sscanf(buffer, "%d%d", &toys, &kids);
if (cnt != 2 || toys <= 0 || kids <= 0)
  Handle_BadToysKids(cnt);
int kid_wants[kids][toys] = { 0 };

for (int k = 0; k < kids; k++) {
  if (fgets(buffer, sizeof buffer, stdin) == NULL)
    HandleEOF();
  char *p = buffer;
  int want;
  int n;
  while ((cnt = sscanf(p, "%d %n", &want, &n)) == 1) {
    if (want <= 0 || want > toys)
      Handle_BadWant(want);
    kid_wants[k][want - 1] = 1;
    p += n;
  }
}

Improvements:
Use size_t toys, kids and "%zu".
Use sentinel to check for extra junk on a line:
int ch; int cnt = sscanf(buffer, "%d%d %c", &toys, &kids, &ch);
Check *p at end of while loop - it should be '\0'.

Upvotes: 1

SHR
SHR

Reputation: 8333

You can use fgets to read a line, not scanf. scanf will read only till the first white space. (better to use fgets just because it is safer than gets)

like this:

ptr = fgets(line,sizeof(line),stdin);

Your strtok will work, if you set ptr to NULL after the first call. Anyway, it is better to add more white spaces like: " \r\n\t"

//assume ptr = line had been set by fgets...
char* tok;
do{
   const char* whitespaces = " \r\n\t";
   tok = strtok(ptr, whitespaces);
   ptr = NULL;//till next fgets
   if(tok){
      //got more number  
   }
}while(tok);

Upvotes: 1

Related Questions