Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sscanf to read file stored in string

46 views
Skip to first unread message

john.chl...@gmail.com

unread,
Aug 10, 2012, 2:09:06 PM8/10/12
to
I have an entire file stored in a string. The file is 2 columns of doubles (stored in ASCII, of course). The doubles are separated by an arbitrary number of spaces, maybe tabs too.

sscanf(file_bytes+offset, "%lf %lf", &x[i], &y[i]) will return the number of "items" read, in this case 2 doubles.

I need to know how to increment "offset" to read the next line?

---John

PS> I looked in FAQs but didn't see anything to answer this question.

Keith Thompson

unread,
Aug 10, 2012, 2:36:11 PM8/10/12
to
john.chl...@gmail.com writes:
> I have an entire file stored in a string. The file is 2 columns of
> doubles (stored in ASCII, of course). The doubles are separated by an
> arbitrary number of spaces, maybe tabs too.
>
> sscanf(file_bytes+offset, "%lf %lf", &x[i], &y[i]) will return the
> number of "items" read, in this case 2 doubles.
>
> I need to know how to increment "offset" to read the next line?

I don't think you can do that with sscanf; it doesn't tell you how many
characters it processed.

Use strtod() instead. Its endptr parameter can be used to get a pointer
to the next character after the last one used in the conversion. It
also has the considerable advantage of being much more robust; if sscanf
reads something that has the syntax of a floating-point number, but is
outside the range of the type (such as "1.0e99999999"), the behavior is
undefined. strtod() can handle such errors.

Calling strtod() repeatedly will give you one double value at a time,
delimited by whitespace (which includes both spaces and newlines).

If you want to detect formatting errors, such as a line that doesn't
have exactly two numbers, you can scan the string for '\n' and space
characters and then call strtod().

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Ben Pfaff

unread,
Aug 10, 2012, 2:42:08 PM8/10/12
to
Keith Thompson <ks...@mib.org> writes:

> john.chl...@gmail.com writes:
>> I have an entire file stored in a string. The file is 2 columns of
>> doubles (stored in ASCII, of course). The doubles are separated by an
>> arbitrary number of spaces, maybe tabs too.
>>
>> sscanf(file_bytes+offset, "%lf %lf", &x[i], &y[i]) will return the
>> number of "items" read, in this case 2 doubles.
>>
>> I need to know how to increment "offset" to read the next line?
>
> I don't think you can do that with sscanf; it doesn't tell you how many
> characters it processed.

You can use %n.

James Kuyper

unread,
Aug 10, 2012, 2:46:39 PM8/10/12
to
On 08/10/2012 02:09 PM, john.chl...@gmail.com wrote:
> I have an entire file stored in a string. The file is 2 columns of doubles (stored in ASCII, of course). The doubles are separated by an arbitrary number of spaces, maybe tabs too.
>
> sscanf(file_bytes+offset, "%lf %lf", &x[i], &y[i]) will return the number of "items" read, in this case 2 doubles.
>
> I need to know how to increment "offset" to read the next line?

For this kind of work, what you need is strtod(), not sscanf().
Warning: untested code. As given below, it's uncompilable: it needs a
context that defines MAX_BYTES, file_bytes, x, and y, and fills in
file_bytes, and declares a function that the code below can be part of.

#include <errno.h>
#include <stdlib.h>
#include
const char *nptr = file_bytes;

for(int i=0; i<MAX_ITEMS && *nptr; i++)
{
char *endptr;

errno = 0;
x[i] = strtod(nptr, &endptr);
if(nptr == endptr)
{
fprintf(stderr, "x[%d]: \"%s\"\n is empty or does "
"not have the form expected by strtod()\n", i, nptr);
break;
}
else if(errno == ERANGE && fabs(x) >= HUGE_VAL)
{
fprintf(stderr, "x[%d]: strtod(\"%s\") overflowed\n", i, nptr);
break;
// ERANGE might or might not also be set on underflow.
}
else if(*endptr == '\0')
{
fprintf(stderr, "file ends without a y value for item %d\n", i);
break;
}
nptr = endptr;

errno = 0;
y[i] = strtod(nptr, &endptr);
// Insert similar error handling code here.
nptr = endptr;
}

The error handling here is just basic, it can be improved. In
particular, you should probably limit the number of bytes that are
printed from nptr: search for the end of the current line, and don't
print beyond that. I've left those details to be filled in by the student.

Fred K

unread,
Aug 10, 2012, 2:22:13 PM8/10/12
to
On Friday, August 10, 2012 11:09:06 AM UTC-7, john.chl...@gmail.com wrote:
> I have an entire file stored in a string. The file is 2 columns of doubles (stored in ASCII, of course). The doubles are separated by an arbitrary number of spaces, maybe tabs too.
>
>
>
> sscanf(file_bytes+offset, "%lf %lf", &x[i], &y[i]) will return the number of "items" read, in this case 2 doubles.
>
>
>
> I need to know how to increment "offset" to read the next line?
>
>
>

Don't use sscanf(). Use strtod() instead.

Eric Sosman

unread,
Aug 10, 2012, 2:54:06 PM8/10/12
to
On 8/10/2012 2:09 PM, john.chl...@gmail.com wrote:
> I have an entire file stored in a string. The file is 2 columns of doubles (stored in ASCII, of course). The doubles are separated by an arbitrary number of spaces, maybe tabs too.
>
> sscanf(file_bytes+offset, "%lf %lf", &x[i], &y[i]) will return the number of "items" read, in this case 2 doubles.
>
> I need to know how to increment "offset" to read the next line?

You could use

int count;
...
sscanf(file_bytes + offset, "%lf%lf%n", &x[i], &y[i], &count);
... error checking ...
offset += count;

Personally, I think it would be easier to use strtod().

> PS> I looked in FAQs but didn't see anything to answer this question.

Thanks for checking before posting! Unfortunately, the F
in FAQ stands for "Frequently," not for "All" ;-)

--
Eric Sosman
eso...@ieee-dot-org.invalid

Keith Thompson

unread,
Aug 10, 2012, 3:16:16 PM8/10/12
to
Yes, good point.

strtod() is still a better tool for this job, though.

lawrenc...@siemens.com

unread,
Aug 10, 2012, 2:54:13 PM8/10/12
to
See the "%n" format specifier. You might find it more convenient to use
strtod() rather than sscanf().
--
Larry Jones

What better way to spend one's freedom than eating chocolate
cereal and watching cartoons! -- Calvin
0 new messages