fscanf issues, please help.

Q

quyvle

I can't seem to get this function to work correctly. I'm wondering
if anyone could help me out with this.

So I'm using the fscanf function to read the input stream and store
each string in the appropriate variables.

Here's what I'm reading from another file:

"# Number of power catergories: 9"

I store each string between a whitespace into a variable. When I print
out all those variables, I get randomness. Some of the outputs are as
follows:

"# Numbof of powecate9 cate9 134518740"

The code is displayed below:


input_file = fopen("output_HIER.txt", "r");

output_file = fopen( "blah.txt", "w" );

result = fscanf(input_file,"%s %s %s %s %s %s", &dummy[0], &dummy[1],
&dummy[2], &dummy[3], &dummy[4], &dummy[5]);

fprintf(output_file,"%s %s %s %s %s %i\n", &dummy[0], &dummy[1],
&dummy[2], &dummy[3], &dummy[4], &dummy[5]);

Please assume that all the variables have been declared already. This
is just for testing purposes. But it doesn't seem to work correctly.
Any help would be much appreciated.
 
M

mark_bluemel

quyvle said:
I can't seem to get this function to work correctly. I'm wondering
if anyone could help me out with this.

So I'm using the fscanf function to read the input stream and store
each string in the appropriate variables.

Here's what I'm reading from another file:

"# Number of power catergories: 9"

I store each string between a whitespace into a variable. When I print
out all those variables, I get randomness. Some of the outputs are as
follows:

"# Numbof of powecate9 cate9 134518740"

The code is displayed below:


input_file = fopen("output_HIER.txt", "r");

output_file = fopen( "blah.txt", "w" );

result = fscanf(input_file,"%s %s %s %s %s %s", &dummy[0], &dummy[1],
&dummy[2], &dummy[3], &dummy[4], &dummy[5]);

fprintf(output_file,"%s %s %s %s %s %i\n", &dummy[0], &dummy[1],
&dummy[2], &dummy[3], &dummy[4], &dummy[5]);

Please assume that all the variables have been declared already.

Why should we do that? If we don't know clearly what you are passing to
fscanf, how can we be sure what's going on.

My initial guess was that you've declared something like this:-

char *dummy[6];

And you're passing the addresses of the uninitialised pointers to
fscanf(), but what do I know?

YEP - that's it. On a 32-bit machine, each of those pointers could hold
up to 4-bytes, which is what the output suggests...

The &s are incorrect, by passing them you are giving fscanf() and
fprintf() the address of a char pointer but telling them that it is the
address of an array of characters..

When you use a "%s" specifier to fscanf, you must provide the address
of a big enough character array to contain what fscanf finds...

In addition you have a mismatch in your format specifiers - you (try
to) read the "9" into a string, but try to output it as an integer...
 
B

Ben Bacarisse

quyvle said:
I can't seem to get this function to work correctly. I'm wondering
if anyone could help me out with this.

So I'm using the fscanf function to read the input stream and store
each string in the appropriate variables.

Here's what I'm reading from another file:

"# Number of power catergories: 9"

I store each string between a whitespace into a variable. When I print
out all those variables, I get randomness. Some of the outputs are as
follows:

"# Numbof of powecate9 cate9 134518740"

The code is displayed below:


input_file = fopen("output_HIER.txt", "r");

output_file = fopen( "blah.txt", "w" );

result = fscanf(input_file,"%s %s %s %s %s %s", &dummy[0], &dummy[1],
&dummy[2], &dummy[3], &dummy[4], &dummy[5]);

fprintf(output_file,"%s %s %s %s %s %i\n", &dummy[0], &dummy[1],
&dummy[2], &dummy[3], &dummy[4], &dummy[5]);

Please assume that all the variables have been declared already.

There is some evidence from the sample output you show that this
assumption would be wrong! Prove me wrong by posting a complete
example that exhibits the problem.

There is no declaration that I can think of that will allow &dummy[5]
to be supplied as the target for an fscanf %s format and as the source
for an fprintf %i format! (You probably want %d as the last fscanf
format and a suitably declared variable to receive the number.)
 
Q

quyvle

I did declare it as a char *dummy[6].

I guess, I would have to allocate memory to the pointers then.

This is what I get for learning perl first.
 
Q

quyvle

Could someone show me how to get this accomplished? I'm somewhat
confused. I thought you were suppose to make an array of pointers and
those pointers point to strings of whatever length.
 
Q

quyvle

quyvle said:
Could someone show me how to get this accomplished? I'm somewhat
confused. I thought you were suppose to make an array of pointers and
those pointers point to strings of whatever length.

n/m I guess I am going to use a double array of char type. I'm
wondering how would you initialize a pointer in an array of pointers?

char *dummy[10]

dummy = (char*)calloc(10, sizeof(char));

is that it?
 
C

CBFalconer

quyvle said:
Could someone show me how to get this accomplished? I'm somewhat
confused. I thought you were suppose to make an array of pointers
and those pointers point to strings of whatever length.

How to get what accomplished? Your post makes no sense whatsoever.
 
J

Jens Thoms Toerring

quyvle said:
Could someone show me how to get this accomplished? I'm somewhat
confused. I thought you were suppose to make an array of pointers and
those pointers point to strings of whatever length.

Definitely *no*. An array of pointers is an array of pointer,
nothing more. Once you have defined an array of pointers the
pointers don't point to anything you would be able to use,
they pont to some random places in memory. Before you can use
them in any way _you_ have to make them point to memory you own
(obtained by either defining a variable or array or calling a
function like malloc()). And, moreover, there are no strings of
"whatever" length in C. If you want a string of a _certain_
length you must ask for it, either by defining an array of chars
or by calling malloc() (if you use malloc() and you're lucky,
the system will give it to you). Once you got it you can use
its exact length, but not a single character more - if you get
it wrong you're in for bad surprises: it could work anyway (but
suddenly fail if you update your compiler or tray it on a different
system), the program could crash in some unforseeable place or it
could look like it works but the results of the program are wrong.

If you come from a Perl background then you have to get rid of
quite a number of assumptions. Perl (and other higher-level
languages) frees you from the burden of thinking very carefully
about where memory comes from - if you have a variable, memory is
suddenly there when you need it. Moreover, if you have an array,
then you can put all kinds of things into it - one element could
be an integer, the next one a string, followed by a hash etc.,
but that's also something you won't get in C. To do this Perl
does a lot of "magic" in the background (that's one reason why
Perl scripts tend to be slower than C programs). But in C nothing
of this is happening, you must do it all by yourself. And you must
be careful to get it right, otherwise all bets are off.

If you only need an array of NUM_STRINGS strings of all the same
length STRING_LENGTH, then something like

char my_string[ NUM_STRINGS ][ STRING_LENGTH ];

is the definition you need. But if you e.g. don't know how long
the different strings are going to be then you would first need
an array of char pointers

char *my_string[ NUM_STRINGS ];

and, once you know how long the individual strings are going to be,
call malloc() for each of the elements of this array to obtain
enough memory. I.e. if you know that the first of the strings is
going to need 99 chars you would call

if ( ( my_string[ 0 ] = malloc( 100 ) ) == NULL ) {
fprintf( stderr, "malloc() failure\n" );
exit( EXIT_FAILURE );
}

If everything goes well you end up with the first pointer of the
array pointing to enough memory for a string consisting of 99
characters (the extra one is going to be needed for the trailing
'\0' character that indicates the end of the string). Since you
can never be sure that everything goes well, you have to check
every time you request memory.

[Hint: never cast the return value of malloc(). If you do all
you get out of it is keeping the compiler from warning you if
you forgot to include <stdlib.h> and, if you did it, creating
a bug that can be extremely hard to find since then the return
value of malloc() is automatically converted to an int before
the resulting integer value is re-converted via the cast to a
pointer, which unfortunately works without a problem on a set
of (popular) machines, but fails badly on others.]

If you don't know how long the string you will have to read is
going to be you're in for even some more work. You have to come
up with a method to determine what's going to be needed, then
allocate memory and only then get hold of the string and put it
where you want it. That's why a function like fscanf() is rather
difficult to use with string input (and also other user input!) -
you hardly ever know an upper bound on the length of the string.
Thus you typically resort to using fgets() where you can read in
a certain number of characters, test if you got no more than fits
into the memory you have (in that case you're done) or the memory
got filled up but there's more, so you need to allocate more memory
and continue to read.

All these things are done in Perl automagically, so you don't got
to worry about it. But something in the innards of Perl is exactly
doing it for you (Perl is implemented in C) - and if you write in
C you have to take care of it all by yourself. All that may look
tedious (it often is:) or even scary, but once you get the hang
of it it's not _that_ complicated.

Regards, Jens
 
B

Barry Schwarz

Could someone show me how to get this accomplished? I'm somewhat
confused. I thought you were suppose to make an array of pointers and
those pointers point to strings of whatever length.

n/m I guess I am going to use a double array of char type. I'm
wondering how would you initialize a pointer in an array of pointers?

char *dummy[10]

dummy = (char*)calloc(10, sizeof(char));

is that it?

Did you try it? Did your compiler complain that dummy could not
appear on the left of the assignment operator? No array object can. C
does not support assigning to an array.

You declare dummy as an array of 10 pointer to char. dummy is an
aggregate object. (For an array, the objects that make up the
aggregate are called elements.) In the case of dummy, it consists of
10 scalar objects. Each of these scalar objects is a pointer. The
value of each is independent of the others. In particular, assigning
a value to one has no affect on the value of any other.

What you need is code that assigns a value to each of the elements.
One method is
dummy[0] = /* a legal address */;
dummy[1] = /* another (possibly the same) legal address */;
...
dummy[9] = ...
Another method is
for (i = 0; i < 10; i++)
{
dummy = calloc(10, sizeof *dummy);
/* most would use malloc here but I tried to be consistent
with the example you posted */
if (dummy == NULL)
{ /* code to handle allocation failure */}
}

Note that you do not want to cast the return from calloc or any of its
cousins.


Remove del for email
 
C

Chris Dollin

quyvle said:
I can't seem to get this function to work correctly. I'm wondering
if anyone could help me out with this.
(fx:snippage)

Please assume that all the variables have been declared already. This
is just for testing purposes. But it doesn't seem to work correctly.
Any help would be much appreciated.

If you don't understand what's going wrong, you don't know what it's
safe not to tell us, and we can't use your context to support our reply.
 

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,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top