Reading a file word by word with no ending chars - c

I have this small program in C that reads through a file a compares word by word,
how can I assure that words like "this," won't be read as a word? I would like it to read as "this"
int main(int argc, char *argv[]) {
if(argc != 3)
{
printf("Usage: ./sw <word> <filename> \n");
exit(1);
}
char* word = argv[1];
const char* filename = argv[2];
FILE* file = fopen(filename, "r");
if(file == NULL)
{
printf("Could not open file\n");
exit(1);
}
//Assuming one word can not have more than 250 chars
char w[250], check_eof;
do
{
check_eof = fscanf(file, "%s", w);
if(strcmp(word, w) == 0)
{
printf("W : %s \n", w);
}
} while(check_eof != EOF);
fclose(file);
return 0;
}

You can check if a char belongs to a word like this
int c = fgetc(file);
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
// c belongs to a word
word[n++] = c;
} else {
// end of word
if (strncmp(word, w, n) == 0) {
// word and w match!
}
}
If you #include <ctype.h>, then you can call isalpha(c) instead to test it.

In the code below, I use isalpha() and I copy the result string in a new buffer named res. However, this procedure can be done in-place, but I'll leave now for the sake of simplicity.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h> // for isalpha()
int main(int argc, char *argv[]) {
char* word = "this";
const char* filename = "test.txt";
FILE* file = fopen(filename, "r");
if(file == NULL)
{
printf("Could not open file\n");
exit(1);
}
//Assuming one word can not have more than 250 chars
// ATTENTION, it is 249 chars, do NOT forget of the null terminator
char w[250], res[250];
int check_eof; // should be of type int, for EOF checking
do
{
check_eof = fscanf(file, "%s", w);
// what if 'word' appears as the last word
// in the file? You should check for eof
// right after fscanf()
if(check_eof == EOF)
break;
int i = 0, j = 0;
while (w[i]) // parse what we read
{
if (isalpha(w[i]))
res[j++] = w[i]; // keep only the alphabetic chars
i++;
}
res[j] = '\0'; // it should be a null terminated string
if(strcmp(word, res) == 0) // compare to 'res' now
{
printf("W : %s \n", res);
}
} while(1); // the terminating step is inside the body now
fclose(file);
return 0;
}

Related

Function is not correctly incrementing variable by 1

I have a function that returns the number of lines, characters, and words in an array. For some reason, when i loop through the array to print the values I am only getting the corrrect value for lines, the characters and words are returning as 0. All the functions are predetermined by my professor and my job is to fill them in.
int main(int argc, char **argv)
{
int *myArray = get_counts(argv[1]);
for (int i = 0; i < 3; i++)
{
printf("%d\n", myArray[i]);
}
return 0;
}
int *get_counts(char *filename)
{
FILE *file;
file = fopen(filename, "r");
if (file == NULL)
{
printf("NULL FILE");
}
char c;
int h;
bool whitespace = true;
static int arr[3] = {0,0,0};
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
while (true)
{
h = fgetc(file);
if (feof(file))
{
break;
}
else if (ferror(file))
{
printf("error reading file");
}
arr[2] ++;
if (whitespace && !isspace(h))
{
arr[1] ++;
whitespace = false;
}
else if (!whitespace &&isspace(h))
{
whitespace = true;
}
}
fclose(file);
return arr;
}
The best option is probably to just iterate through the file in one loop (you could also rewind() after the first loop). Use the return value of fgetc() to determine of you are at EOF instead of separate feof() calls. I also made the the result array an (out) argument instead of using a static variable (the latter is not reentrant if you ever want to call this from multiple threads and it's easy to do):
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
void get_counts(char *filename, int arr[3]) {
memset(arr, 0, 3 * sizeof(int));
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("NULL FILE");
return;
}
bool whitespace = true;
for(;;) {
int c = fgetc(file);
if(c == EOF)
break;
else if(c == '\n')
arr[0]++;
else if (whitespace && !isspace(c)) {
arr[1]++;
whitespace = false;
} else if (!whitespace && isspace(c))
whitespace = true;
arr[2]++;
}
fclose(file);
}
int main(int argc, char **argv) {
int myArray[3];
get_counts(argv[1], myArray);
for (int i = 0; i < 3; i++) {
printf("%d\n", myArray[i]);
}
}
The output on the above file is:
39
94
715
The word count 94 doesn't agree with wc -w but you could be using a different definition of what a word is.
It's a good idea to separate calculations and i/o, so consider opening and closing the file in main() and pass in the file handle. It becomes easy, for instance, to use the stdin file handle instead if you don't want to use a physical file.
After the first do-while loop the condition EOF occurs.
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
So the following while loop has no effect.
You should use only one loop to count lines, words and characters.
Pay attention to that the variable c should be declared as having the type int
int c;
Also you need to exit the function if the file was not opened.

running the program doesn't print the second printf statement

whenever I run the program the second print statement isn't printing. I tried using a function but I'm new to C and don't really understand anything. I've also attached my activity as I'm not sure how to do the other things on it.activity photo
#include <stdio.h>
#include <string.h>
#define LINE_LENGTH 1000
int main(int argc, char **argv)
{
FILE *input_file = fopen("cstest.c", "r");
char line [LINE_LENGTH];
//while loop to ger
while (fgets(line, LINE_LENGTH, input_file) != NULL)
{
int ch = 0;//ch is the cast
int lines = 0;//start with one because
if (input_file == NULL)
return 0;
while (!feof(input_file))
{
ch = fgetc(input_file);
if (ch == '\n')
{
lines++;
}
}//end while
printf("lines: %d\n", lines);
}//end while loop
while (fgets(line, LINE_LENGTH, input_file) != NULL)
{
int ch = 0;//ch is the cast
int lines = 0;//start with one because
if (input_file == NULL)
return 0;
while (!feof(input_file))
{
int characters = 0;
char c;
for (c = getc(input_file); c != EOF; c = getc(input_file))
// Increment count for this character
characters = characters + 1;
printf("characters: %d\n", characters);
fclose(input_file);
}
}
}

trying to store a text file into an array

i am trying to read from a text file and store it into an array character by character, ive tested it out by trying to print or check the ii count but it doesn't seem to be storing, any help would be muchly appreciated
char *readFile(char* filename)
{
FILE* f;
int ii = 0;
char* file = (char*)malloc(1000*sizeof(char));
char ch = '\0';
f = fopen(filename,"r");
if(f == NULL)
{
printf("Error opening file '%s'.\n", filename);
}
else
{
while ((ch = fgetc(f)) != EOF)
{
printf("%c",ch);
file[ii] = (char) ch;
ii++;
}
}
/* file[ii] = '\0'; setting last character as null*/
printf("\n");
fclose(f);
free(file);
return file;
}
I have commented out the line containing the code to free the character array before returning, which was basically making the pointer invalid. I have also changed the type of the variable "ch" to int as fgetc() returns integer.
#include <stdio.h>
#include <stdlib.h>
char *readFile(char* filename)
{
FILE* f;
int ii = 0;
char* file = (char*)malloc(1000*sizeof(char));
int ch; //changed to int from char.
f = fopen(filename,"r");
if(f == NULL)
{
printf("Error opening file '%s'.\n", filename);
}
else
{
while ((ch = fgetc(f)) != EOF)
{
// printf("%c",ch);
file[ii] = (char) ch;
ii++;
}
}
/* file[ii] = '\0'; setting last character as null*/
printf("\n");
fclose(f);
//free(file); //commented this line out
return file;
}
int main()
{
char *filename = "sample.txt";
char *file_arr = readFile(filename);
printf("%s \n",file_arr);
return 0;
}

Can't get output reversed reading from a file C

I want to do something pretty simple, but somehow it doesn't do what I want.
I have a file with numbers in it. I wanna read from that file and print those numbers but in reverse order.
so let's say we have the numers:
10
32
43
6
7
I want to have:
7
6
43
32
10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 255
int main(int argc, char *argv[]) {
char userInput[MAX], target[MAX];
FILE *file = stdin;
if (argc > 2) {
fprintf(stderr, "Usage: %s[<file>]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2) {
file = fopen(argv[1], "r");
if (!file) {
perror(argv[0]);
exit(EXIT_FAILURE);
}
}
while(fgets(userInput, sizeof(userInput), file)) {
size_t len = strlen(userInput);
int i;
for (i = len-1; i >= 0; i--) {
if (userInput[i] == ' ') {
userInput[i] = '\0';
printf("%s ", &(userInput[i]) + 1);
}
}
printf("%s", userInput);
}
if (file != stdin) {
fclose(file);
}
exit(EXIT_SUCCESS);
}
Does anyone see the mistake?
This is the content of my .txt file:
11
34
45
3
78
43
3
4
9
34
23
43
Your program is designed to accept all of its input on a single line. Your input file contains multiple lines.
The following 1. solution is based on the example shown in the question.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 255
int main(int argc, char *argv[])
{
char userInput[MAX] = "";
char target[MAX] = "";
FILE *file = stdin;
if (argc > 2)
{
fprintf(stderr, "Usage: %s[<file>]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2)
{
file = fopen(argv[1], "r");
if (!file)
{
perror(argv[0]);
exit(EXIT_FAILURE);
}
}
/* Read all numbers from file and write it to target buffer */
while(fgets(userInput, sizeof(userInput), file))
{
/* Break loop if there is not enough space to store current number. */
if ((strlen(target) + strlen(userInput)) >= MAX)
{
break;
}
/* Add current number read from file to target buffer */
strcat(target, userInput);
/* Print current number read from file */
printf("%s", userInput);
}
if (file != stdin) {
fclose(file);
}
/*
* Run over target buffer in reverse order and replace current number
* split character '\n' by string end marker '\0'.
* After that print current number.
*/
size_t len = strlen(target);
if (len > 0)
{
for (size_t i = len-1; i != 0; i--)
{
if (target[i] == '\n')
{
target[i] = '\0';
printf("%s\n", &(target[i]) + 1);
}
}
/* Print first number */
printf("%s\n", &(target[0]));
}
exit(EXIT_SUCCESS);
}
However it might be better to store the numbers within an array of integer using sscanf() and after that print the content of the array in reverse order.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 255
int main(int argc, char *argv[])
{
char userInput[MAX] = "";
int nums[MAX];
int count = 0;
FILE *file = stdin;
if (argc > 2)
{
fprintf(stderr, "Usage: %s[<file>]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2)
{
file = fopen(argv[1], "r");
if (!file)
{
perror(argv[0]);
exit(EXIT_FAILURE);
}
}
/* Read all numbers from file and write it to target buffer */
while(fgets(userInput, sizeof(userInput), file))
{
sscanf(userInput, "%i", &nums[count]);
/* Break loop if there is not enough space to store current number. */
if (count >= MAX)
{
break;
}
count++;
/* Print current number read from file */
printf("%s", userInput);
}
if (file != stdin) {
fclose(file);
}
/* Print numbers stored in array in reverse order */
printf("\n");
for (int idx = count; idx != 0; idx--)
{
printf("%i\n", nums[idx-1]);
}
exit(EXIT_SUCCESS);
}
You can read your input file starting from the end using fseek
Here there's a possible implementation based on your code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 255
int main(int argc, char *argv[]) {
int i = 0, end = 0, cnt = 0;
char ch, cnt_flag = 0;
char userInput[MAX];
FILE *fp = stdin;
if (argc > 2) {
fprintf(stderr, "Usage: %s[<fp>]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2) {
fp = fopen(argv[1], "r");
if (!fp) {
perror(argv[0]);
exit(EXIT_FAILURE);
}
}
fseek(fp, 0, SEEK_END);
end = ftell(fp);
while (i < end) {
i++;
fseek(fp, -i, SEEK_END);
ch = fgetc(fp);
if (cnt_flag == 1) {
cnt++;
if (ch == '\n') {
/* skip empty lines */
if (cnt > 1) {
fgets(userInput, cnt, fp);
printf("%s\n", userInput);
}
cnt_flag = 0;
cnt = 0;
}
}
if (ch == '\n')
cnt_flag = 1;
}
/* read first line */
fseek(fp, 0, SEEK_SET);
fgets(userInput, cnt + 1, fp);
printf("%s\n", userInput);
if (fp != stdin) {
fclose(fp);
}
exit(EXIT_SUCCESS);
}
If u need to reverse strings in file, check this out. This is crossplatform solution without big chunk buffer usage. Only restriction that this is for file operations only. Advantages: file size independent solution.
This example based on your code.
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#define NEW_LINE 2 // Windows new line: 2 bytes (CR) + (LF)
#else
#define NEW_LINE 1 // Linux new line: 1 byte (LF)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 255
// This function can be replaced with any other solution
// u need (write data into another file, or allocate data in the memory and etc)
void printLineFromFile(FILE *file) {
char buff[255];
// write line with \n to buff
fgets(buff, 255, file);
// total buff size
int buffLen = strlen(buff);
int printLen = buffLen;
// printLen equals buffLen if the last symbol isn't \n
if (buff[buffLen - 1] == '\n') printLen--;
// print specified amount of bytes from buff
fprintf(stdout, "%.*s\n", printLen, buff);
}
int main(int argc, char *argv[]) {
FILE *file = stdin;
if (argc > 2) {
fprintf(stderr, "Usage: %s[<file>]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2) {
file = fopen(argv[1], "r");
if (!file) {
perror(argv[0]);
exit(EXIT_FAILURE);
}
}
// set position to the end of file
fseek(file, 0, SEEK_END);
// endPosition - position of last byte in file. (not EOF)
long endPosition = ftell(file) - 1;
// currPosition - moving position across the file
long currPosition = endPosition;
// byte buffer to read into it
int ch;
while (currPosition >= 0) {
// moving file position to the currPosition
fseek(file, currPosition, SEEK_SET);
if (currPosition == 0) {
printLineFromFile(file);
currPosition -= NEW_LINE;
continue;
}
ch = fgetc(file);
if (ch == '\n') {
if (currPosition == endPosition) {
currPosition -= NEW_LINE;
fprintf(stdout, "\n");
}
else {
printLineFromFile(file);
currPosition -= NEW_LINE;
continue;
}
}
// move back to position before fgetc
currPosition--;
};
if (file != stdin) {
fclose(file);
}
exit(EXIT_SUCCESS);
}

Convert and count upper case and lowercase characters

I am writing a C program to convert all uppercase characters to lowercase and all lowercase to uppercase from a file.
I also want to count the characters read and the number of characters converted to uppercase and characters converted to lowercase.
I am able to convert the characters but unable to figure out how to count them.
Example;
Hello World!
Output;
hELLO wORLD!
Read 13 characters in total.
8 converted to uppercase.
2 converted to lowercase.
Here's my code;
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define INPUT_FILE "input.txt"
#define OUTPUT_FILE "output.txt"
int main()
{
FILE *inputFile = fopen(INPUT_FILE, "rt");
if (NULL == inputFile) {
printf("ERROR: cannot open the file: %s\n", INPUT_FILE);
return -1;
}
// 2. Open another file
FILE *outputFile = fopen(OUTPUT_FILE, "wt");
if (NULL == inputFile) {
printf("ERROR: cannot open the file: %s\n", OUTPUT_FILE);
return -1;
}
int c;
int ch;
int upper = 0;
int lower = 0;
int count = 0;
while (EOF != (c = fgetc(inputFile))) {
ch = islower(c)? toupper(c) : tolower(c);
fputc(ch, outputFile);
}
while (EOF != (c = fgetc(inputFile))) {
if (isupper(c))
{
upper++;
}
else if (islower(c))
{
lower++;
}
fputc(upper, outputFile);
fputc(lower, outputFile);
}
fclose(inputFile);
fclose(outputFile);
return 0;
}
Your main problem is that you are using 2 loops to read input file.
Your second loop should rewind the file before to start re-reading the file.
You can count and convert with a single loop.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define INPUT_FILE "input.txt"
#define OUTPUT_FILE "output.txt"
int main()
{
FILE *inputFile = fopen(INPUT_FILE, "rt");
if (NULL == inputFile) {
printf("ERROR: cannot open the file: %s\n", INPUT_FILE);
return -1;
}
// 2. Open another file
FILE *outputFile = fopen(OUTPUT_FILE, "w");
if (NULL == outputFile) {
printf("ERROR: cannot open the file: %s\n", OUTPUT_FILE);
return -1;
}
int ch;
int upper = 0;
int lower = 0;
int count = 0;
while (EOF != (ch = fgetc(inputFile)))
{
if (isalpha(ch))
{
if (islower(ch))
{
ch = toupper(ch);
upper++;
}
else
{
ch = tolower(ch);
lower++;
}
count++;
}
fputc(ch, outputFile);
}
fprintf(outputFile, "\nTotal: %d\nToUpper: %d\nToLower: %d\n", count, upper, lower);
fclose(inputFile);
fclose(outputFile);
return 0;
}
Take also note that you have to check if a read char is an alpha char before to convert the case, as the isalpha call inside the loop do.

Resources