Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
481 views
in Technique[技术] by (71.8m points)

c - fscanf problem with reading in String

I'm reading in a .txt file. I'm using fscanf to get the data as it is formatted. The line I'm having problems with is this:

result = fscanf(fp, "%s", ap->name);

This is fine until I have a name with a whitespace eg: St Ives So I use this to read in the white space:

result = fscanf(fp, "%[^
]s", ap->name);

However, when I try to read in the first name (with no white space) it just doesn't work and messes up the other fscanf.

But I use the [^ ] it works fine within a different file I'm using. Not sure what is happening.

If I use fgets in the place of the fscanf above I get " " in the variable.

Edit//

Ok, so if I use:

result = fscanf(fp, "%s", ap->name);
result = fscanf(fp, "%[^
]s", ap->name);

This allows me to read in a string with no white space. But When I get a "name" with whitespace it doesn't work.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One problem with this:

result = fscanf(fp, "%[^
]s", ap->name);

is that you have an extra s at the end of your format specifier. The entire format specifier should just be %[^ ], which says "read in a string which consists of characters which are not newlines". The extra s is not part of the format specifier, so it's interpreted as a literal: "read the next character from the input; if it's an "s", continue, otherwise fail."

The extra s doesn't actually hurt you, though. You know exactly what the next character of input: a newline. It doesn't match, and input processing stops there, but it doesn't really matter since it's the end of your format specifier. This would cause problems, though, if you had other format specifiers after this one in the same format string.

The real problem is that you're not consuming the newline: you're only reading in all of the characters up to the newline, but not the newline itself. To fix that, you should do this:

result = fscanf(fp, "%[^
]%*c", ap->name);

The %*c specifier says to read in a character (c), but don't assign it to any variable (*). If you omitted the *, you would have to pass fscanf() another parameter containing a pointer to a character (a char*), where it would then store the resulting character that it read in.

You could also use %[^ ] , but that would also read in any whitespace which followed the newline, which may not be what you want. When fscanf finds whitespace in its format specifier (a space, newline, or tab), it consumes as much whitespace as it can (i.e. you can think of it consuming the longest string that matches the regular expression [ ]*).

Finally, you should also specify a maximum length to avoid buffer overruns. You can do this by placing the buffer length in between the % and the [. For example, if ap->name is a buffer of 256 characters, you should do this:

result = fscanf(fp, "%255[^
]%*c", ap->name);

This works great for statically allocated arrays; unfortunately, if the array is dyamically sized at runtime, there's no easy to way to pass the buffer size to fscanf. You'll have to create the format string with sprintf, e.g.:

char format[256];
snprintf(format, sizeof(format), "%%%d[^
]%%*c", buffer_size - 1);
result = fscanf(fp, format, ap->name);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...