0

I was wondering if it is possible to only read in particular parts of a string using scanf.

For example since I am reading from a file i use fscanf

if I wanted to read name and number (where number is the 111-2222) when they are in a string such as:

Bob Hardy:sometext:111-2222:sometext:sometext

I use this but its not working:

(fscanf(read, "%23[^:] %27[^:] %10[^:] %27[^:] %d\n", name,var1, number, var2, var3))
4
  • 3
    suggest " %23[^:]: %27[^:]: %10[^:]: %27[^:]: %d" Add 4 :, Add lead space, drop trailing space - maybe (depends on code). Still better off using fgets() and then parse the buffer. Commented Oct 28, 2015 at 21:35
  • ...after fgets use strtok to extract parts of the string. Commented Oct 28, 2015 at 21:39
  • can anyone explain about %23[^:] what is the usage. Commented Oct 28, 2015 at 21:42
  • @user3121023 Thank you. Commented Oct 28, 2015 at 21:48

2 Answers 2

1

Your initial format string fails because it does not consume the : delimiters.

If you want scanf() to read a portion of the input, but you don't care what is actually read, then you should use a field descriptor with the assignment-suppression flag (*):

char nl;
fscanf(read, "%23[^:]:%*[^:]:%10[^:]%*[^\n]%c", name, number, &nl);

As a bonus, you don't need to worry about buffer overruns for fields with assignment suppressed.

You should not attempt to match a single newline via a trailing newline character in the format, because a literal newline (or space or tab) in the format will match any run of whitespace. In this particular case, it would consume not just the line terminator but also any leading whitespace on the next line.

The last field is not suppressed, even though it will almost always receive a newline, because that way you can tell from the return value if you've scanned the last line of the file and it is not newline-terminated.

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

2 Comments

Something should consume the '\n' else the next call of fscanf(read, "%23[^:]..., name will likely begin with '\n'.
@chux, I updated the format to consume the trailing \n, where there is one. This is more parallel to the OP's attempt. It will suffer a matching failure on the last line of the file if that line is not newline-terminated, but that will not affect reading the desired data. That case can be distinguished by the return value.
1

Check fscanf() return value.

fscanf(read, "%23[^:] %27[^:] ... is failing because after scanning the first field with %23[^:], fscanf() encounters a ':'. Since that does not match the next part of the format, a white-space as in ' ', scanning stops.

Had code checked the returned value of fscanf(), which was certainly 1, it may have been self-evident the source of the problem. So the scanning needs to consume the ':', add it to the format: "%23[^:]: %27[^:]: ...

Better to use fgets()

Using fscanf() to read data and detect properly and improperly formatted data is very challenging. It can be done correctly to scan expected input. Yet it rarely works to handle some incorrectly formated input.

Instead, simple read a line of data and then parse it. Using '%n' is an easy way to detect complete conversion as it saves the char scan count - if scanning gets there.

char buffer[200];
if (fgets(buffer, sizeof buffer, read) == NULL) {
  return EOF;
}
int n = 0;
sscanf(buffer, " %23[^:]: %27[^:]: %10[^:]: %27[^:]:%d %n", 
    name, var1, number, var2, &var3, &n);
if (n == 0) {
  return FAIL; // scan incomplete
}
if (buffer[n]) {
  return FAIL; // Extra data on line
}
// Success!

Note: sample input ended with text, but original format used "%d". Unclear on OP's intent.

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.