I'm studying textfile topic in C and I have got a question: what can I use instead of __fpurge(stdin); but make this function work like __fpurge(stdin); and I am not allowed to include <stdlib.h> in this program. I have read this c - need an alternative for fflush but as long as I'm not allowed to #include <stdlib.h> so I can't use strtol.
void generateBill() {
FILE *fp, *fp1;
struct Bill t;
int id, found = 0, ch1, brel = 0;
char billname[40];
fp = fopen(fbill, "rb");
printf("ID\tName\tPrice\n\n");
while (1) {
fread(&t, sizeof(t), 1, fp);
if (feof(fp)) {
break;
}
printf("%d\t", t.pid);
printf("%s\t", t.pname);
printf("%d\t\t\t\n", t.pprice);
total = total + t.pprice;
}
printf("\n\n=================== Total Bill Amount %d\n\n", total);
fclose(fp);
if (total != 0) {
//__fpurge(stdin);
printf("\n\n\n Do you want to generate Final Bill[1 yes/any number to no]:");
scanf("%d", &ch1);
if (ch1 == 1) {
brel = billFileNo();
sprintf(billname, "%s%d", " ", brel);
strcat(billname, "dat");
fp = fopen(fbill, "rb");
fp1 = fopen(billname, "wb");
while (1) {
fread(&t, sizeof(t), 1, fp);
if (feof(fp)) {
break;
}
fwrite(&t, sizeof(t), 1, fp1);
}
fclose(fp);
fclose(fp1);
fp = fopen(fbill, "wb");
fclose(fp);
}
total = 0;
}
}
for a replacement for __fpurge(stdin) suggest:
int ch;
while( (ch = getchar() ) != EOF && ch != '\n' ){;}
which only requires #include <stdio.h>
__fpurge is a non-standard function only available on some systems (glibc 2.1.95, IBM zOS...) that discards input read into the stream buffer not yet consumed by getc().
As explained in the linux manual page, Usually it is a mistake to want to discard input buffers.
You read user input with scanf(), which stops scanning input when the requested conversion is completed, for example %d stops reading the characters typed by the user when it reads a character that cannot continue the number and leaves this character in the input stream. Since stdin is usually line buffered when attached to a terminal, you should just read and discard any remaining bytes in the line input by the user after you process the input.
Here is a simple function for this purpose:
int flush_input(FILE *fp) {
int c;
while ((c = getc(fp)) != EOF && c != '\n')
continue;
return c;
}
You would call this function after processing user input and you should test the return value of scanf() to ensure the user input had the expected syntax.
Here is a modified version of you function:
#include <errno.h>
#include <string.h>
// return a non zero error code in case of failure
int generateBill(void) {
FILE *fp, *fp1;
struct Bill t;
int id, found = 0, ch1, brel = 0;
char billname[40];
fp = fopen(fbill, "rb");
if (fp == NULL) {
fprintf(sdterr, "cannot open %s: %s\n", fbill, strerror(errno));
return 1;
}
printf("ID\tName\tPrice\n\n");
while (fread(&t, sizeof(t), 1, fp) == 1) {
printf("%d\t", t.pid);
printf("%s\t", t.pname);
printf("%d\t\t\t\n", t.pprice);
total = total + t.pprice;
}
printf("\n\n=================== Total Bill Amount %d\n\n", total);
if (total != 0) {
int res;
printf("\n\n\n Do you want to generate Final Bill[1 yes/any number to no]:");
while ((res = scanf("%d", &ch1)) == 0) {
fprintf("Invalid input. Try again\n");
flush_input(stdin);
}
flush_input(stdin);
if (res == EOF) {
fprintf("premature end of file on input\n");
fclose(fp);
return 2;
}
if (ch1 == 1) {
brel = billFileNo();
snprintf(billname, sizeof billname, "bill-%d-dat", brel);
rewind(fp);
fp1 = fopen(billname, "wb");
if (fp1 == NULL) {
fprintf(sdterr, "cannot open %s: %s\n", billname, strerror(errno));
fclose(fp);
return 1;
}
while (fread(&t, sizeof(t), 1, fp) == 1) {
fwrite(&t, sizeof(t), 1, fp1);
}
fclose(fp1);
}
}
fclose(fp);
return 0;
}
Related
I'm trying to copy words from one file to another, but the words must begin with the given letter. It's working but doesn't copy every word that matches.
#include <stdio.h>
int main() {
FILE *f = fopen("words.txt", "r");
FILE *f2 = fopen("words_copy.txt", "a+");
char usr;
printf("enter letter: ");
scanf("%c", &usr);
char buffer[255];
char ch, ch2;
while ((ch = fgetc(f)) != EOF) {
ch2 = fgetc(f);
if (ch2 == usr && ch == '\n') {
fputc(ch2, f2);
fgets(buffer, sizeof(buffer), f);
fputs(buffer, f2);
}
}
return 0;
}
Words.txt contains:
adorable aesthetic alluring angelic appealing arresting attractive
blooming charismatic charming cherubic chocolate-box classy contagious
cute dazzling debonair decorative delectable delicate distinguished
enchanting enticing eye-catching glamorous glossy good-looking
gorgeous infectious lovely lush magnetic magnificent majestic melting
mesmerizing noble picturesque poetic prepossessing shimmering striking
stunning winsome
every word is in next line,
when I'm running the program and giving the letter m words_copy.txt contains only:
magnificent melting
How to fix to copy every word with matching letter?
The test in the loop is incorrect: you check the first letter after a newline and output the line if there is a match. With this logic:
you cannot match the first word in the file
you only match words starting with usr
and the word following a match is ignored
Furthermore, you ch and ch2 should be defined with type int to match EOF reliably, you should test for fopen failure and close the files after use.
You should use a simpler approach:
read a word
test if it contains the letter
output the word if it matches
Here is a modified version:
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char usr;
char buffer[256];
int ch = 0;
size_t pos;
FILE *f = fopen("words.txt", "r");
if (f == NULL) {
fprintf(stderr, "cannot open words.txt: %s\n", strerror(errno));
return 1;
}
FILE *f2 = fopen("words_copy.txt", "a+");
if (f2 == NULL) {
fprintf(stderr, "cannot open words_copy.txt: %s\n", strerror(errno));
fclose(f);
return 1;
}
printf("enter letter: ");
if (scanf(" %c", &usr) != 1) {
fprintf(stderr, "missing input\n");
fclose(f);
fclose(f2);
return 1;
}
while (ch != EOF) {
pos = 0;
/* read a word, stop at whitespace and end of file */
while ((ch = fgetc(f)) != EOF && !isspace(ch)) {
if (pos + 1 < sizeof(buffer))
buffer[pos++] = (char)ch;
}
buffer[pos] = '\0';
/* test for a match */
if (strchr(buffer, usr)) {
/* output matching word */
fprintf(f2, "%s\n", buffer);
}
}
fclose(f);
fclose(f2);
return 0;
}
I'm learning about file i/o in C language and I wrote this program that reads a file, and then for every even number found, it has to print * to the screen.
My problem is that my program keeps printing * forever.
I have tried different ways,some from this website, but I can't seem to understand how to read until end of a text file using EOF.
I want to learn how to read a text file until the end of the file please.
How do I read until the end of a text file? EOF in C.
int main(void)
{
int num;
FILE *ifp;
ifp = fopen("numbers.txt", "r" );
if(ifp == NULL)
{
exit(1);
}
do
{
fscanf(ifp, "%d", &num);
if(num%2 == 0)
{
printf("*\n");
}
} while(num != EOF);
fclose(ifp);
return 0;
}
you need to check the result of the scanf
do
{
int result;
result = fscanf(ifp, "%d", &num);
if(result == EOF) break;
if(result != 1)
{
printf("scanf error\n");
break;
}
if(num%2 == 0)
{
printf("*\n");
}
} while(1);
Instead, you should try while loop.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int num;
FILE *ifp;
ifp = fopen("numbers.txt", "r" );
if(ifp == NULL)
{
perror("Read");
exit(1);
}
while(fscanf(ifp, "%d ", &num) != EOF)
{
if(num % 2 != 0) // For every odd number.
{
printf("*\n");
}
}
fclose(ifp);
return 0;
}
Have you tried this:
while (!feof(ifp)) {
if (fscanf(ifp, "%d ", &num) > 0) {
if(num % 2 != 0) // For every odd number.
{
printf("*\n");
}
}
}
It's doing this because while(num != EOF) is testing whether int num, the number read from the file, is EOF, rather than whether the end of file has been reached.
To test whether the EOF flag has been set on FILE *ifp, use while(!feof(ifp)) instead.
Im trying to read a text file into an array of structs, but when trying to print the array, the struct is empty. The printing function works fine and I think the problem is in getRawData.
struct student
{
char ID[MAXID + 1];
char f_name[FIRST_NAME_LENGTH + 1];
char s_name[LAST_NAME_LENGTH + 1];
int points[MAXROUNDS];
};
//main//
case 'W':
if(save(array, len) == 0);
{
printf("Data saved.\n");
}
break;
case 'O':
if(getRawData(array, len));
{
printf("File read.\n");
}
break;
int save(struct student *h, int num_students)
{
char name[20];
printf("Enter file name: " );
scanf("%s", name); // Read in filename
FILE *output = fopen(name, "w"); // open the file to write
if (!output) {
return -1; // error
}
for (int i = 0; i < num_students; ++i)
{
fprintf(output, "%s %s %s \n", h[i].f_name, h[i].s_name, h[i].ID);
for(int j = 0; j < MAXROUNDS; j++)
{
fprintf(output, "%d\n", h[i].points[j]);
}
printf("Information of student %s %s (%s) written into file %s\n", h[i].s_name, h[i].f_name, h[i].ID, name);
}
fclose(output); // close
return 0;
}
int getRawData(struct student *records)
{
int i;
int nmemb; // amount of structs
char name[20];
printf("Name of the file to be opened: \n");
scanf("%s", name);
FILE *outtput = fopen(name, "r");
int ch=0;
int lines=0;
if (outtput == NULL);
return 0;
lines++;
while(!feof(outtput))
{
ch = fgetc(outtput);
if(ch == '\n')
{
lines++;
}
}
nmemb = lines / 7;
for(i = 0; i < nmemb; i++) {
fscanf(outtput, "%s %s %s", records[i].f_name, records[i].s_name, records[i].ID);
for(int j = 0; j < MAXROUNDS; j++)
{
fscanf(outtput, "%d\n", &records[i].points[j]);
}
}
printf("%d", lines);
return i;
}
So my goal is to get the data from the file and write it over whatever there is stored in the struct array. I would appreciate some help as I have been working on this for way too long.
Look at this code in getRawData(), first you are reading file to identify total number of lines:
while(!feof(outtput))
{
ch = fgetc(outtput);
if(ch == '\n')
.....
.....
due to this the file stream pointer pointing to EOF and after this, in the for loop, you are doing:
for(i = 0; i < nmemb; i++) {
fscanf(outtput, "%s %s %s", records[i].f_name, records[i].s_name, records[i].ID);
.....
.....
Here, the fscanf() must be returning the EOF because there is nothing remain to read from stream file. You should check the return value of fscanf() while reading file.
You should reset the pointer to start of file before reading it again. You can use either rewind(ptr) or fseek(fptr, 0, SEEK_SET). Below is a sample program to show you what is happening in your code and how the solution works:
#include <stdio.h>
int main (void) {
int ch;
int lines = 0;
char str[100];
FILE *fptr = fopen ("file.txt", "r");
if (fptr == NULL) {
fprintf (stderr, "Failed to open file");
return -1;
}
while (!feof(fptr)) {
ch = fgetc (fptr);
if(ch == '\n') {
lines++;
}
}
printf ("Number of lines in file: %d\n", lines);
printf ("ch : %d\n", ch);
printf ("Now try to read file using fscanf()\n");
ch = fscanf (fptr, "%s", str);
printf ("fscanf() return value, ch : %d\n", ch);
printf ("Resetting the file pointer to the start of file\n");
rewind (fptr); // This will reset the pointer to the start of file
printf ("Reading file..\n");
while ((ch = fscanf (fptr, "%s", str)) == 1) {
printf ("%s", str);
}
printf ("\nch : %d\n", ch);
fclose (fptr);
return 0;
}
The content of file reading in the above program:
Hello Vilho..
How are you!
Output:
Number of lines in file: 2
ch : -1
Now try to read file using fscanf()
fscanf() return value, ch : -1
Resetting the file pointer to the start of file
Reading file..
HelloVilho..Howareyou!
ch : -1
Here you can see, the first ch : -1 indicate that the file pointer is at EOF and if you try to read you will get EOF because there is nothing left to read. After resetting file pointer, you can see fscanf() is able to read file.
You should not use while (!feof(file)). Check this.
I have copied the contents of a file to another file and I am trying to get the line, word, and character count. The code I have right now displays the number of lines and words in the file content. Now I need to display the character count but I am unsure of how to do that. I am guessing a for loop? But I am not sure.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAX_WORD_LEN 100
#define MAX_LINE_LEN 1000
#define ipsumFile "Lorem ipsum.txt"
#define ipsumCopy "Lorem ipsum_COPY.txt"
int wordCount(FILE *fp);
int charCount(FILE *fp);
int sendContentTo(FILE *fp, FILE *out);
int getWordAt(FILE *fp, int pos, char *word);
int appendToFile(char *fileName, char *newText);
int main(void)
{
FILE *fp, *fp2; //"file pointer"
int ch; //place to store each character as read
//open Lorem ipsum.txt for read
if ((fp = fopen(ipsumFile, "r")) == NULL)
{
fprintf(stdout, "Can't open %s file.\n", ipsumFile);
exit(EXIT_FAILURE);
}
//open Lorem ipsumCopy for writing
if ((fp2 = fopen(ipsumCopy, "w+")) == NULL)
{
fprintf(stdout, "Can't open %s file.\n", ipsumCopy);
exit(EXIT_FAILURE);
}
//print out and count all words in Lorem ipsum.txt
int numOfWords = wordCount(fp);
//print out and count all lines in Lorem ipsum.txt
int numOfLines = sendContentTo(fp, stdout);
//copy the content of Lorem ipsum.txt into a new file (ipsumCopy)
numOfLines = sendContentTo(fp, fp2);
fclose(ipsumFile);
fclose(ipsumCopy);
// close Lorem ipsum.txt
if (fclose(fp) != 0)
fprintf(stderr, "Error closing file\n");
if (fclose(fp2) != 0)
fprintf(stderr, "Error closing copy\n");
return 0;
}
int sendContentTo(FILE *in, FILE *out)
{
fprintf(stdout, "Performing file copy...\n\n");
//start at the beginning of the file
rewind(in);
// array to hold one line of text up to 1000 characters
char line[MAX_LINE_LEN];
int lineCount = 0;
// read one line at a time from our input file
while (fgets(line, MAX_LINE_LEN, in) != NULL)
{
//send line we just read to output.
fprintf(out, "%s", line);
//count the lines
lineCount++;
}
fprintf(stdout, "\nFinished line count.\n");
fprintf(stdout, "Count is: %d.\n\n", lineCount);
// Return how many text lines
// we've processed from input file.
return lineCount;
}
// Read content from file one character at a time.
// Returns number of total characters read from the file.
int charCount(FILE *fp)
{
fprintf(stdout, "Performing char count...\n\n");
rewind(fp);
int charCount = 0;
char ch;
//print out each character, and return the
// number of characters in the file.
fprintf(stdout, "\nFinished character count. \n");
fprintf(stdout, "Count is: %d. \n\n", charCount);
return charCount;
}
// Read content from file one word at a time.
// Returns number of total words read from the file.
int wordCount(FILE *fp)
{
fprintf(stdout, "Performing word count...\n\n");
rewind(fp);
char word[MAX_WORD_LEN];
int wordCount = 0;
while (fscanf(fp, "%s", word) == 1)
{
// Send entire word string
// we just read to console
puts(word);
//count the word
wordCount++;
}
fprintf(stdout, "\nFinished word count.\n");
fprintf(stdout, "Count is: %d.\n\n", wordCount);
return wordCount;
}
You don't need to write different function for counting the number of lines, words, and characters in a file. You can do it in a single parsing of file character by character and while parsing, in order to copy the content of file to another file, you can write the characters to another file. You can do:
#include <stdio.h>
#include <stdlib.h>
int count_and_copy(const char * ipsumFile, const char * ipsumCopy)
{
unsigned int cCount = 0, wCount = 0, lCount = 0;
int incr_word_count = 0, c;
FILE *fp, *fp2;
if ((fp = fopen(ipsumFile, "r")) == NULL)
{
fprintf(stdout, "Can't open %s file.\n", ipsumFile);
exit(EXIT_FAILURE);
}
if ((fp2 = fopen(ipsumCopy, "w+")) == NULL)
{
fprintf(stdout, "Can't open %s file.\n", ipsumCopy);
exit(EXIT_FAILURE);
}
while((c = fgetc(fp)) != EOF)
{
fputc(c, fp2); // write character c to the copy file
cCount++; // character count
if(c == '\n') lCount++; // line count
if (c == ' ' || c == '\n' || c == '\t')
incr_word_count = 0;
else if (incr_word_count == 0) {
incr_word_count = 1;
wCount++; // word count
}
}
fclose (fp);
fclose (fp2);
printf ("Number of lines : %u\n", lCount);
printf ("Number of words : %u\n", wCount);
printf ("Number of characters : %u\n", cCount);
return 0;
}
int main()
{
/* Assuming, you want to count number of lines, words
* and characters of file1 and copy the contents of file1
* to file2.
*/
count_and_copy("file1", "file2");
return 0;
}
I suppose that the following approach will work:
void *cw(const char *fname)
{
FILE *f = fopen(fname, "r");
if (f == NULL) {
fprintf(stderr, "fopen(%s): %s\n", fname, strerror(errno));
exit(EXIT_FAILURE);
}
int bc = 0; /* bytes counter */
int wc = 0 ; /* words counter */
int nlc = 0; /* new lines counter */
const int in_word_state = 0;
const int out_word_state = 1;
int state = out_word_state;
int c = 0;
for (;;) {
c = fgetc(f);
if (ferror(f) != 0) {
perror("fgetc");
goto error;
}
if (feof(f))
break;
if (c == '\n')
nlc++;
if (c == ' ' || c == '\t' || c == '\n')
state = out_word_state;
if (state == out_word_state) {
state = in_word_state;
wc++;
}
bc++;
}
if (fclose(f) == EOF) {
perror("fclose");
goto error;
}
printf("w: %d, c: %d, l:%d\n", wc, bc, nlc);
error:
if (f != NULL) {
if (fclose(f) == EOF) {
perror("fclose");
}
}
exit(EXIT_FAILURE);
}
I need to make a program that prompts the user for the name of two text files which will be read in and displayed on screen followed by their statistics, such as number of characters, words and lines. I've managed to get it all working apart from the statistics part. They don't seem to be counting up and I think it's something to do with the while statements that I've used. Any help would be great :)
code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main() {
// declaring variables
FILE *fp;
int charcount = 0, wordcount = 0, linecount = 0;
int character;
char first[50];
char second[50];
char ch[200];
// asking the user for the file names and scanning the names they enter as txt files
printf(" Enter the first file name: ");
scanf("%s", first);
strcat(first, ".txt");
printf(" Enter the second file name: ");
scanf("%s", second);
strcat(second, ".txt");
// opening the file stream
fp = fopen(first, "r");
// if the file cannot be reached, display error
if (fp == NULL) {
printf("File cannot be opened: %s\n", first);
return 0;
}
// reading and printing the file into the program
printf("\n---FIRST FILE---\n");
while (!feof(fp)) {
fgets(ch, 200, fp);
puts(ch);
}
// counting the characters, words and lines until the program is finished
while ((character = getc(fp)) != EOF) {
if (character == '-')
{
charcount++;
}
if (character == ' ')
{
wordcount++;
}
if (character == '\n')
{
linecount++;
}
}
// closing the stream
fclose(fp);
// printing the number of characters, words and lines
printf("\n Characters: %d \n Words: %d\n Lines: %d\n\n\n", charcount, wordcount, linecount);
//---------SECOND FILE----------//
// opening the stream
fp = fopen(second, "r");
// reading and printing the file into the program
printf("\n---SECOND FILE---\n");
while (!feof(fp)) {
fgets(ch, 200, fp);
puts(ch);
}
// counting the characters, words and lines until the program is finished
while ((character = getc(fp)) != EOF) {
if (character == '-')
{
charcount++;
}
if (character == ' ')
{
wordcount++;
}
if (character == '\n')
{
linecount++;
}
}
// closing the stream
fclose(fp);
// printing the number of characters, words and lines
printf("\n Characters: %d \n Words: %d\n Lines: %d\n\n", charcount, wordcount, linecount);
}
Imagine that you're using one of those text editors to open your file and moving the caret/cursor is the only way to navigate. Your first goal is to navigate through the whole content and display it. That's what the loop below does:
while(!feof(fp)){
fgets(ch, 200, fp);
puts(ch);
}
The !feof(fp) moved the cursor to the end of the file so you could read it all.
If you have to count chars then you need to navigate back to somewhere in your file. Since you want statistics from the whole txt, then you could simply use rewind(fp) or fseek(fp, 0, SEEK_SET) before your second loop to move the cursor back to the begin.
I recommed using fseek() because it will clear the end of file indicator.
Take a closer look here.
I finally got it to work, if anyone is interested the final code is here:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main() {
// declaring variables
FILE *fp;
int charcount = 0, wordcount = 0, linecount = 1;
int charcount2 = 0, wordcount2 = 0, linecount2 = 1;
int character;
char first[50];
char second[50];
char ch[200];
// asking the user for the file names and scanning the names they enter as txt files
printf(" Enter the first file name: ");
scanf("%s", first);
strcat(first, ".txt");
printf(" Enter the second file name: ");
scanf("%s", second);
strcat(second, ".txt");
// opening the file stream
fp = fopen(first, "r");
// if the file cannot be reached, display error
if (fp == NULL) {
printf("File cannot be opened: %s\n", first);
return 0;
}
// reading and printing the file into the program
printf("\n---FIRST FILE---\n");
while (!feof(fp)) {
fgets(ch, 200, fp);
fputs(ch, stdout);
}
// counting the characters, words and lines until the program is finished
fseek(fp, 0, SEEK_SET);
while ((character = fgetc(fp)) != EOF) {
if (character == EOF)
break;
{
charcount++;
}
if (character == ' ' || character == '.')
{
wordcount++;
}
if (character == '\n')
{
linecount++;
}
}
// closing the stream
fclose(fp);
// printing the number of characters, words and lines
printf("\n Characters: %d \n Words: %d\n Lines: %d\n\n\n", charcount, wordcount, linecount);
//---------SECOND FILE----------//
// opening the stream
fp = fopen(second, "r");
// reading and printing the file into the program
printf("\n---SECOND FILE---\n");
while (!feof(fp)) {
fgets(ch, 200, fp);
fputs(ch, stdout);
}
// counting the characters, words and lines until the program is finished
fseek(fp, 0, SEEK_SET);
while ((character = getc(fp)) != EOF) {
if (character == EOF)
break;
{
charcount2++;
}
if (character == ' ' || character == '.')
{
wordcount2++;
}
if (character == '\n')
{
linecount2++;
}
}
// closing the stream
fclose(fp);
// printing the number of characters, words and lines
printf("\n Characters: %d \n Words: %d\n Lines: %d\n\n", charcount2, wordcount2, linecount2);
}
counting sample
#include <stdio.h>
#include <ctype.h>
typedef struct statistics {
size_t charcount, wordcount, linecount;
} Statistics;
Statistics count_cwl(FILE *fp){
size_t c = 0, w = 0, l = 0;
int ch;
char prev = ' ';
while((ch = getc(fp)) != EOF){
++c;
if(isspace(prev) && !isspace(ch)){
++w;//need to delete punctuation marks ?
}
if(ch == '\n'){
++l;
}
prev = ch;
}
if(prev != '\n')//There is no newline at the end of the file
++l;
return (Statistics){ c, w, l};
}
int main(void) {
char filename[50] = "test.c";
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
printf("File cannot be opened: %s\n", filename);
return -1;
}
Statistics stat = count_cwl(fp);
fclose(fp);
printf("\nCharacters: %zu\nWords: %zu\nLines: %zu\n", stat.charcount, stat.wordcount, stat.linecount);
}