Reputation: 13
I wrote a c program meant to count the characters in a certain file.
int main(void) {
FILE *fp;
fp = fopen("txt.txt", "r");
char text;
int count;
while (fscanf(fp, "%c", &text) != EOF) {
count++;
}
printf("%d", count);
return 0;
}
I want to add a char array into it but for some reason it changes the value of my int type (count).
for example, if I run this program I get an output of 3549. Now, lets say I declare "char potato[5000]
" alongside my other char type. For some reason I get a completely different output of 159062601. Why is this and how do I prevent that?
Upvotes: 1
Views: 148
Reputation: 2940
You have several problems in your code. i will list them below:
c
programming we declare variables in the scope begin. and initialize them if we need so. you have a mixture of declerations and code.count
variable non initialized!! you have entered the while loop with garbage value in count. UB (Undefined behavior) - in each run you will get different values.fopen
!! you must check if the operating system succed in opening the file you have requested to manipulate.Now lets try to learn new topics regarding working with IO streams.
return value of function fscanf
The value
EOF
is returned if the end of input is reached before either the first successful conversion or a matchingfailure occurs
.EOF
is also returned if aread error
occurs, in which case the error indicator for the stream (see ferror(3)
) is set, anderrno
is set indicate the error.
This is how check if errors ocured while working with the file we are reading:
int ferror(FILE *stream);
The function ferror() tests the error indicator for the stream pointed to by stream, returning nonzero if it is set. The error indicator can only be reset by the clearerr() function.
And in this function bellow we get a human readble error, not just an errnor number!
explain_ferror
const char *explain_ferror(FILE *fp);
The explain_ferror function is used to obtain an explanation of an error returned by the ferror(3) system call. The least the message will contain is the value of strerror(errno), but usually it will do much better, and indicate the underlying cause in more detail.
The errno global variable will be used to obtain the error value to be decoded.
#include <stdlib.h>
#include <stdio.h>
#include <libexplain/ferror.h> /* for the non standard const char* explain_ferror(FILE* fp); */
int main(void)
{
FILE *fp;
char text;
int count = 0;
fp = fopen("txt.txt", "r");
if(fp == NULL)
{
perror("fopen failed"); /*write to standard error*/
exit(EXIT_FAILURE);
}
while (fscanf(fp, "%c", &text) != EOF)
{
++count;
}
if (ferror(fp)) /* nonzero return if error occured */
{
fprintf(stderr, "%s\n", explain_ferror(fp));
exit(EXIT_FAILURE);
}
printf("%d", count);
return 0;
}
Since the const char *explain_ferror(FILE *fp);
is not GNU standard function, i am posting a GNU standard functions in the code snippet below:
char *strerror(int errnum);
strerror
is standard library c function which returns a pointer to a string that describes the error code passed in the argument errnum
. Be aware that this function is not Thread safe
. for thread safe function use The strerror_r()
.
Return Value
The strerror(), function return the appropriate error description string, or an "Unknown error nnn" message if the error number is unknown.
Since POSIX.1-2001
and POSIX.1-2008
requires that a successful call to strerror() shall leave errno
unchanged, and note that, since no function return value is reserved to indicate an error, if we wishe to check for errors we should initialize errno to zero before the call (by calling void clearerr(FILE *stream);
, and then check errno after the call.
#include <string.h>
#include <errno.h>
#include <stdio.h>
...
clearerr(fp); /* clear previous seted errno */
while (fscanf(fp, "%c", &text) != EOF)
{
++count;
}
if (ferror(fp)) /* nonzero return if error occured */
{
fprintf(stderr, "%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
...
Finally:
man pages (or man7) or typing man <enter_string_here>
in terminal on linux shall clear all the q.marks.
for further reading go to:
Upvotes: 3
Reputation: 16540
The following proposed code:
fopen()
and for fscanf()
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
fp = fopen("txt.txt", "r");
if( ! fp )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
char text;
int count = 0;
while ( fscanf( fp, "%c", &text ) == 1 )
{
count++;
}
fclose( fp );
printf( "%d\n", count );
return 0;
}
Upvotes: 4