user2976686
user2976686

Reputation: 159

How fscanf know this is the end of the line?

I read string from file if the string in the file is:

 "User1 User2 User3 User4 User5"
 "test1"

i want to read only the first line from the file,my code is:

 if (in_fp != NULL)
 {
   while (fscanf(in_fp, "%s", &user)!=EOF)
    {
      temp = (char*)malloc(sizeof user);
      strcpy(temp,user);
     }
 fclose (in_fp);
 }

but the problem is that fscanf read also that "test1" from the text file,i need to know how to make him to know that is the end of the line,what i need to fix in my code? i know about fgets but i want to read each user separately

Upvotes: 0

Views: 15920

Answers (3)

chux
chux

Reputation: 153358

To use fscanf("%s") and variant formats is a tough way to solve this task.

The %s consumes leading whitespace including ' ' and '\n' indiscriminately, yet OP uses these 2 distinctly as a username delimiter and record delimiter. Much better to read a line, using fgets() and then parse the buffer read.

OP is concerned about about unknown line length. Whereas it is good to not limit code to only work with a short line, designing code to work with an endless line has a problem too. Excessively long lines are increasing a sign of errant data or nefarious attempts to hack. Better to allocate a big buffer and gracefully complain should a data file try to exceed it.

size_t N = 4096;
char *buffer = malloc(N);
if (buffer == NULL) ...
while (fgets(buffer, N, in_fp) != NULL) {
  size_t Len = strlen(buffer);
  if (Len == 0 || buffer[Len-1] != '\n) {
    HandleUnacceptbaleBuffer();
  }
  // parse buffer via sscanf, strtok, etc.
  char *p = buffer;
  int n
  while (1 == sscanf(p, "%s%n", &user, &n)) {
    Handle(user);
    p += n;
  }
}
free (buffer);

Upvotes: 2

BLUEPIXY
BLUEPIXY

Reputation: 40145

a way

    if (in_fp != NULL){
        while (fscanf(in_fp, "%s%c", user, &ch)==2){
            temp = (char*)malloc(sizeof user);
            strcpy(temp, user);
            //do something
            printf("%s\n", user);
            free(temp);
            if(ch == '\n')
                break;
        }
        fclose (in_fp);
    }

Upvotes: 6

user529758
user529758

Reputation:

You don't.

And you don't want to use scanf() either. Avoid it like the plague.

If you want to read lines, then use fgets(). (Use it even if you don't want to read lines, still much better than scanf()).


I see the "but I want to read each word separately" question incoming. So, here you are:

char buf[LINE_MAX];
if (!fgets(buf, sizeof buf, stdin)) {
    // handle error
}

char *p = buf, *s = p;
while (p) {
    p = strtok_r(s, " ", &s);
    // do stuff with `p` if it's not NULL
}

Also, do NOT cast the return value of malloc()!

Upvotes: -1

Related Questions