fscanf question - most of line -> null

C

Cal Lidderdale

My input line is i1,i2,i3,i4,i5,i6,i7,i8^,...i596,597, ...
14101,14102...NL/CR

very long line of data - I only want the first 8 items and
the delimiter between 8 & 9 is a carrot "^".
The line can end at the 100th item or the 40,000th item.

My code is:

char data[500], mynull[800000];
n1 = fscanf (fp, "%[^^]^%[^\n]\n", &data, mynull);

what I'd like is
fscanf (fp, "%[^^]^%[^\n]\n", &data, >/dev/null);

well you get the point.

Seems like there could be a cleaner way to send every
thing between the "^" & "\n" to the bit bucket so all I
get is 1-8, 1-8, 1-8 with all the 9-\n > null.

Thanks
 
M

Michael Mair

Cal said:
My input line is i1,i2,i3,i4,i5,i6,i7,i8^,...i596,597, ...
14101,14102...NL/CR

very long line of data - I only want the first 8 items and
the delimiter between 8 & 9 is a carrot "^".
The line can end at the 100th item or the 40,000th item.

My code is:

char data[500], mynull[800000];
n1 = fscanf (fp, "%[^^]^%[^\n]\n", &data, mynull);
^^^ ^
1. restrict the number of characters to be read into data
2. &data is the address of the address of data[0]. You
want data or &data[0] instead.
what I'd like is
fscanf (fp, "%[^^]^%[^\n]\n", &data, >/dev/null);

well you get the point.

Seems like there could be a cleaner way to send every
thing between the "^" & "\n" to the bit bucket so all I
get is 1-8, 1-8, 1-8 with all the 9-\n > null.

Use
char data[500];
n1 = fscanf (fp, " %499[^^]^%*[^\n]", data);

I moved the white-space to the beginning.


Cheers
Michael
 
E

Eric Sosman

Cal said:
My input line is i1,i2,i3,i4,i5,i6,i7,i8^,...i596,597, ...
14101,14102...NL/CR

very long line of data - I only want the first 8 items and
the delimiter between 8 & 9 is a carrot "^".
The line can end at the 100th item or the 40,000th item.

My code is:

char data[500], mynull[800000];
n1 = fscanf (fp, "%[^^]^%[^\n]\n", &data, mynull);

what I'd like is
fscanf (fp, "%[^^]^%[^\n]\n", &data, >/dev/null);

well you get the point.

Seems like there could be a cleaner way to send every
thing between the "^" & "\n" to the bit bucket so all I
get is 1-8, 1-8, 1-8 with all the 9-\n > null.

Use the assignment-suppression operator on the
second scanset (and guard against overlength input
to the first scanset):

fscanf(fp, "%499[^^]^%*[^\n]\n", data);

Incidentally, the final '\n' in your scan format
doesn't do what you probably want. It is not a literal
character that matches only a newline, but a white
space character that matches any (non-empty) amount of
white space input. It will consume the '\n' at the end
of the current line, plus any leading spaces and tabs
and such on the next line, and if it still hasn't found
a non-white it will consume the next line's '\n' and keep
going. In short, it will consume everything until it
finds a non-white character or end-of-input. One way to
remedy this is to consume the newline with a one-byte
assignment-suppressed scanset of its own:

fscanf(fp, "%499[^^]^%*[^\n]%*1[\n]", data);
 
C

Chris Torek

In short, [the newline in the format] will [make scanf] consume
everything until it finds a non-white character or end-of-input.
One way to remedy this is to consume the newline with a one-byte
assignment-suppressed scanset of its own:

fscanf(fp, "%499[^^]^%*[^\n]%*1[\n]", data);

Or, more simply, a suppressed-assignment single character reading
directive, "%*c". Note that both of these have a drawback: if an
earlier directive fails, they will not be reached and therefore
will not consume the newline. In particular, if a line does not
contain non-newline characters following the '^' character -- i.e.,
if the ^ is at the end -- a single fscanf() will not consume the
newline. One can fix this by removing the "consume the newline"
directive, and just doing a separate getc(); but then I, at least,
must wonder what happens if an input line fails to contain the '^'?

This particular problem is probably best "open-coded":

for (datalen = 0; (c = getc(fp)) != '^' && c != '\n'; datalen++) {
if (datalen < 500)
data[datalen] = c;
}
/* at this point, either c=='^' or c=='\n' */
if (datalen >= 500) {
... handle error -- the data buffer is full ...
}
data[datalen] = '\0'; /* terminate the string */
if (c == '^') {
/* consume the rest of the line through the newline */
while ((c = getc(fp)) != '\n')
continue;
} else {
this branch is optional -- what does it mean if there is no ^ ?
}

The 16 lines above are a candidate for a small "get a line of
input with funny '^' marker action" function.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top