In C, "getc" reads only three lines from text file - c

My Code is HERE
int main(){
FILE *fp;
fp = fopen("dic.txt", "r");
while(getc(fp) != EOF){
if(getc(fp) == ' '){
printf("up ");
}
}
}
My dic.txt is HERE
dic.txt
my predict is that "up up up up "
because, there are four space " "
but it printed "up " only one
what is problem?

You are calling getc twice per iteration of the loop; one of these two calls compares the character to EOF, while the other call compares the character to ' '.
This has two consequences:
Your program will only print "up" for the spaces which are on even position, and will miss all spaces which are on odd position;
Your program might make one extra call to getc after reaching EOF the first time.
How to fix
You need to make a single call to getc per iteration of the loop. Save the character returned by getc to a local variable; then use this variable to check for spaces in the body of the loop, and to check for EOF in the condition of the loop.

You want this:
#include <stdio.h>
int main() {
FILE* fp;
fp = fopen("dic.txt", "r");
if (fp == NULL)
{
printf("Can't open file\n");
return 1;
}
int ch; // int is needed her, not char !!
while ((ch = getc(fp)) != EOF) { // read one char and check if it's EOF in one go
if (ch == ' ') {
printf("up ");
}
}
}
You need to call getc once only in the loop, otherwise you skip one out of two characters.
Bonus: you need to check if fopen fails.

Try Out This Code:
FILE *fp;
fp = fopen("dic.txt", "r");
int ch = getc(fp);
while(ch != EOF){
if(getc(fp) == ' '){
printf("up ");
}
}
return 0;

Related

How does following statement produce spaces?

What my program "upper" trying to do is making letters upper case. It gets a file from the commmand line as argv; then reads it afterwards it makes them uppercase.
An example: "i wonder if it works" in the example.txt file. In command line:
C:\Users\...>upper example.txt
I WONDER IF IT WORKS
This was the code I used first:
int main (int argc, char *argv[]){
FILE * fp;
int ch;
if ((fp = fopen (argv[1] , "r+")) == NULL) {
fprintf (stderr , "Can not be opened.");
exit(EXIT_FAILURE);
}
while((ch = getc(fp)) != EOF){
if (isalpha(ch))
putchar(toupper(ch));
else
putchar(' ');
}
fclose(fp);
return 0;
}
It works but I saw a more concise version which doesn't need the else statement.
while((ch = getc(fp)) != EOF){
putchar(toupper(ch));
}
And it puts the spaces between each word too. How is this possible?
From the documentation
int toupper(int c);
Converts c to its uppercase equivalent if c is a lowercase letter and has an uppercase equivalent. If no such conversion is possible, the value returned is c unchanged.

Writing and reading CSV file in C wierd output

I'm new to C language and I'm trying to save data to a .csv and read the same data in a very simple program.
char c;
FILE *fp;
fp = fopen("file.csv", "w+");
fprintf(fp, "Hello;World\nLine");
fclose(fp);
fp = fopen("file.csv", "r");
while (getc(fp) != EOF) {
printf("%c", getc(fp));
}
fclose(fp);
I don't know why the output is wrong:
el;ol
ie
Thanks in advance
Because you are reading a character in the loop condition (so it prints out every other one when printing), and reading another one when printing it out. Try this:
int ch;
while ((ch=getc(fp)) != EOF) {
printf("%c", ch);
}
Here:
while (getc(fp) != EOF) {
printf("%c", getc(fp));
}
You are calling getc() twice every time through the loop, but only printing one character. So you get half te hrces rm te fl n ls h ohr hl.

Read input from one file and write it to another file in C

I'm trying to read contents from a file "file.txt" and write each character from there to "copy.txt" but I get a weird character at the end of the "copy.txt" file.
I'm trying to open and close the two files and modify the body of the while loop in the program so that the character is no longer put to standard output (stdout).
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c;
FILE *from, *to;
from = fopen("file.txt", "r");
if (from == NULL)
{
perror("file.txt doesn't exist.");
exit(1);
}
to = fopen("copy.txt", "w");
if (to == NULL)
{
perror("copy.txt doesn't exist.");
exit(1);
}
do
{
c = getc(from);
putc(c, to);
}
while(c != EOF);
fclose(to);
fclose(from);
exit(0);
}
Your Problem lies in this loop:
do
{
c = getc(from);
putc(c, to);
}
while(c != EOF);
What you need to understand is the difference between a do-while and a while loop. A while loop will evaluate the expression BEFORE running the loop (thus the loop runs at least 0 times) and a do-while loop evaluates AFTER the loop circle (thus running at least one time).
So whats the problem? You read a character, write it to copy.txt, THEN evaluate if its EOF and exit the loop or not. Now, what happens when the last char is read from the file? The loop will run one more time, as the last character is NOT EOF. Your program will read one more character and write to the file. That is the character that you meant.
So in order to fix, you need to evaluate for EOF BEFORE writing. Here are two attempts, one that will keep your do-while loop and one that uses a while loop (more clear):
Do-While Attempt (not pretty and unneccessary if):
do
{
c = getc(from);
if (c != EOF) {
putc(c, to);
}
}
while(c != EOF);
While Attempt:
while ((c = getc(from)) != EOF) {
putc(c, to);
}

Entire file is not read in C (EOF occurs unexpectedly)

I am trying to print contents of a file with approximately 4000 characters.
Somehow the program records only the first 220 characters and terminates.
int main(void)
{
char ch = ' ', file_name[25], payload[3904];
FILE *fp;
printf("Enter the name of file you wish to see\n");
gets(file_name);
fp = fopen(file_name, "r"); // read mode
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name);
int gin = 0;
while ((ch = fgetc(fp)!=EOF))
{
printf("%d) %x \n",gin, ch);
payload[gin++] = ch;
}
printf("Also, value of gin is %d --->", gin);
getchar();
//...rest of the code
}
Here the value of gin is 220.
Just to check, I modified the while() condition to run for the exact number of characters in the file:
{
//...
while (gin<3904)
{
if ((ch = fgetc(fp)) == EOF) res++;//ADDED THIS TO COUNT NUMBER OF EOF's
printf("%d) %x \n",gin, ch);
payload[gin++] = ch;
//printf(" %x \n", payload[(gin - 1)]);
if (gin % 100 == 0)
{
printf("Also, value of res is %d --->", res); getchar();
getchar();
}
}
//...rest of the code
}
The value of gin reaches 3904, the value of res(no. of EOF's) is 3684, meaning that every character after the first 220 is being read as an EOF. The program starts reading FF after the first 220 character even though it is filled.
I think the code is fine, apart from the fact that you should change the ch to int.
fgetc() returns
If success, "the character read as an unsigned char cast to an int"
In failure, "EOF on end of file or error"
So, first, you have to change the ch to int, as some return values from fgetc() may not fit into a char.
Now, in the second case, you're not checking the return value of fgetc() against EOF to detect any error . You're simply taking the return value and trying to store those values into the array. Actually, when the end of file is reached, there is nothing more to be read, and all the further reads on the same file pointer will return you error.
It is most likely that those values. after 220 in your case are valid , at all.
So, to the statement in your question,
(EOF occurs unexpectedly)
is wrong. It occurs just fine, you're ignoring it and running into, well, trouble.
Note:
In your first snippet, you're doing two successive fgetc() calls, essentially discarding the result of the first one, and using the second one without any check.
Never use gets(). It suffers from buffer overflow issues. Always use fgets() instead.
the following code:
uses fgets() rather than the obsolete gets()
removed the newline from the user input
uses the proper size_t rather than int for indexing
is consistently indented
has modification to the printf statements to display size_t rather than int
compiles cleanly (which surprises me as payload is set but never used)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int ch = ' ';
char file_name[25];
char payload[3904];
FILE *fp;
printf("Enter the name of file you wish to see\n");
fgets(file_name, sizeof(file_name), stdin);
// remove trailing newline
char *newline = strstr(file_name, "\n" );
if (newline ) *newline = '\0';
fp = fopen(file_name, "r"); // read mode
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
// implied else, fopen successful
printf("The contents of %s file are :\n", file_name);
size_t gin = 0;
while ( ((ch = fgetc(fp)!=EOF)) && (sizeof(payload) > gin) )
{
printf("%ld) %x \n",gin, ch);
payload[gin++] = ch;
}
printf("Also, value of gin is %ld --->", gin);
getchar();
//...rest of the code
return(0);
}

Counting number of words with multiple whitespaces

I am trying to write a program that prints the number of words found in a text file. Words are defined as sequences of characters separated by any number of white space.
However, I am having a problem when there are multiple whitespaces because then it doesn't report the right number of words.
Here is my code so far:
#include <stdio.h>
int main()
{
FILE *fp;
char str;
int i=0;
/* opening file for reading */
fp = fopen("myfile.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
while(( str = fgetc(fp)) != EOF ) {
if (str == ' ')
++i;
}
printf("%d\n", i);
fclose(fp);
return(0);
}
myfile.txt is:
Let's do this! You can do it. Believe in yourself.
I'm not sure if I use fgets, fscanf, or fgetc.
Let's say I define whitespace as it is defined in the fscanf function when reading a string
It prints 14 which is not right. I'm not sure how to account for multiple whitespaces. In this case, whitespaces are any number of spaces between words.
Counting a whitespace only if it is not preceded by any other white space will do the trick.
#include <stdio.h>
int main()
{
FILE *fp;
char str;
char prevchar; //tracks the previous character
int i=0;
/* opening file for reading */
fp = fopen("myfile.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
prevchar='x'; //initialize prevchar to anything except a space
while(( str = fgetc(fp)) != EOF ) {
if (str == ' ' && prevchar!=' ') // update the count only if previous character encountered was not a space
++i;
prevchar=str;
}
printf("%d\n", i+1);
fclose(fp);
return(0);
}
Edit: The code assumes that words are separated by one or more spaces and does not cover all the corner cases like when sentences spread over multiple lines or when words are separated by comma and not spaces. But these cases can be covered by adding more conditions.
just use a little state diagram, two cases are, either you are inside a word, or you are outside a word
#include <stdio.h>
int main()
{
FILE *fp;
char str;
int i=0,inside_word =0;
/* opening file for reading */
fp = fopen("myfile.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
inside_word =0;
while(( str = fgetc(fp)) != EOF ) {
if (str == ' ' || str == '\n' || str == '\t')
inside_word = 0;
else if(inside_word == 0){
i++;
inside_word=1;
}
}
printf("%d\n", i);
fclose(fp);
return(0);
}
First thing comes into my mind is, add another while loop right after ++i to exhaust space characters.
And by the way, be careful with your terminology, you are not dealing with whitespaces you are just taking care of space characters. \t and \n are also whitespaces!
How about using regular expression such as '!\s+!' to replace with a single space ' ', then continue with your code

Resources