Finding number of characters,words and lines in a text file - c

Here is the .c file followed by the functions in my .h file
#include <stdio.h>
#include "functions.h"
#define INPUT_FILE "C:/Users/user/Desktop/test.txt"
int main(){
FILE *text_file;
int num_characters, num_words, num_lines;
text_file = fopen(INPUT_FILE,"r");
if(text_file == NULL){
printf("!!-------ERROR OPENING FILE------!!\nclosing program....");
return 0;
}
num_characters = read_characters(text_file);
num_words = read_words(text_file);
num_lines = read_lines(text_file);
printf("Number of Characters: %d\nNumber of Words: %d\nNumber of Lines: %d\n",num_characters,num_words,num_lines);
return 0;
}
#include <stdio.h>
#include "functions.h"
#define INPUT_FILE "C:/Users/Lott-kerby/Desktop/test.txt"
#ifndef FUNCTIONS_H_
#define FUNCTIONS_H_
#include <stdio.h>
int read_characters(FILE *text_file){
int i;
int char_count = 0;
while((i = fgetc(text_file)) !=EOF)
char_count++;
return char_count;
}
int read_words(FILE *text_file){
char j;
int word_count = 0;
while((j = fgetc(text_file)) != EOF){
if(j == ' ')
word_count++;
}
return word_count;
}
int read_lines(FILE *text_file){
char k;
int line_count = 0;
while((k = fgetc(text_file)) != EOF){
if(k == '\n')
line_count++;
}
return line_count;
}
The goal is to find the number of characters words and lines in the text file. I get the correct number of characters when i run but I get the incorrect number of words and lines. The text file I am using is as follows:
word
word
word
with this .txt my program out put is:
Number of characers:14
NUmber of words: 0
Number of Lines: 0
any help would be greatly appreciated. The "words" are on their own line each in my text file.

Well you count the nunmber of words by counting the number of spaces because you assume there is a space between every word. but in your example input file there are no spaces.
So you may want to add a check for space OR new line.
Also you may want to return word_count+1 and line_count+1 because a single line without a newline should return 1. And the same is true for a single word with no space
EDIT: oouuhh and now I see that you read the file multiple times without resetting the file pointer so fgetc will always instantly return EOF in read_words() and read_lines() ... reset it using
rewind ( text_file );

Related

How to add a sentence to end of a specifics line in text file using C?

i have a text file that includes words in each line like TEST, TEST1, TEST! and i have to use 3 proccess to check these words.
Proccess one should check if the word consists of only letters.
proccess two should check if the word contains numbers,
proccess three should check if the word contains special characters.
Imagine that first line in text file is the word "TEST". Proccess one, should add "-Only Letters-" to end of line. These operations should be applied on the same txt file. I wrote this code:
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
int main()
{
char *filename = "kaynak.txt";
FILE *fp = fopen(filename, "rb+");
if (fp == NULL)
{
printf("Error: file not exist! %s", filename);
return 1;
}
char ch;
char line[10000];
bool write = false;
char sayi[10000] = "-Sayi var -";
while(fgets(line,sizeof(line),fp) != NULL){
int i = 0;
while(line[i] != '\0')
{
if(line[i] >= '0' && line[i] <= '9')
{
write = true;
printf("Number find\n");
}
i++;
}
if(write == true)
{
fputs("- Number - \n", fp);
write = false;
}
}
fclose(fp);
return 0;
}
This code replaces these lines:
2
Mart'ta
sunu8lan
in my sample text file with:
2
- Number -
u8lan
but it should be like this:
2 - Number -
Mart'ta
sunu8lan - Number -
How can i fix my algorithm?

Using a struct and dynamically allocated memory to write all the lines from a text file in C

I have written a program in C to represent a quiz game. Each question is an individual line of a text file. I am using a struct to represent the array of questions. It begins by taking some user input, then counts the amount of text lines in the file. It then allocated the amount of memory needed for the structs before reading each line of the file into the struct. When I print out the elements in the struct it prints out 20 lines of errors instead of the file values. What am I doing incorrectly? I have included a screenshot of some of lines of the file also.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define filepath "Questions_Answers"
#define CAPACITY 120
typedef struct
{
char* questions;
} Lines;
int setupGame(int *difficulty);
int main() {
int difficulty; //Set difficulty out of ten of the quiz
int numberOfLines = 0; //Set the number of lines counted in the file initially to zero
int question_length;
char answer[20];
char c;
//Calls setup game function which sets the difficulty
difficulty = setupGame(&difficulty);
FILE* fPointer = fopen(filepath, "r"); //Points to the address of a File not yet known
//If the file has no content, print error and end program
if (fPointer == NULL) {
perror("Error opening file");
return -1;
}
// Extract characters from file and store in character c
for (c = getc(fPointer); c != EOF; c = getc(fPointer)) {
if (c == '\n') // Increment count if this character is newline
numberOfLines++;
}
numberOfLines = numberOfLines + 1;
printf("Number of questions in quiz - %d\n", numberOfLines);
Lines *lines = malloc(sizeof(Lines) * numberOfLines); // allocate memory for questions
for (int i = 0; i < numberOfLines; i++) {
int lengthOfQuestion = 150;
lines[i].questions = malloc(sizeof(char) * (lengthOfQuestion + 1));
fscanf(fPointer, "%s", lines[i].questions);
printf("%s\n", lines[i].questions);
}
fclose(fPointer);
for (int i = 0; i < numberOfLines; i++) {
free(lines[i].questions);
}
free(lines);
return 0;
}
You have to fclose(fPointer); then reopen before you want to get questions from the file.
fclose(fPointer);
fPointer = fopen("input.txt", "r");
fscanf reads word by word not whole the line. You should use fgets() or getline().
I see in your code, you init the length of all questions by 150
int lengthOfQuestion = 150;
So, i think, it's easier when you declare the struct (you can use pointer if you want):
typedef struct
{
char questions[150];
} Lines;
You should use one loop for storing and increasing the number of lines. The code will be more readable. For example:
char line[150];
lines = malloc(sizeof(Lines));
if(!lines) {// handle the error}
while (fgets(fPointer, sizeof(line), line)) {
strcpy(lines[numberOfLines].question, line);
numberOfLines++;
lines = realloc(lines, sizeof(Lines) * numberOfLines);
if(!line) {// handle the error}
}

How do I read a number from a file to get the size in c

For an assignment I must create 2 files each with a number that has more than 100 digits. I can do this well, but when it comes time to finding out exactly how many digits are int the file I am stumped I have tried fgets(), but I do not think that I am handling this well. Any help is greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#include <stdio.h>
int getc(FILE *stream);
int getchar(void);
This is not really necissary to my problem but it is part of my code eventually I will need to get the size of each number and pass them as parameters here:
int * add(int * a,int s_a,int * b,int s_b){
if(s_b<s_a){
int tmp_s;
int * tmp_a;
tmp_s=s_a;
s_a=s_b;
s_b=tmp_s;
tmp_a=a;
a=b;
b=tmp_a;
}
int * out= (int *)malloc (sizeof(int)*(s_b+1));
int i, carry,sum;
carry=0;
for(i=0;i<s_a;i++){
sum=((a[i])+b[i]%10)+carry;
carry=(a[i]+b[i])/10;
out[i]=sum;
}
for(i;i<s_b;i++){
sum=(b[i]+carry)%10;
carry=(b[i]+carry)/10;
out[i]=sum;
}
out[i]=carry;
return out;
}
This is where I am adding the random numbers to the file and works I do not add spaces because It is supposed to all be one very long number. Although I have the size in this function that is not the purpose of this function and the print statement will be commented out once the next function is working properly.
void addrandomNums(char * fileName){
srand ( time(NULL) );
FILE *ffp;
ffp=fopen(fileName,"w");//if the file exsisists then we erase and write
new stuff
int sizeOfNum=rand()%10000+100;//the size of the number will be from 100-10099(I think)the instructions said a number greater than 100 digits so I tried to make this as wide of a range as possible
printf("Size of the number for this file is: %d digits \n",sizeOfNum);
for(int i=1;i<sizeOfNum;i++){
fprintf(ffp,"%d", rand() % 10);//adds a number from 0-9
}
fclose(ffp);
}
This is the function that needs help I do not know what I am doing wrong.
int getNumDigits(char * fileName){
int numDigits=0;
FILE *fp=fopen(fileName,"w");
printf( "Reading the file: %s \n" ,fileName) ;
if (fp == NULL)
printf("The file is not found!!");
return 0;
do
{
// Taking input single character at a time
char c = fgetc(fp);
// Checking for end of file
if (feof(fp))
break ;
printf("%c", c);
numDigits++;
} while(1);
fclose(fp);
printf("***The number of characters present in file is: %d \n",numDigits);
//getch();
return numDigits;
}
int main(void) {
addrandomNums("num1.txt");
addrandomNums("num2.txt");
int size1=getNumDigits("num2.txt");
return 0;
}
Thank you all for your help this is the fixed code. I really appreciate the help.
int getNumDigits(char * fileName){
int numDigits=0;
FILE *fp=fopen(fileName,"r");
printf( "Reading the file: %s \n" ,fileName) ;
//char buffer[MAX]=fgets()
// int length=strlen(fgets(buffer, MAX, fp));
if (fp == NULL)
printf("The file is not found!!");
char c;
do{
// Taking input single character at a time
c = fgetc(fp);
// Checking for end of file
if (feof(fp)){
numDigits++;
break ;
}
numDigits++;
} while(1);
fclose(fp);
printf("***The number of characters present in file is: %d \n",numDigits);
printf("All Done.");
return numDigits;
}
Problems with the loop:
// problem code
int numDigits=0;
char c;
do {
c = fgetc(fp);
// Checking for end of file
if (feof(fp)){
numDigits++;
break ;
}
numDigits++;
} while(1);
Off by 1
When it is time to exit, no need to add + 1 to the count.
Counts all characters as digits
There is no test to determine if the character read is a digit.
Inadequate exit condition
On a rare input error, OP's code loop forever with fgetc(fp) returning EOF and feof(fp) not true.
Count may readily exceed INT_MAX.
Some fixes:
// int numDigits=0;
unsigned long long numDigits = 0;
unsigned long long numCharacters = 0;
//char c;
int c; // fgetc() typically returns 257 different values
do {
c = fgetc(fp);
// if (feof(fp)){
// numDigits++;
// break ;
// }
if (c == EOF) {
break;
}
// numDigits++;
if (isdigit(c)) numDigits++;
numCharacters++;
} while(1);

Counting Character usage in text file? C

Hi,
I need to count the usage of alphabetical characters in some plain text file. This is what i have came with. Basically just run through the text file and compare each character with the ASCII value of specific searched character.
When I run it, all I can see is just the first printf() string and just error of terminated status when I close the console.
I do have a text.txt file in same folder as the .exe file but I can't see anything.
Not sure if just my syntax is bad or even semantics.
Thx for help! :-)
#include <stdio.h>
#include <stdlib.h>
#define ASCIIstart 65
#define ASCIIend 90
void main(){
FILE *fopen(), *fp;
int c;
unsigned int sum;
fp = fopen("text.txt","r");
printf("Characters found in text: \n");
for (int i = ASCIIstart; i <= ASCIIend; i++){
sum = 0;
c = toupper(getc(fp));
while (c != EOF){
if (c == i){
sum = sum++;
}
c = toupper(getc(fp));
}
if (sum > 0){
printf("%c: %u\n",i,sum);
}
}
fclose(fp);
}
Instead of looking up the entire file for each character, you could do
FILE *fp;
int c, sum[ASCIIend - ASCIIstart + 1]={0};
fp = fopen("file.txt,"r");
if(fp==NULL)
{
perror("Error");
return 1;
}
int i;
while( (c = toupper(getc(fp)))!= EOF)
{
if(c>=ASCIIstart && c<=ASCIIend)
{
sum[c-ASCIIstart]++;
}
}
for(i=ASCIIstart; i<=ASCIIend; ++i)
{
printf("\n%c: %d", i, sum[i-ASCIIstart]);
}
You must check the return value of fopen() to ensure that the file was successfully opened.
There's an array sum which holds the the number of occurrences of each character within the range denoted with ASCIIend and ASCIIstart macros.
The size of the array is just the number of characters whose number of occurrences is to be counted.
sum[c-ASCIIstart] is used because the difference between the ASCII value (if the encoding is indeed ASCII) of c and ASCIIstart would give the index associated with c.
I don't know what you meant with FILE *fopen(), fp; but fopen() is the name of a function in C used to open files.
And by
FILE *fopen(), *fp;
you gave a prototype of a function fopen().
But in stdio.h, there's already a prototype for fopen() like
FILE *fopen(const char *path, const char *mode);
yet no errors (if so) were shown because fopen() means that the function can have any number of arguments. Have a look here.
Had the return type of your FILE *fopen(); were not FILE * or if it were shown to other parameter types like int, you would definitely have got an error.
And, void main() is not considered good practice. Use int main() instead. Look here.
You can use a character array and parse the file contents with one time traversal and display the array count finally.
#include <stdio.h>
#include<ctype.h>
void main(){
FILE *fopen(), *fp;
int c;
fp = fopen("test.txt","r");
printf("Characters found in text: \n");
char charArr[26]= {0};
c = toupper(fgetc(fp));
while(c!=EOF) {
charArr[c-'A']=charArr[c-'A']+1;
c = toupper(fgetc(fp));
}
fclose(fp);
for(int i=0;i<26;i++){
printf("\nChar: %c | Count= %d ",i+65,charArr[i]);
}
}
Hope this helps!!
because after first time you are end of the file.
and your c = toupper(getc(fp)); returning -1 after that.
For counting just one character, you are reading the whole file and repeating this for each and every character. Instead, you can do:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define ASCIIstart 65
#define ASCIIend 90
int main(){
FILE *fp;
int c, i;
int alphabets[26] = {0};
fp = fopen("text.txt","r");
if (fp == NULL){
fprintf (stderr, "Failed to open file\n");
return -1;
}
while ((c = toupper(fgetc(fp))) != EOF){
if (c >= ASCIIstart && c <= ASCIIend)
alphabets[c - ASCIIstart]++;
}
fclose(fp);
fprintf(stdout, "Characters found in text: \n");
for (i = 0; i < 26; i++)
fprintf (stdout, "%c: %d\n", i+ASCIIstart, alphabets[i]);
return 0;
}
TLDR
Working with your code, your loops are inside-out.
I'll answer in pseudo-code to keep the concepts straightforward.
Right now you are doing this:
FOR LETTER = 'A' TO 'Z':
WHILE FILE HAS CHARACTERS
GET NEXT CHARACTER
IF CHARACTER == LETTER
ADD TO COUNT FOR CHAR
END IF
END WHILE
END FOR
The problem is you are running through the file with character 'A' and then reaching the end of file so nothing gets done for 'B'...'Z'
If you swapped this:
WHILE FILE HAS CHARACTERS
GET NEXT CHARACTER
FOR LETTER = 'A' TO 'Z'
IF LETTER = UCASE(CHARACTER)
ADD TO COUNT FOR LETTER
END IF
END FOR
END WHILE
Obviously doing 26 checks for each letter is too much so perhaps a better approach.
LET COUNTS = ARRAY(26)
WHILE FILE HAS CHARACTERS
CHARACTER := UCASE(CHARACTER)
IF CHARACTER >= 'A' AND CHARACTER <= 'Z'
LET INDEX = CHARACTER - 'A'
COUNTS[INDEX]++
ENDIF
END WHILE
You can translate the pseudo code to C as an exercise.
Rewind the pointer to the beginning of the file at the end of your for loop?
This has been posted before: Resetting pointer to the start of file
P.S. - maybe use an array for your output values : int charactercount[pow(2,sizeof(char))] so that you don't have to parse the file repeatedly?
edit: was missing pow()

Program to count number of times a character appear in file(case insensitive)

executed this code in an online editor.but always getting File 'test.txt' has 0 instances of letter 'r'.what to do??File 'test.txt' has 99 instances of letter'r'.This is the expected output.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
FILE *fptr;
int d=0;
char c;
char ch,ck;
char b[100];
printf("Enter the file name\n");
scanf("%19s",b);
fptr=fopen(b,"r");
printf("Enter the character to be counted\n");
scanf(" %c",&c);
c=toupper(c);
if(fptr==NULL)
{
exit(-1);
}
while((ck=fgetc(fptr))!=EOF)
{
ch=toupper(ck);
if(c==ch||c==ck)
++d;
}
fclose(fptr);
printf("File '%s' has %d instances of letter '%c'.",b,d,c);
return(0);
}
Problems:
ck should be an int, not a char as #alk has pointed out because fgetc returns an int, not a char.
As per the title, you want a case insensitive comparision. Your code does not do that. The solution is that this:
if(c==ch||c==ck)
needs to be
if(c == ch || (tolower(c)) == ck) /* Compare upper with upper, lower with lower */
I tested it. It works fine. I can't detect your problem without you providing the test file it fails on. As far as I am concerned, it does what it is supposed to do - it counts the number of times specified character appears (case-insensitive) in specified file. Here's your prettified version of your code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* strlen */
#include <ctype.h>
#define MAX_FILENAME_LENGTH 100
int main(int argc, char **argv) {
/* Variables */
FILE *file = NULL;
int count = 0, file_char;
char target_char, filename[MAX_FILENAME_LENGTH];
/* Getting filename */
printf("Enter the file name: ");
fgets(filename, MAX_FILENAME_LENGTH, stdin);
/* Removing newline at the end of input */
size_t filename_len = strlen(filename);
if(filename_len > 0 && filename[filename_len - 1] == '\n') {
filename[filename_len - 1] = '\0'; }
/* Opening file */
file = fopen(filename, "r");
if(file == NULL) exit(EXIT_FAILURE);
/* Getting character to count */
printf("Enter the character to be counted: ");
scanf(" %c", &target_char);
target_char = toupper(target_char);
/* Counting characters */
while((file_char = fgetc(file)) != EOF) {
file_char = toupper(file_char);
if(target_char == file_char) ++count; }
/* Reporting finds */
printf("File '%s' has %d instances of letter '%c'.",
filename, count, target_char);
/* Exiting */
fclose(file);
return EXIT_SUCCESS; }

Resources