How to check if a string is in a file - c

I'm new to C and I am trying to figure out how I can search for a specific string and the number that follows it in a file that has several numbers and words.
The input file that I'm using looks like this:
TREES 2
BENCHES 5
ROCKS 10
PLANTS 8
I know how to make a function read a string and I know how to compare two strings but I don't know how to put them both together or how to set the array up to read through the whole file.
I've been using strcmp, but I just don't know how to go about initializing the word I'm trying to look for.

You could do something like this:
#include <stdio.h> // For file-handling methods
#include <string.h> // For strstr method
int main(void){
FILE *fp;
char *searchString="ROCKS";
fp = fopen("myfile.txt", "r");
char buf[100]; // Either char* buf or char buf[<your_buffer_size>]
int myNumber = -1;
while((fgets(buf, 100, fp)!=NULL)) { //good to handle error as well
if(strstr(buf, searchString)!=NULL) {
sscanf(buf + strlen(searchString), "%d", &myNumber);
break;
}
}
printf("After the loop, myNumber is %d\n", myNumber);
fclose(fp);
return (0);
}
Disclaimer - untested. Should be close...

Create an array that contains the words to search for. Create an outer loop that advances through your file stream of data one character offset at a time. Create a second inner loop that iterates over your array of terms to search for. The inner loop examines each term in the array against the data provided by the outer loop. Use strncmp to limit the length of each compare to the length of the word being searched for. Upon a match, check the following character in the source buffer to ensure it doesn't negate the match.

Related

How to use fscanf and fgets from a text file with ints and strings?

Example file:
School Name (with spaces)
FirstNameofStudent StudentID
School Name2 (with spaces)
FirstNameofStudent2 StudentID2
School Name3 (with spaces)
FirstNameofStudent3 StudentID3
I cant seem to figure out what to do after using fgets for the first line.
If by itself, I can easily get school name using fgets
and the second line by itself using fscanf then converting the studentID to int using atoi.
But how do I combine both fgets and fscanf?
The information scanned would be placed into an array.
Before I go onto the solution, I want to point out that an array can only have a single type. You cannot store integers in an array of characters.
Meaning if you would like all of this information to go in a single 2D array, you'd need to store the ID as a string. Then if you need it as an integer, you'd need to use atoi on it once you retrieve it.
Now for combining the two, you'd need a while loop with fgets in the condition in order to retrieve the first line. Something like this:
while(fgets(schoolname, 255, fp) != 0){ ... }
This would keep on retrieving lines until it fails, or it reaches EOF. However, you wanted to use fscanf for the second line, and for that, you'd need a line like this:
fscanf(fp, "%s %s\n", name, id);
This means, from the current point, there are two strings seperated by a space, and a newline. Store the two strings in name and id, and gobble the newline.
Gobbling the newline is key, as if you don't do it, the next time fgets runs, it would only find a single newline on the line.
As for storing the elements in an array, you'd need a 2D array of strings. For that, you can either do it fixed, or dynamic. For fixed, it's pretty easy, just have a line like char students[3][3][80] and simply store stuff in there, but for dynamic, you'd need to use memory allocation, pointers, etc, with a variable liks char ***students
Here's the code I used to solve your problem, though I suggest trying to do this on your own as well, to get the hang of it:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
FILE *fp = fopen("ex.txt", "r");
if(fp == 0) exit(-1);
char ***students;
// Used to check how many students there are
int studentno = 0;
// Init students array
// So far it means 1 ROW, with 3 COLUMNS, each of 80 CHARACTERS
students = calloc(studentno+1, 3 * 80);
// Temporary variables for storage
char schoolname[80];
char name[20];
char id[10];
int i = 0;
while(fgets(schoolname, 255, fp) != 0){
studentno++;
// Retrieve name and id from second line
fscanf(fp, "%s %s\n", name, id);
// Cut off newline left from fgets
schoolname[strlen(schoolname)-2] = 0;
// Allocate memory for new members of array
students[i] = malloc(3 * 80);
students[i][0] = malloc(80);
students[i][1] = malloc(80);
students[i][2] = malloc(80);
// Copy strings received into array
strcpy(students[i][0], schoolname);
strcpy(students[i][1], name);
strcpy(students[i][2], id);
// Resize students array for additional students
students = realloc(students, (size_t) (studentno+1) * 3*80);
i++;
}
// Check students are stored correctly
for(int i = 0; i < studentno-1; i++){
printf("%s - %s - %s\n", students[i][0], students[i][1], students[i][2]);
}
}

read a text file, make every character lowercase and store it in an array

I would like to read in a text file and store the characters in an array. But the stored characters all have to be lower cased and keep a running count of the number of words. We can assume that we will use no more that the first 5000 words in the test and no more than the first 15 characters in a word. How would I fix make the each character into lower case.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *inFile;
char userInputFileName[100];
char *line = malloc(sizeof(char)*100);
int count = 0;
char *token;
char delim[] = " ,.!;:\n";
char *eachWord;
printf("Please enter the name of the text file \n");
scanf("%s", &userInputFileName);
inFile = fopen(userInputFileName, "r");
if(inFile == NULL)
{
fprintf(stderr, "Failed to open file \n");
exit(1);
}
while(fgets(line, sizeof(line),inFile)
{
printf("%s\n", line);
char newWord[5000];
while((eachWord = strtok(token, delim)) != NULL)
{
strcpy(newWord[count], eachWord);
}
count++;
}
}
Your while loop has some thought errors. I'll outline them to you but won't fix them so you can fix them and learn.
You write while(fgets(line, sizeof(line),... but that will read only 4 or 8 characters. Why? Read about sizeof and then look at what you are asking the size of.
In the while loop you say char newWord[5000]. That means you are allocating one array of 5000 characters. But in your problem statement you say "...5000 words in the test and no more than the first 15 characters". So there is a thought error and you would need an array for 5000 words of 15 characters each.
But, you are declaring this array in the loop, meaning it will be destroyed at the bottom of the while loop and recreated at the top. So you loose the word(s) just read and stored. You should allocate the array where it will not be destroyed and recreated with every iteration.
In tyour strcpy you do not make sure that only the first 15 characters (as per your problem statement) are copied. Use the right copy function to do that. And don't forget to terminate the copied characters.
And then after the while strtok... you increment count. That does not seem the right place to count the number of words.
Go back to the drawing board...

Merged files versus appending files in C

Can someone please help explain the difference in C and how my file fails to merge, and appends instead? The background is I am on an online computer science class this summer which uses C language, all we are given is read the entire texbook (732 pages), and do 20 projects over the course of 8 weeks, with no actual instruction, lecture, slides, or explanations. Please explain it so I can learn as I need to actually understand these terms to be better and progress in my Electrical Engineering program. I have contacted my professor for help but the answers are always short and uninformative, and you guys have provided so much more quality feedback to date. Also I do get that he is right and it was appended and not merged, but any feedback how i could of rectified this will help as well. Thank you again!
#include <stdio.h>
#include <stdlib.h>
FILE *inptr1, *inptr2, *outptr;
int main()
{
char c;
char file1[30], file2[30], file3[30];
printf("Enter the first files name\n");
gets(file1);
printf("Enter the second files name\n");
gets(file2);
printf("Enter the file name that will store the data from the other two files\n");
gets(file3);
inptr1 = fopen("C:\\Users\\Eric\\Desktop\\file1.txt","r");
inptr2 = fopen("C:\\Users\\Eric\\Desktop\\file2.txt","r");
if( inptr1 == NULL || inptr2 == NULL )
{
perror("Error ");
printf("Press any key to exit!\n");
exit(1);
}
outptr = fopen("C:\\Users\\Eric\\Desktop\\file3.txt","w");
if( outptr == NULL )
{
perror("Error ");
printf("Press any key to exit!\n");
exit(1);
}
while( ( c = fgetc(inptr1) ) != EOF )
fputc(c,outptr);
while( ( c = fgetc(inptr2) ) != EOF )
fputc(c,outptr);
printf("The two files were sucessfully merged into %s \n",file3);
fclose(inptr1);
fclose(inptr2);
fclose(outptr);
return 0;
}
Page 611 #5 Write a complete C program. Use the two files provided. Your program should not assume that you know which file is shorter.
5) Write a function to merge two sorted files of names and write the names to a
new file.
Was the only direction I was given as far as to what the program was supposed to do.
and this was the feedback i received, "Did you look at the resulting file?The girls names are all at the bottom. You were to merge the files,not append the files."
Thank you again in advance for your valuable feedback as it has taught me so much to date.
You're going to need to look at the contents of each file and write them to the third file in sorted order. That seems to be what the assignment is asking you to do. What you're doing currently is dumping the contents of file1.txt into file3.txt followed by the contents of file2.txt. You want to end up with a sorted list containing the contents of both files.
There are many ways to accomplish your requirements. This is just one that jumps out:
Steps to perform:
1 Open two existing files (fopen(fp, "r");), and one new file (fopen(fp, "w");)
2 write all lines of first file, then the second file to the third file. (fopen(), fgets(), fputs(), fclose(), etc.)
3 Read third file into an array of strings, keeping a count of the total number of strings read. close file.
4 Sort array of strings. (qsort())
5 Open third file, Write sorted array of strings into that file.
6 Close all files, free all memory.
Note, using this method, it does not matter if the two original files are sorted, or not, (Assignment says they are, but does not matter). The qsort routine will completely sort the string array either way.
qsort()
Most of the functions referenced are straight forward to use. qsort() is a little weird.
Here is an example showing how to set up qsort() for use sorting an array of strings:
For an array of strings: strings with the number of strings being say: cnt then:
qsort(strings, cnt, sizeof(char*), sortstring);
//With the function sortstring defined as:
static int sortstring( const void *str1, const void *str2 )
{
const char *rec1 = *(const char**)str1;
const char *rec2 = *(const char**)str2;
int val = strcmp(rec1, rec2);
return val;
}
string arrays
Creating an array of strings can also be challenging. Again, there are several ways to do this, here are two:
If you know the dimensions of each line, and the total number of lines in both files, then you can do it like this:
char strArray[numLines][longestLine];
If you don't, then you have to determine that at run-time by getting a count of the total number of lines, say when you are reading them from each file. And you will also need the length of the longest line found in both files, say by using strlen() on each one at some point as it is read or written. Once you have that information, you can create your string array like this:
char **strings=0;
Then, before you need it, create memory for it:
char **allocMemoryStr(char **strings, int numStrings, int maxLen)
{
int i;
strings = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
strings[i] = calloc(sizeof(char)*maxLen + 1, sizeof(char));
}
return strings;
}
Finally, when you are finished using dynamically allocated memory, you must always free it:
void freeMemoryStr(char **strings, int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(strings[i]) free(strings[i]);
free(strings);
}

Replace value in string with another from another string

I've been stuck for a while now. The program i'm writing basically changes the false words with the correct ones from the dictionary. However, when i run the program, it gives me no warnings or errors, but it doesn't display anything. Can you please help me?
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int main(void){
char fname[20],word[2500], dictn[50];
int i,j;
float len1, len2;
FILE *inp, *dict, *outp, *fopen();
fpos_t pos1, pos2;
dict= fopen("dictionary.txt", "r");
printf("Enter the path of the file you want to check:\n");
scanf("%s", fname);
inp= fopen(fname, "r");
for(i=0;(fscanf(inp, "%s", word) != EOF); i++){
for(j=0;fscanf(dict, "%s", dictn) != EOF; j++){
fgetpos(inp, &pos1);
fgetpos(dictn, &pos2);
len1=(float)strlen(word);
len2=(float) strlen(dictn);
if(len1<=(0.6*len2)){
fsetpos(dictn, &pos1);
}
if(strncmp(word, dictn, 1)==0){
fsetpos(dictn, &pos1);
}
if(strcmp(word, dictn)==0){
fsetpos(dictn, &pos1);
}
}
printf("%s ", word);
}
fclose(inp);
fclose(dict);
return(0);
}
You can use
sprintf(word, "%s ", dictn);
If your code is working with printf it should work with sprintf, provided you don't overflow "word", including the NULL termination, so you might have to resize "word" if it is smaller than dictn.
First of all, I'm assuming you have created arrays word and dictn with enough size to hold the maximum length string any of your files.
First fault:
In loops you've created, i represents number of strings in input file and j represents number of strings in dictionary. word is your input string variable and dictn is your dictionary string variable. But you want to retrieve and alter word's ith or dictn's jth character. This may cause an error because there can be a case like this:
Suppose there are 10 words at inp file and 100 words at dictn. And in your loops, i have value of 8 and j have value of 88. Corresponding these i and j values, word has string value of, say, apple and dictn has string value of apple also. So this means apple is the 8th word at input file and 88th word at dictionary file. And if one of those if conditions was satisfied, compiler tries to apply a statement like word[i]=dictn[j];. This means word[8] = dictn[88]; for this example. But both of those string have apple as values which consists only 5 characters! And this will cause an error since you've tried to retrieve 88th character of a 5-length string and assign it to the 8th character of a 5-length string. So your code is wrong, it will only work for some cases which will be a rare situation.
Second fault:
I assume you want to read whole dictionary file for every word in input file but you will be able to read it for only first word of input file since you don't reopen it or set position indicator at the beginning of dictionary file after you read whole dictionary.
Third fault:
Your first if statement will never be reached assuming you have created len1 and len2 variables as integers. Because in your if statement, there is a multiplication of a decimal number and an integer which will return 0 as a result and since fscanf() ignores whitespaces, len1 and len2 will be at least 1.
Fourth fault:
Also your else if statement will never be reached because if a string has same value with another, their first character will also be equal to each other and your if statement where you compare their first characters will be also accepted.
Actually, I would write a code as solution but first of all you need to correct things up which are logically wrong because I do not know what you are really try to achieve by your code -just because I commented with full of assumptions-. But I can provide you some guidelines:
Convert your len1 and len2 variables from int to float and cast values which return from strlen() functions to float.
Reopen your dict file for every iteration of outside loop. (And do not forget not to close it).
To change your inp file, you can use a fpos_t type of variable to track your position indicator of your inp file (fgetpos() to get current position and fsetpos() to change position with value of fpos_t variable. You can search them.) and type the word with fprintf() or fputs() to that location to change that string.

Simple count how many integers are in file in C

Im currently learning C through random maths questions and have hit a wall. Im trying to read in 1000 digits to an array. But without specifiying the size of an array first i cant do that.
My Answer was to count how many integers there are in the file then set that as the size of the array.
However my program returns 4200396 instead of 1000 like i hoped.
Not sure whats going on.
my code: EDIT
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
FILE* fp;
const char filename[] = "test.txt";
char ch;
int count = 0;
fp = fopen(filename, "r");
if( fp == NULL )
{
printf( "Cannot open file: %s\n", filename);
exit(8);
}
do
{
ch = fgetc (fp);
count++;
}while (ch != EOF);
fclose(fp);
printf("Text file contains: %d\n", count);
return EXIT_SUCCESS;
}
test.txt file:
731671765313306249192251196744265747423553491949349698352031277450632623957831801698480186947885184385861560789112949495459501737958331952853208805511
125406987471585238630507156932909632952274430435576689664895044524452316173185640309871112172238311362229893423380308135336276614282806444486645238749
303589072962904915604407723907138105158593079608667017242712188399879790879227492190169972088809377665727333001053367881220235421809751254540594752243
525849077116705560136048395864467063244157221553975369781797784617406495514929086256932197846862248283972241375657056057490261407972968652414535100474
821663704844031998900088952434506585412275886668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912883142607690042
242190226710556263211111093705442175069416589604080719840385096245544436298123098787992724428490918884580156166097919133875499200524063689912560717606
0588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
Any help would be great.
You forgot to initialize count, so it contains random garbage.
int count = 0;
(But note that with this change it's still not going to work, since %d in a scanf format means read as many digits as you find rather than read a single digit.)
Turn on your compiler's warnings (-Wall), it will tell you that you didn't initialize count, which is a problem: it could contain absolutely anything when your program starts.
So initialize it:
int count = 0;
The other problem is that the scanfs won't do what you want, at all. %d will match a series of digits (a number), not an individual digit. If you do want to do your counting like that, use %c to read individual characters.
Another approach typically used (as long as you know the file isn't being updated) is to use fseek/ftell to seek to the end of the file, get the position (wich will tell you its size), then seek back to the start.
The fastest approach though would be to use stat or fstat to get the file size information from the filesystem.
If you want number of digits thin you tave to do it char-by-char e.g:
while (isdigit(fgetc(file_decriptor))
count++;
Look up fgetc, getc and scanf in manpages, you don't seem to understand whats going on in your code.
The way C initializes values is not specified. Most of the time it's garbage. Your count variable it's not initialized, so it mostly have a huge value like 1243435, try int count = 0.

Resources