getc(fp) causing trouble - c

Here is my code.
#include<stdlib.h>
#include<stdio.h>
int main(int argc,char** argv)
{
char a;
a=9;
FILE * fp;
fp=fopen(argv[1],"r");
while(a!= EOF)
{
a=fgetc(fp);
printf("\n%d",a);
}
}
The output to this is alright but at the end I am getting a weird character with -1 (since I am printing integer value.
How to stop it at EOF only?
Also what is this character?

Besides the methods in the other answers, you can also do like this:
while ((a = fgetc(fp)) != EOF)
{
printf("%d\n", a);
}
Now you have a few alternative solutions. :)
Edit: As R.. so kindly reminds us, you also have to change the type of a to int.

You are printing the EOF character (the -1) as you do not check if EOF was encountered immediately after fgetc(). Change the structure of the loop to:
int a; /* not char, as pointed out by R... */
for (;;)
{
a = fgetc(fp);
if (EOF == a) break;
printf("\n%d", a):
}

You need to make a have type int, as that type is the return type of fgetc(), and is needed to represent EOF correctly.

Why don't you stop the while with this condition:
do {...}while(a != EOF)
I suppose that a got EOF value AFTER read it.
So, you do the cycle an extra time

Related

using char, cast to an int as array index to store frequency of "chars" in a textfile

Iam writing a simple program to store number of occurrence's of the various symbols in a text file. I am reading from this file using fgetc() and a file pointer. one char at a time. i set up my array outside my method like so
int frequency[MAX_SYMBOLS] = {0};
MAX_SYMBOLS is defined as being 255. I then read over the and try to count every time a particular character appears below is my method set_frequency()
void set_frequency()
{
int count = 0;
char c;
FILE *fp = fopen("file.txt","r");
while((c = fgetc(fp)) != EOF)
{
if(c != ' ' && c != '\n')
{
frequency[(int) c]++;
count++;
}
}
fclose(fp);
}
iam currently getting a segmentation fault for this not entirely sure why?
I think its an issue with the array index. or possibly the size of my file as it is rather large. If anyone can help that would be great as iam not great with c to be honest.
EDIT
the 'c' variable need to be an int not a char as that is what is returned from the fgetc() function. then I wont have to cast in the index value!!
In addition to the fact that EOF could not fit in a char, you have 2 potential problems:
MAX_SYMBOLS is smaller than 255, that are the character you can find using plane ascii.
char is a signed integer. If you read something > 0x7f it will be converted in a negative array index.
Try using an integer for reading to satisfy requirement for EOF. You'll also get guarantee that the code will never be negative, but in the range 0-255.
void set_frequency()
{
int count = 0;
int c;
FILE *fp = fopen("file.txt","r");
while((c = fgetc(fp)) != EOF)
{
if(c != ' ' && c != '\n')
{
frequency[c]++;
count++;
}
}
fclose(fp);
}
If happens that you have to use chars for similar issues use cast to force unsigned values:
frequency[(int)(unsigned char) c]++;

Write a program that reads input up to # and reports the number of times that the sequence ei occurs

Write a program that reads input up to # and reports the number of times that the sequence ei occurs
I have this question and I found a code here for this but I'm unable to figure out what the int c1 part does. Here's the code :
#include <stdio.h>
int main(void) {
int c;
int ei_count = 0;
while ((c = getchar())!= '#') {
if (c == 'e') {
int c1 = getchar();
if (c1 == 'i')
ei_count++;
}
}
printf("ei appeared %d times\n", ei_count);
return(0);
}
My question is, how does the if condition work? Can someone please explain ?
I'm new at C
The c1-part is a broken try at scanning the second part of ei, they could have reused c without introducing more errors.
Better alternative:
#include <stdio.h>
int main(void) {
int c, last = 0, ei_count = 0;
while ((c = getchar()) >= 0 && c != '#') {
ei_count += last && c == 'i';
last = c == 'e';
}
printf("ei appeared %d times\n", ei_count);
}
Corrected errors:
neither ei nor # recognized after e.
infinite loop on EOF / input error.
Random facts:
main has an implicit return 0; just before the closing brace.
getchar() returns an int, so it can return -1 on failure and an unsigned char converted to int on success. Always check for failure.
logical and comparison operators always return 0 or 1.
0 is logical false, all else is logical true.
return is not a function call: Use return 0; without parentheses.
That part you mentioned is a way to find a pattern like "ei". At the first moment the code try to find the 'e' character in a loop, and then, once it is found, the code checks if the next char is the letter 'i'. Case not, start again the loop to find another 'e' char.
This is not an good approach since there is no error verification during the getchar() operation and you can fall on a infinite loop.
Oversimplified, it's just a state machine.
Stepping through line-by-line:
while ((c = getchar())!= '#') {
Read input and assign it to the variable c. If that read in char is anything but #, execute the body of the while, otherwise jump over it.
if (c == 'e') {
If the read in character is an e, then we want to execute the internal block. If it's not, skip to the end of this block.
int c1 = getchar();
Read another character.
if (c1 == 'i') ei_count++;
If the new character is an i, then increment the counter of found items.
} close if (if e was found)
} close while.
It's worth pointing out there is a very clear flaw in the logic flow, however. Think about what happens if you have the input "eei".
In C, char and int data types are pretty much the same thing. In an assignment statement, the final result of the calculations are converted to the type of the variable being assigned to. Probably in this example, the author of this code assumed that the value returned by getchar() function which is of type int cannot be assigned to a char variable. You can use a char type for the c1 variable, since the getchar() function returns the ASCII code of the next character in the input, and the value is automatically converted to char during assingment. In the next if statement, you can easily compare the value of c1 with the character value i.
This code is a little bit buggy, for if you enter e# as an input, the program hangs. The reason is that c1 = getchar(); statement in the if block assigns '#' value to variable c1, and the comparison obviously fails, and at the next iteration of the while loop, getchar() returns a value after the '#' character in the input stream, which is a garbage value unless you entered more other characters after the '#' character.
Here's my code with a few fixes:
#include <stdio.h>
int main(void) {
char ch, next;
int ei_cnt = 0;
while((ch = getchar()) != '#') {
if(ch == 'e') {
next = getchar();
if(next == '#')
break;
if(next == 'i')
ei_cnt++;
}
}
printf("ei substring occured %d %s.\n", ei_cnt,
ei_cnt == 1 ? "time" : "times");
return 0;
}

calculation of the length of the file doesn't work

#include "stdio.h"
#include "stdlib.h"
int main()
{
FILE *fp;
int noOfLines =0;
char fname[]="Rtl_Prod_Id.txt";
printf(fname);
fp=fopen(fname,"r");
char ch;
//looping for every line
do {
ch=fgetc(fp);
if (ch=='\n')
noOfLines++;
} while(ch!=EOF);
//line before the last line
if (ch!='\n'&&noOfLines!=0)
noOfLines++;
fclose(fp);
printf("%d",noOfLines);
return 0;
}
I am just trying to calculate the number of lines in my file . The Same doesn't not return me any result .
What are the possible mistakes which i am doing
Environment : AIX and Compiler : CC
Thanks
Edit : My program compiles succesfully but while execute the .Out file it doesn't turn up anything
P.S : Although i got the answer . thanks to https://stackoverflow.com/users/434551/r-sahu . I had change char ch; to int ch; . but i wonder why ? What is wrong in char declaration ? . As i going to check for '\n' and EOF characters why integer then ?
The problem is that char on AIX is actually unsigned char.
fgetc() returns an int value and -1 is (typically) used to signal EOF. However, because unsigned char cannot be negative (EOF becomes 255), so the comparison ch != EOF will always be true and this causes an endless loop.
Defining int ch; fixes the problem; btw, this should have shown up during compilation if you use -Wall (show all compiler warnings).
This is a wild shot but changing the line
char ch;
to
int ch;
is appropriate. The return type of fgetc is int, not char.
You should use <...> instead of "..." to include system header files such as stdio.h or stdlib.h.
You should check the return value of fopen for possible error.
The return type of fgetc() is int, not char.
There is a logical flaw in your last line adaption. After the before do {} while loop, ch is EOF, it never will be '\n'. You need another flag to remember if there is any characters after the last '\n', and set it properly in your do {} while loop.
Here is a fixed version of your code, a little more flexible:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp;
int noOfLines, isRem, ch;
if (argc > 1) {
fp = fopen(argv[1],"r");
if (fp == NULL) {
perror("fopen");
exit(EXIT_FAILURE);
}
}
else {
fp = stdin;
}
noOfLines = 0;
isRem = 0;
//looping for every line
do {
ch = fgetc(fp);
if (ch != EOF)
isRem = 1;
if (ch == '\n') {
noOfLines++;
isRem = 0;
}
} while (ch != EOF);
//line before the last line
if (isRem)
noOfLines++;
if (argc > 1)
fclose(fp);
printf("%d\n", noOfLines);
exit(EXIT_SUCCESS);
}
Testing:
$ wc -l t000.c
44 t000.c
$ ./a.out t000.c
44
$ echo -e "abc\ndef" | ./a.out
2
$ echo -ne "abc\ndef" | ./a.out
2
I had change char ch; to int ch; . but i wonder why ? What is wrong in
char declaration ? . As i going to check for '\n' and EOF characters
why integer then ?
EOF has a value of -1, and is of type INT, hence ch must be of type INT too.
Also, the prototype of getchar() is
int getchar(void);
so the return of getchar() must always be checked with an integer type.
There is an inherent confusion of EOF, read more about it here

fgetc is always returning value 1

there is the following function:
void readAndPrint(FILE * f) {
int c;
while(c = fgetc(f) != EOF) {
printf("%d", c);
}
}
In the main() body I used the following code to use the above function:
FILE * pFile;
pFile=fopen ("myfile.txt","r");
readAndPrint(pFile)
;
Whatever I put into myfile.txt, the program prints out ones.
For example, for abc, 111 is printed out.
I know that c in the function should be declared int to properly compare it to EOF. Also, I expected an int code from the ASCII set for each char in the text file to be printed out (97 for a, ...). I cannot figure out why it prints out 'ones'... Does you know the reason why? Thank you in advance.
(c = fgetc(f) != EOF) - Here first fgetc(f) != EOF this condition is happening and the result 1 or 0 is assigned to c. Always a condition check returns TRUE(1) or FALSE (0).
Do while((c = fgetc(f)) != EOF)

Unsure about three simple functions with C programming

/* stringlength
* input: str, pointer to a string
* output: integer representing the length of string str,
* not counting the terminating character.
*
* You may NOT call ANY functions within this function.
*/
int stringlength(char *str)
{
// count the number of characters in str
int count=0,k;
for (k=0; str[k] != '\0';k++)
count++;
return count;
}
/* countchars
* inputs: character c, string str
* output: The number of instances of c in the string str
* You may not call ANY function calls within this function.
*/
int countchars(char c, char *str)
{
// count the number of times c is found in str
int k,count=0;
for (k=0;str[k]=='\0';k++)
{
if (str[k] == c)
count++;
else;
}
return count;
}
/* countlines
* input: char *filename - string containing the filename
* output: integer representing the number of lines in the file
*/
int countlines(char *filename)
{
// count the number of lines in the file called filename
FILE *f = fopen(filename,"r");
char ch;
int lines=0;
f = fopen(filename,"r");
do{
ch = fgetc(f);
if( ch == '\n')
lines++;
}while( ch != EOF );
return lines;
}
I need help with these three different functions that I am implementing in my program. I am a beginner so go easy on me, the countlines function is giving me the most trouble. If anyone could explain why not or why these functions will work, it would be greatly appreciated.
There are a number of problems in countlines():
You open the file twice, but overwrite the first FILE * value with the second, so there's no way you can close it. This is a minor problem.
The major problem is that the function fgetc() returns an int, not a char. In particular, EOF is a value different from every char.
The code does not close the file before returning. Generally, if you open a file in a function, then you should close it. If you don't, you have to pass the file pointer back to the calling code so that it can close it.
The do ... while loop is seldom correct for an input loop (a while loop testing at the top is almost always much cleaner and clearer) but at least you weren't using feof().
int countlines(char *filename)
{
FILE *fp = fopen(filename,"r");
int ch;
int lines = 0;
if (fp == 0)
return lines;
while ((ch = fgetc(fp)) != EOF)
{
if (ch == '\n')
lines++;
}
fclose(fp);
return lines;
}
When you use char instead, one of two things happens:
If your char type is signed, then a real character (often ÿ — y-umlaut, U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS) also matches EOF so you can stop reading before you reach end of file.
If your char type is unsigned, no value will ever match EOF so the loop will never stop.
In stringlength(), you have two variables count and k that are carefully kept at the same value; you only need one of the two.
Apart from raggedy indentation (endemic in the code shown — and definitely something to be avoided), and the unnecessary and pointless else; which does absolutely nothing, the code for countchars() looks OK (late addition) ... has the condition in the for loop inverted; it should be str[k] != '\0', of course.

Resources