How to iterate through files in c? - c

I have to write a function that given two files, compares them both and writes on a third file each word they have in common, I tried with this one, actually making it write on terminal to see if it works, it actually iterates trough the second file but it only compares the first word of the first file, any suggestions?
void fileCopy(FILE *f1,FILE *f2){
char fileString1[100], fileString2[100];
while(!feof(f1)){
fscanf(f1,"%s",fileString1);
while(!feof(f2)){
fscanf(f2,"%s",fileString2);
if(!strcmp(fileString1,fileString2)) printf("%s ",fileString1);
}
}
}

while(!feof(f2)) loops until the end of the second file. You must iterate through both files simultaneously. Instead of these while(!feof... you should be checking the result of each fscanf.
A simple pseudo code example:
while(1)
{
int fscanf1_result = fscanf(f1, ...);
int fscanf2_result = fscanf(f2, ...);
if(fscanf1_result != 1 || fscanf2_result != 1)
{
break;
}
/* rest of the code here */
};

Related

Recursive function : abort-condition

We need to create a binary tree which contains content of textfiles. The pointer selection_a and selection_b pointing to another textfile in the directory.
The structure of the textfiles is following:
line: Title
line: OptionA
line: OptionB
line: Text.
The first file is given as parameter while starting the program. All files should be saved at the beginning of the program. Then the text of the first file shows, and the user can input A or B to continue. Based on the selection, the text of File Option A/B is shown and the user can decide again.
The last file of a tree contains no Options: lines 2 and 3 are "-\n".
The problem is, this code only reads all the option A files of the first tree. It doesn't read in any B-Options. In the end, the program shows a memory access error.
I think the problem is that the readingRows function has no abort condition.
current->selection_a = readingRows(input_selection_a);
current->selection_b = readingRows(input_selection_b);
I know the code may be kind of chaotic, but we are beginners in programming. Hope anybody can help us to write an abort-condition.
The function should be aborted if the content of option A (line 3) is "-\n".
Here is the whole function:
struct story_file* readingRows(FILE *current_file)
{
char *buffer = fileSize(current_file);
char *delimiter = "\n";
char *lines = strtok(buffer, delimiter);
int line_counter = 0;
struct story_file *current = malloc(sizeof(struct story_file));
while(lines != NULL)
{
if(line_counter == 0)
{
current->title = lines;
}
else if(line_counter == 1)
{
char *filename_chapter_a = lines;
FILE *input_selection_a = fopen(filename_chapter_a, "r");
if(input_selection_a)
{
current->selection_a = readingRows(input_selection_a);
}
fclose(input_selection_a);
}
else if(line_counter == 2)
{
char *filename_chapter_b = lines;
FILE *input_selection_b = fopen(filename_chapter_b, "r");
if(input_selection_b)
{
current->selection_b = readingRows(input_selection_b);
}
fclose(input_selection_b);
}
else if (line_counter >= 3)
{
current->text = lines;
}
lines = strtok(NULL, delimiter);
line_counter++;
}
return current;
}
There are two items that define a terminating recursive function:
One or more base cases
Recursive calls that move toward a base case
Your code has one base case: while (lines!=NULL) {} return current;, it breaks the while loop when lines is NULL and returns current. In other words, within any particular call to your function, it only terminates when it reaches the end of a file.
Your code moves toward that base case as long as your files do not refer to each other in a loop. We know this because you always read a line, take an action according to your if-else block, and the read the next line. So you always move toward the end of each file you read.
But as you note, the issue is that you don't have a case to handle "no Options", being when lines 2 or 3 are "-\n". So right now, even though you move through files, you are always opening files in line 2. Unless a file is malformed and does not contain a line 2, your recursive call tree never ends. So you just need to add another base case that looks at whether the beginning of lines matches "-\n", and if it does, return before the recursive call. This will end that branch of your recursive tree.
Inside of your while loop, you will need code along the lines of:
if `line_counter` is `2` or `3`
if `lines` starts with your terminating sequence "-\n"
return current
else
`fopen` and make the recursive call
In the parent function that made the recursive call, it will move to the next line and continue as expected.
P.S. Make sure you use free for each malloc you do.

Searching a particular string in a large file

I am making program in C which can search for a specific string in a large .txt file and count it and then print it out. But it seems that something have go wrong, cause the output of my program is different from that of the two text editor. According to the text editor, there are totally 3000 words,in this case I search for the word "make", in that .txt file. But the output of my program is just 2970.
I cannot find out the problem of my program. So I am curios about how could a text editor search for a specific string so accurately? How do people implement that? Can any people show me some code in C?
To make things clear: that is a large .txt file, 20M or so, containing lots of characters. So I think it's not so good to read it into memory all at once. I have implement my program by splitting my program in to pieces and then scan all of those for parsing. However, it fail some way.
Maybe I should put the code here. Wait a minute please.
The code is kinda long, 70 lines or so. I have put it on my github, if you have any interest, please help. https://github.com/walkerlala/searchText
note that the only related file is wordCount.c and testfile.txt which goes like:
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
char arr[51];
int flag=0;
int flag2=0;
int flag3=0;
int flag4=0;
int pieceCount(FILE*);
int main()
{
//the file in which I want to search the word is testfile.txt
//I have formatted the file so that it contain no newlins any more
FILE* fs=fopen("testfile.txt","r");
int n=pieceCount(fs);
printf("%d\n",n);
rewind(fs); //refresh the file...
static bool endOfPiece1=false,endOfPiece2=false,endOfPiece3=false;
bool begOfPiece1,begOfPiece2,begOfPiece3;
for(int start=0;start<n;++start){
fgets(arr,sizeof(arr),fs);
for(int i=0;i<=46;++i){
if((arr[i]=='M'||arr[i]=='m')&&(arr[i+1]=='A'||arr[i+1]=='a')&&(arr[i+2]=='K'||arr[i+2]=='k')&&(arr[i+3]=='E'||arr[i+3]=='e')){
flag+=1;
//continue;
}
}
//check the border
begOfPiece1=((arr[1]=='e'||arr[1]=='E'));
if(begOfPiece1==true&&endOfPiece1==true)
flag2+=1;
endOfPiece1=((arr[47]=='m'||arr[47]=='M')&&(arr[48]=='a'||arr[48]=='A')&&(arr[49]=='k'||arr[49]=='K'));
begOfPiece2=((arr[1]=='k'||arr[1]=='K')&&(arr[2]=='e'||arr[2]=='E'));
if(begOfPiece2==true&&endOfPiece2==true)
flag3+=1;
endOfPiece2=((arr[48]=='m'||arr[48]=='M')&&(arr[49]=='a'||arr[49]=='A'));
begOfPiece3=((arr[1]=='a'||arr[1]=='A')&&(arr[2]=='k'||arr[2]=='K')&&(arr[3]=='e'||arr[3]=='E'));
if(begOfPiece3==true&&endOfPiece3==true)
flag4+=1;
endOfPiece3=(arr[49]=='m'||arr[49]=='M');
}
printf("%d\n%d\n%d\n%d\n",flag,flag2,flag3,flag4);
getchar();
return 0;
}
//the function counts how many pieces have I split the file into
int pieceCount(FILE* file){
static int count=0;
char arr2[51]={'\0'};
while(fgets(arr2,sizeof(arr),file)){
count+=1;
continue;
}
return count;
}
You can do this quite simply just by having a rolling buffer. You don't need to break the file into sections.
#include <stdio.h>
#include <string.h>
int main(void) {
char buff [4]; // word buffer
int count = 0; // occurrences
FILE* fs=fopen("test.txt","r"); // open the file
if (fs != NULL) { // if the file opened
if (4 == fread(buff, 1, 4, fs)) { // fill the buffer
do { // if it worked
if (strnicmp(buff, "make", 4) == 0) // check for target word
count++; // tally
memmove(buff, buff+1, 3); // shift the buffer down
} while (1 == fread(buff+3, 1, 1, fs)); // fill the last position
} // end of file
fclose(fs); // close the file
}
printf("%d\n", count); // report the result
return 0;
}
For simplicity I stopped short of making the search word "softer" and allocating the correct buffer and various sizes, since that wasn't in the question. And I have to leave something for OP to do.

Where am I going wrong in getting this function to do what I would like?

I have written the following function in my C program. The program loads a text file (Les Miserables Vol. I) as well as another text file of 20 of the characters names. The purpose of this function is to scan the entire file, line by line, and count the number of times any of the 20 names appear.
NumOfNames = 20.
Names is an array of the 20 names stored from Names[1] - Names[20].
MaxName is a global integer variable which I would like to store the total number of name appearances throughout the file (It should be in the hundreds or even thousands).
EDIT: After the function is executed, the value of MaxName is 4. I am completely lost as to where I have made a mistake, but it appears that I have made several mistakes throughout the function. One seems to be that it only executed the first iteration of the for loop i.e. it only searches for Name[1], however the first name appears 196 times in the file, so it still isnt even working correctly for just the first name.
void MaxNameAppearances()
{
char LineOfText[85];
char *TempName;
FILE *fpn = fopen(LesMisFilePath, "r+");
for(i = 1; i<=NumOfNames; i++)
{
while(fgets(LineOfText, sizeof(LineOfText), fpn))
{
TempName = strstr(LineOfText, Names[i]);
if(TempName != NULL)
{
MaxName++;
}
}
}
fclose(fpn);
}
I guess that one problem of the code is that it would have to read the file upon every iteration of i. Try to re-order the loops like this:
while(fgets(LineOfText, sizeof(LineOfText), fpn))
{
for(i = 1; i<=NumOfNames; i++)
{
TempName = strstr(LineOfText, Names[i]);
if(TempName != NULL)
{
MaxName++;
}
}
}
This reads a line, checks the occurrances of all names in that line and then goes on to the next line.
If you do it your way, you will be at the end of file for i == 1 already.

Read lines from a file into character arrays

I'm completely new to C and I'm working on a program which has to read in 3 lines from a text file(two numbers and a mathematical symbol) and write out the result. So for example:
The text file looks like:
1
4
*
and my program should be able to read the 3 lines and write out something like "1*4 = 4" or something.
I managed to get to a point where i can read the 3 lines in and show them on screen, so I thought I should put the two numbers in one array and the symbol in another one. The problem is, that I tried to see if the arrays contain the numbers I put in them and my output has some huge numbers in it and I'm not sure why.
Here's the code i wrote:
#include <stdio.h>
#include <io.h>
#include <string.h>
int main(void)
{
int res = 1; /*Creates an integer to hold the result of the check for the file*/
const char *file = "input.txt"; /*String holding the name of the file with the input data*/
res = access(file,R_OK); /*Checks if the file "input.txt" exists*/
if(res == -1)
{ /*IF the file doesn't exist:*/
FILE *input = fopen("input.txt","w"); /*This creates a file called "input.txt" in the directory of the program*/
char write[] = "1\n1\n+"; /*This variable holds the string that's to be written to the file*/
fprintf(input,"%s",write); /*This writes the variable "write" to the file*/
printf("input.txt file created!"); /*Tells you the file is created*/
fclose(input); /*Closes the file after it's done*/
}
else
{ /*IF the file exists:*/
FILE *f = fopen("input.txt","r");
//char line[ 5000 ];
//while ( fgets ( line, sizeof line, f ) != NULL )
//{
// fputs ( line, stdout );
//}
char line[5000];
char nums[2];
char symbol[1];
int i = 0;
while(fgets(line,sizeof line,f)!=NULL)
{
i++;
if(i < 3)
{
fputs(nums,f);
}
else
{
fputs(symbol,f);
}
printf("%d,%d",nums,symbol);
}
printf("\n\n\n");
scanf("\n");
}
return 0;
}
Any help would be greatly appreciated!
Thank you in advance
If you require any more information i will provide it.
This is a self-explanatory algorithm. Also, here is the code that does the operation you are looking for. Generally, the complex operations are accomplished using stack, push and pop method. Once the operators are pushed. One need to apply the BODMAS rule,to evaluate the expression. Since the problem given to you is simple, a simple expression evaluation. This can be simply achieved by FIFO. Here is the algorithm, general explanation. Afterwards, the code is present. This code is well tested.You can extend it to do operations like +,-,division /, %, etc. If you like my answer please appreciate.
#include "stdio.h"
int main(int argc, char *argv[])
{
FILE *fp_op;
int buff[2]; /** assuming a simple operation, thus the buffer size is 3 only, the last one is to store the NULL **/
char operat_buff[2]; /** assuming this operation we can extend it to evaluate an expression **/
fp_op = fopen("calc.txt","rb");
if ( fp_op == 0 )
{
perror("The file doesn't exist to calculate\r\n");
goto error;
}
/** Read the two numbers here **/
fscanf(fp_op,"%d",&(buff[0]));
printf("The buff[1] = %d\r\n",buff[0]);
fscanf(fp_op,"%d",&(buff[1]));
printf("The buff[1] = %d\r\n",buff[1]);
/** read the next line now \n **/
operat_buff[0] = fgetc(fp_op);
/** read the actual character now **/
operat_buff[0] = fgetc(fp_op);
printf("The operat_buff[0] = %d\r\n",operat_buff[0]);
/** Read operation completed **/
/** use switch here **/
switch(operat_buff[0])
{
case '*':
printf("The multiplication result=%d\r\n",buff[0]*buff[1]);
break;
case '+':
printf("The Addition result=%d\r\n",buff[0]+buff[1]);
break;
default:
printf("Add more operations\r\n");
}
return 0;
error:
return -1;
}
I assume that the calc.txt was something like this.
calc.txt
3
5
*
Note: This code is compiled and verified.It compiles with zero warnings. It does the error checking too. You can directly copy and paste it.
What are you reading from the files are simply characters codes: the program has no way of figuring by itself that the character "4" corresponds to the integer number 4. The %d placeholder of printf expects int variables, or it won't work.
If you want just to print the characters you have to save them in char variables (or a char array) and use the placeholder %c in printf. If you want to actually use the numbers and symbols in your program you have more work to do.
Not only in C, but I think in most languages you have to "parse" the characters to numbers.
In C you can use the functions atoi or atol (you have to #include <stdlib.h>) in order to do this conversion.
In order to parse the symbol I'm afraid you will have to use an if or a switch to read the character and perform the operation accordingly.
For example your loop could look like:
while(fgets(line,sizeof line,f)!=NULL)
{
int op1;
int op2;
int res;
char symbol;
i++;
switch (i) {
case 1:
//First line is first operand
op1 = atoi(line);
printf("op1 %d\n",op1);
break;
case 3:
//Second line is second operand
op2 = atoi(line);
printf("op2 %d\n",op2);
break;
//Fifth line is the operator, could be +,-,%./ or anything
case 5:
symbol = line[0];
printf("operand %c\n",symbol);
switch(symbol) {
case '+':
res = op1+op2;
break;
case '-':
res = op1-op2;
break;
default:
//operation not defined, return
return;
}
printf("%d%c%d = %d",op1,symbol,op2,res);
}
}
printf("%d,%d",nums,symbol);
In your code nums and symbol are strings, you can't print them with %d. What you are getting are the addresses of the nums and symbol arrays, respectively - even if that's not the right way of printing an address.
You'll likely want to convert them to integers, using strtol or sscanf and then use those to perform the computation.

Using a function to read in a file

I have the code below which compiles fine in xcode, but when I take it across to Microsoft Visual studio I get a bunch of errors.
void openfile(int mapArray[MAX_HEIGHT][MAX_WIDTH], int *interest, int *dimension1, int *dimension2)
{
int counter = 0;
char buffer;
int rowss, colss;
*interest = 0;
FILE *f;
f = fopen(FILENAME, "r");
if (f==NULL) {
printf("Map file could not be opened");
return 0;
}
// create char array the dimensions of the map
fscanf(f, "%d %d" , dimension1, dimension2 );
// printf("%d %d\n" , dimensions[0], dimensions[1]);
// Reads the spaces at the end of the line till the map starts
buffer=fgetc(f);
while (buffer!='*') {
buffer=fgetc(f);
}
// Read the txt file and print it out while storing it in a char array
while (buffer!=EOF) {
mapArray[rowss][colss]=buffer;
colss++;
// Count up the points of interest
if (((buffer>64)&&(buffer<90))||(buffer=='#') ) {
counter++;
}
// resets column counter to zero after newline
if (buffer=='\n') {
colss=0;
rowss++;
}
buffer=fgetc(f);
}
// Closes the file
fclose(f);
*interest=counter;
}
Which parts are creating all the errors?
I get this list of errors when attempting to compile
Thanks in advance.
I see a few immediate problems. First, you're not initialising rowss or colss before you use them, hence they could contain any value.
Second, fgetc() returns an int so that you can detect end of file. By using a char to hold the return value, you're breaking the contract with the standard library.
Thirdly, you return a 0 if the filename couldn't be opened, despite the fact that the function is specified to return void (ie, nothing).
No doubt those are three of the errors the compiler picked up on, there may be others, and you should probably post the error list with your question for a more exhaustive analysis.

Resources