problem with fgets

E

Emerson

Hi all:

my problem is in the comments of the code .
would u please give me some clue what 's the problem?
what u in advance.

/*******************************/
#include "stdio.h"
#include "malloc.h"
#include "assert.h"
int main(void)
{
FILE *p_file;
static char *filename="test";
char *s=NULL;
int c;
int num=0;

if ((p_file=fopen(filename,"w+"))==NULL) { /* does "w+" means your
can read & write the file? */
printf("cant't open file %s\n",filename);
}
else{
while ((c=getchar())!=EOF) {
if (fputc(c,p_file)!=EOF)
++num; /*# of character written*/

}
fflush(p_file);

}

if ((s=(char*)calloc(num,sizeof(*s)))==NULL) {
printf("can't calloc enough memory\n");
}
else{

assert(p_file!=NULL); /*the file stores actually what i
input,ant the p_file is NOT NULL */
if((s=fgets(s,5,p_file))==NULL) /*i just get 5-1 character,and make
sure the p_file has more than 5 character*/
printf("error in fgets\n"); /*problem is HERE,this message is
printed,WHY?*/
else
printf("fgets get followings: %s \n", s);
}

fclose(p_file);
return 0;
}
 
J

Jens.Toerring

Emerson said:
my problem is in the comments of the code .
would u please give me some clue what 's the problem?
/*******************************/
#include "stdio.h"
#include "malloc.h"

There's no "malloc.h" in standard C. Use <stdlib.h> for the declaration of
malloc() and friends. Moreover, you normally would enclose the names of the
standard header files in angle brackets (i.e. ' said:
#include "assert.h"
int main(void)
{
FILE *p_file;
static char *filename="test";
char *s=NULL;
int c;
int num=0;
if ((p_file=fopen(filename,"w+"))==NULL) { /* does "w+" means your
can read & write the file? */

Yes. And if it already exists it's truncated to zero length.
printf("cant't open file %s\n",filename);

It probably would make sense to bail out in this case, so add e.g.

return EXIT_FAILURE;
} else {
while ((c=getchar())!=EOF) {
if (fputc(c,p_file)!=EOF)
++num; /*# of character written*/
}
fflush(p_file);
}
if ((s=(char*)calloc(num,sizeof(*s)))==NULL) {
printf("can't calloc enough memory\n");
} else {
assert(p_file!=NULL); /*the file stores actually what i
input,ant the p_file is NOT NULL */
if((s=fgets(s,5,p_file))==NULL) /*i just get 5-1 character,and make
sure the p_file has more than 5 character*/
printf("error in fgets\n"); /*problem is HERE,this message is
printed,WHY?*/

Because after writing to the file you're at the end of it, i.e. at the
position directly after the last character you wrote. Before you can
read back all the characters you just wrote you must set the current posi-
tion in the file back to the start of it using either rewind() or fseek().
else
printf("fgets get followings: %s \n", s);
}
fclose(p_file);
return 0;
}

Regards, Jens
 
M

Michael Mair

Emerson said:
Hi all:

my problem is in the comments of the code .
would u please give me some clue what 's the problem?
what u in advance.

I am not comfortable with your kind of English. I guess you
mean "thank" by "what" but it does not show with all the "u"s.

/*******************************/
#include "stdio.h"
#include "malloc.h"
#include "assert.h"
int main(void)
{
FILE *p_file;
static char *filename="test";
char *s=NULL;
int c;
int num=0;

if ((p_file=fopen(filename,"w+"))==NULL) { /* does "w+" means your
can read & write the file? */

Yes. Moreover, the file is truncated to zero if it already
exists.
printf("cant't open file %s\n",filename);
}
else{
while ((c=getchar())!=EOF) {
if (fputc(c,p_file)!=EOF)
++num; /*# of character written*/

}
fflush(p_file);

}

The current position in the file is "at the very end".
(*)
if ((s=(char*)calloc(num,sizeof(*s)))==NULL) {

You have written num characters, so you need num+1 characters
to store the written characters plus the string terminator.
The cast to char * is unnecessary and potentially dangerous.
printf("can't calloc enough memory\n");
}
else{

assert(p_file!=NULL); /*the file stores actually what i
input,ant the p_file is NOT NULL */
if((s=fgets(s,5,p_file))==NULL) /*i just get 5-1 character,and make
sure the p_file has more than 5 character*/

Well, you are reading from the very end of the file (see (*)), so you
cannot get even one character.
In addition, you have switched from a stream to write to to
a stream to read from. This requires a call to fflush() or
file positioning functions (rewind(), fsetpos(), fseek()).
You called fflush(), so this is not a problem here.
If you replace the call to fflush() by one to rewind(),
you should not encounter any problems.

One real bug is to assign s the return value of fgets().
As soon as you do not get back the original value of s
but NULL, you have effectively lost a pointer to allocated
memory. Replace this by
if (fgets(....)==NULL)
and free() s before the end of the program.
printf("error in fgets\n"); /*problem is HERE,this message is
printed,WHY?*/
else
printf("fgets get followings: %s \n", s);
}

fclose(p_file);
return 0;
}


Cheers
Michael
 
V

vijoeyz

Hi all:
my problem is in the comments of the code .
would u please give me some clue what 's the problem?
what u in advance.


/*******************************/
#include "stdio.h"
#include "malloc.h"
#include "assert.h"
int main(void)
{
FILE *p_file;
static char *filename="test";
char *s=NULL;
int c;
int num=0;


if ((p_file=fopen(filename,"w+"))==NULL) { /* does "w+" means your
can read & write the file? */
printf("cant't open file %s\n",filename);
}
else{
while ((c=getchar())!=EOF) {
if (fputc(c,p_file)!=EOF)
++num; /*# of character written*/


}
fflush(p_file);


}

It is a better idea to terminate if p_file is NULL here, because you
are using
fgets() after this.
if ((s=(char*)calloc(num,sizeof(*s)))==NULL) {
^^^^^^^^^
sizeof (*s) is 1...
printf("can't calloc enough memory\n");
}
else{


assert(p_file!=NULL); /*the file stores actually what i
input,ant the p_file is NOT NULL */
if((s=fgets(s,5,p_file))==NULL) /*i just get 5-1 character,and
make

.... and, you are reading more than 1 characters.
 
M

Michael Mair

It is a better idea to terminate if p_file is NULL here, because you
are using
fgets() after this.



^^^^^^^^^
sizeof (*s) is 1...

Right. We are calloc()ing num*1 bytes of storage.
what i


make

... and, you are reading more than 1 characters.

So what? As long as 5<=num everything is fine.
Probably you are confusing malloc() and calloc().

The produced memory leak is much worse.

-Michael
 
I

infobahn

Emerson said:
Hi all:

my problem is in the comments of the code .
would u please give me some clue what 's the problem?
what u in advance.

/*******************************/
#include "stdio.h"
#include "malloc.h"
#include "assert.h"

It's wiser to use <> delimiters for standard headers. Also,
you gain nothing by including the non-standard header "malloc.h"
instead of the standard header <stdlib.h>, so let's make it:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *p_file;
static char *filename="test";
char *s=NULL;
int c;
int num=0;

if ((p_file=fopen(filename,"w+"))==NULL) { /* does "w+" means your
can read & write the file? */

"w+" means "create text file for update; discard previous contents
if any" (source: K&R2, p242). If the file already exists and you
don't want to destroy it, use "r+" instead.
printf("cant't open file %s\n",filename);
}
else{
while ((c=getchar())!=EOF) {
if (fputc(c,p_file)!=EOF)
++num; /*# of character written*/

}
fflush(p_file);

This looks fine at first glance.
}

if ((s=(char*)calloc(num,sizeof(*s)))==NULL) {

You can lose the cast:

if((s = calloc(num, sizeof *s)) == NULL)

is quite sufficient.
printf("can't calloc enough memory\n");
}
else{

assert(p_file!=NULL); /*the file stores actually what i
input,ant the p_file is NOT NULL */

/* ##### (see below) */
if((s=fgets(s,5,p_file))==NULL) /*i just get 5-1 character,and make
sure the p_file has more than 5 character*/
printf("error in fgets\n"); /*problem is HERE,this message is
printed,WHY?*/


You haven't repositioned the file position indicator to the start
of the file. Above, where I've marked the code #####, add this line:

rewind(p_file);

I think it should work just fine after that, although admittedly
I haven't tested it.
 
L

Lawrence Kirby

It's wiser to use <> delimiters for standard headers.

Specifically #include <stdio.h> (for example) is guaranteed to get you the
standard header on a conforming hosted implementation, #include "stdio.h"
isn't.

Lawrence
 
D

dcorbit

Perhaps the OP meant something like this:

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#define Min(a,b) ((a) < (b) ? (a) : (b))

int main(int argc, char **argv)
{
FILE *p_file;
static char *filename = "test";
char *s = NULL;
int c;
unsigned character_count = 0;
char *pname = "This program";
static const unsigned pointless_moronic_constant = 5;
if (argc >= 1)
pname = argv[0];
if ((p_file = fopen(filename, "w+")) == NULL) {
perror("Program failure.");
printf("%s can't open file %s\n", pname, filename);
exit(EXIT_FAILURE);
} else {
while ((c = getchar()) != EOF) {
if (fputc(c, p_file) != EOF)
++character_count;
}
fflush(p_file);
}
/* The operator sizeof (*s) returns 1. It would take a pretty
major
* rewrite for it to be otherwise, since you use fgets() etc. */
if ((s = calloc(character_count, sizeof(*s))) == NULL) {
printf("%s can't allocated enough memory\n", pname);
} else {
assert(p_file); /* assert is useful only for debug runs
*/
if (p_file) {
rewind(p_file);
if ((s = fgets(s, Min(pointless_moronic_constant,
character_count), p_file)) == NULL)
printf("Error in fgets\n");
else
printf("fgets got the following: %s \n", s);
}
}
if (s)
free(s);
if (p_file)
fclose(p_file);
return 0;
}
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top