Searching for word in file and add to count - c

I am attempting to search for a word in a file and add to a counter variable every time it appears in the text. In my research I have not been able to find a solution that works. This is the code block I am using so far. N is a variable used earlier in the code to store input from the user(the program prints a menu with multiple options, search is the first in the list). I have checked that the file is opened properly but when I try to execute this block I get an error that buffer != nullptr. Does anyone see the issue?
if (strcmp(n, "S") == 0) {
char search_word = NULL;
printf("What word would you like to search for?");
scanf("%s", search_word);
while(fgets(str, sizeof(str), fp)){
if ((strstr(str, search_word)) != NULL)
i++;
}
printf("Your word appears %d times.", &i);
}

You can use fget instead of scanf
You need to loop strstr a line
#include <stdio.h>
#include <string.h>
int main() {
char search_word[100];
printf("What word would you like to search for?");
gets(search_word); // change scanf to gets
char line[1024];
int i = 0;
while (fgets(line, sizeof(line), fp)) {
char* found = line;
// After getting a line of characters, loop to find search_word and
// go to found empty
while ((found = strstr(found, search_word)) != NULL) {
i++;
found++; // move found to next char
}
}
printf("Your word appears %d times.", i);
return 0;
}

First thing i can see as a potential problem is the variable used in the scanf, you're trying to put an array of char in a char, so instead of using char search_word, use something like char search_word[32]; this way you're able to read an array of char in this case up to 32 characters. and also another problem you have is the usage of the strstr, the function returns the first time the word is found in a string, meaning that if you are using a string like "Hello my name is Jeff. is ..."and you are using the strstr function to search the word "is" the return of the function is the a pointer to "is Jeff. is ..." so you need to use to return value until you get a null return and then move to the next line.

Related

How to save every line in file (IN C) in a variable? :)

I need to save every line of text file in c in a variable.
Here's my code
int main()
{
char firstname[100];
char lastname[100];
char string_0[256];
char string[256] = "Vanilla Twilight";
char string2[256];
FILE *file;
file = fopen("record.txt","r");
while(fgets(string_0,256,file) != NULL)
{
fgets(string2, 256, file);
printf("%s\n", string2);
if(strcmp(string, string2)==0)
printf("A match has been found");
}
fclose(file);
return 0;
}
Some lines are stored in the variable and printed on the cmd but some are skipped.
What should I do? When I tried sscanf(), all lines were complete but only the first word of each line is printed. I also tried ffscanf() but isn't working too. In fgets(), words per line are complete, but as I've said, some lines are skipped (even the first line).
I'm just a beginner in programming, so I really need help. :(
You're skipping over the check every odd number of lines, as you have two successive fgets() calls and only one strcmp(). Reduce your code to
while(fgets(string_0,256,file) != NULL)
{
if( ! strcmp(string_0, string2) )
printf("A match has been found\n");
}
FWIW, fgets() reads and stores the trailing newline, which can cause problem is string comparison, you need to take care of that, too.
As a note, you should always check the return value of fopen() for success before using the returned pointer.

Array of strings being overwritten

I have a program that is trying to take a text file that consists of the following and feed it to my other program.
Bruce, Wayne
Bruce, Banner
Princess, Diana
Austin, Powers
This is my C code. It is trying to get the number of lines in the file, parse the comma-separated keys and values, and put them all in a list of strings. Lastly, it is trying to iterate through the list of strings and print them out. The output of this is just Austin Powers over and over again. I'm not sure if the problem is how I'm appending the strings to the list or how I'm reading them off.
#include<stdio.h>
#include <stdlib.h>
int main(){
char* fileName = "Example.txt";
FILE *fp = fopen(fileName, "r");
char line[512];
char * keyname = (char*)(malloc(sizeof(char)*80));
char * val = (char*)(malloc(sizeof(char)*80));
int i = 0;
int ch, lines;
while(!feof(fp)){
ch = fgetc(fp);
if(ch == '\n'){ //counts how many lines there are
lines++;
}
}
rewind(fp);
char* targets[lines*2];
while (fgets(line, sizeof(line), fp)){
strtok(line,"\n");
sscanf(line, "%[^','], %[^',']%s\n", keyname, val);
targets[i] = keyname;
targets[i+1] = val;
i+=2;
}
int q = 0;
while (q!=i){
printf("%s\n", targets[q]);
q++;
}
return 0;
}
The problem is with the two lines:
targets[i] = keyname;
targets[i+1] = val;
These do not make copies of the string - they only copy the address of whatever memory they point to. So, at the end of the while loop, each pair of target elements point to the same two blocks.
To make copies of the string, you'll either have to use strdup (if provided), or implement it yourself with strlen, malloc, and strcpy.
Also, as #mch mentioned, you never initialize lines, so while it may be zero, it may also be any garbage value (which can cause char* targets[lines*2]; to fail).
First you open the file. The in the while loop, check the condition to find \n or EOF to end the loop. In the loop, if you get anything other than alphanumeric, then separate the token and store it in string array. Increment the count when you encounter \n or EOF. Better use do{}while(ch!=EOF);

counting the number of times one word has been typed in

after numerous attempts to make my program work I turn to you guys. I want to make a program that counts the numbers of times a specific word has been typed in. That specific word has been specified as an argument and I'm trying to recall it by using argc and argv. Then I want the program to count the number of times I type in a word and to finish I want to be able to type in #EOF so it stops and shows me the result. This is what I have been trying on so far.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i=0;
char buf[1026]={'\0'};
char *p="#EOF\n";
fgets(buf, sizeof buf, stdin);
while((strcmp(buf, p) !=0) && (fgets(buf, sizeof buf, stdin) != NULL ))
{
if(strncmp(buf, argv[1], strlen(argv[1])) == 0)
{
i++;
}
}
printf("%d", i);
return 0;
}
I get no errors at all, but nothing really happens either. I did try to check where the fault lies, and I found out that when I try to display the value of I within the if statement it's counting very very very fast!
Thanks in advance!
Well, the first problem is that argv[0] is the name of your program; your parameters start at argv[1].
Also, your while loop is being invoked before you put anything into buf. You definitely need to either use a different loop or initialize buf before-hand to ensure your loop behaves properly.
Also, I recommend making sure that you know exactly what should and should not match. You are doing a substring comparison (strncmp) based on the length of the word to be searched for, but is this what you want? This will get the word in a substring, but do you want that, or the whole word? Also, will the user just type in a word on each line or a sentence in which the word may occur? Is case important?
You have an infinite loop.
fgets(buf, 1025, stdin);
In the above line of code, fgets() will take from stdin a string of characters including the newline character and store it into buf.
A simple fix to that is to add the newline character into the string you check against:
char *p="#EOF\n";
Other issues:
1)
char buf[1026]; // This should be initialized to an empty string when you start
// char buf[1026] = {'\0'}; would do it
char *p="#EOF";
while(strcmp(buf, p) !=0)
2) Because you used a while() loop, and you're checking before getting any input, you'll always enter it at least once. This might not be what you wanted to do. A do/while loop, or grabbing the input as the first step would be better.
3) if(strncmp(buf, argv[0], this is checking against the name of your program, if you wanted to check against the first command line argument you wanted argv[1]
4) If you're trying to check that the first command line argument is the same as what the user is typing you want this:
if(strncmp(buf, argv[1], strlen(argv[1])) == 0)
My version of your code that's working:
int main(int argc, char *argv[])
{
int i=0;
char buf[1026]={'\0'};
char *p="#EOF\n";
do
{
fgets(buf, 1025, stdin);
if(strncmp(buf, argv[1], strlen(argv[1])) == 0)
i++;
} while (strcmp(buf, p) != 0);
printf("%d\n", i);
return 0;
}
Your loop should be:
while( fgets(buf, sizeof buf, stdin) != NULL )
{
}
It doesn't make sense to check that the buffer is non-empty before the fgets().
Note that fgets() will include the line feed, see the documentation. Also note use of sizeof to avoid the use of magical numbers in the code.
If you want the user to really type #EOF to end, rather than ending the input by "sending" the end-of-file signal (Ctrl+D in Linux, Ctrl+Z) in Windows) which will work and cause the loop to exit, you msut of course compare against that before counting the word(s) in the line.

fscanf() error on this text file?

test.txt:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
ccccccccccccccccccccccccccccccccccc
The color of the car is blue
code:
FILE *fp;
char var[30];
int result
if( (fp = fopen( "test.txt", "r")) == NULL) //open for read
printf("ERROR");
result = fscanf( fp, "The color of the car is %s", &var);
After this executes:
opens file (not NULL and was able to execute an append when testing)
result = 0 //zero- in the case of a matching failure....?
errno = 0;
and var is garbage.
I was expecting fscanf() to match "blue".
How should I correctly get blue into var?
Thank You.
How about using fgets instead:
char *search = "The color of the..";
char *p;
while (fgets(var, SIZE, stdin)) {
/* Does it have what we want ? */
if ((p = strstr(var, search)))
break;
}
if (p)
p += strlen(str);
Fscanf doesn't work like this. It doesn't look around nor scan the string for stuff to match. You have to supply a string exactly matching the format specifier. So you could do stuff like
result = fscanf(fp, "aaaaaaaaaaaaa\nbbbbbbbbbbb\ncccccccccc\nThe color of the car is %s", &var);
to achieve what you want.
You have a bug where you are passing in the pointer to an array of char into fscanf, when you should be passing in a pointer to char. It so happens that the address of an array equals the address of the first element of an array, so it works on accident. But, the wrong type is being passed in.
In addition, you want to find the line which provides you with the match, and you seem to want to store "blue" into var. To do this, you should test to see if a line of input matches your scan pattern. You can use fgets to read a line, and use sscanf to scan the line.
while (fgets(buf, sizeof(buf), fp) != 0) {
result = sscanf(buf, "The color of the car is %s", var);
if (result == 1) break;
}
sscanf will return how many directives it successfully scanned. In this case, there is the one %s directive.
Doing it this way prevents a scanning error from "jamming" your input parsing. That is, if fscanf returns an error, it will fail to move past the input that caused the error until you call clearerr().
You have another bug here in that if test.txt doesn't exist, your code will go ahead and use fscanf anyway, making your check useless. This would almost certainly cause the program to crash.
Use regex
char p[100];
char q[100];
char r[100];
fscanf(fp, "%[^\n]\n%[^\n]\n%[^\n]\nThe color of the car is %s",p,q,r, &var);
Modify it according to your requirement. I know this is not your actual string.

Reading formatted strings from file into Array in C

I am new to the C programming language and trying to improve by solving problems from the Project Euler website using only C and its standard libraires. I have covered basic C fundamentals(I think), functions, pointers, and some basic file IO but now am running into some issues.
The question is about reading a text file of first names and calculating a "name score" blah blah, I know the algorithm I am going to use and have most of the program setup but just cannot figure out how to read the file correctly.
The file is in the format
"Nameone","Nametwo","billy","bobby","frank"...
I have searched and searched and tried countless things but cannot seem to read these as individual names into an array of strings(I think thats the right way to store them individually?) I have tried using sscanf/fscanf with %[^\",]. I have tried different combos of those functions and fgets, but my understanding of fgets is everytime I call it it will get a new line, and this is a text file with over 45,000 characters all on the same line.
I am unsure if I am running into problems with my misunderstanding of the scanf functions, or my misunderstanding with storing an array of strings. As far as the array of strings goes, I (think) I have realized that when I declare an array of strings it does not allocate memory for the strings themselves, something that I need to do. But I still cannot get anything to work.
Here is the code I have now to try to just read in some names I enter from the command line to test my methods.
This code works to input any string up to buffer size(100):
int main(void)
{
int i;
char input[100];
char* names[10];
printf("\nEnter up to 10 names\nEnter an empty string to terminate input: \n");
for(int i = 0; i < 10; i++)
{
int length = 0;
printf("%d: ", i);
fgets(input, 100, stdin);
length = (int)strlen(input);
input[length-1] = 0; // Delete newline character
length--;
if(length < 1)
{
break;
}
names[i] = malloc(length+1);
assert(names[i] != NULL);
strcpy(names[i], input);
}
}
However, I simply cannot make this work for reading in the formatted strings.
PLEASE advise me as to how to read it in with format. I have previously used sscanf on the input buffer and that has worked fine, but I dont feel like I can do that on a 45000+ char line? Am I correct in assuming this? Is this even an acceptable way to read strings into an array?
I apologize if this is long and/or not clear, it is very late and I am very frustrated.
Thank anyone and everyone for helping, and I am looking forward to finally becoming an active member on this site!
There are really two basic issues here:
Whether scanning string input is the proper strategy here. I would argue not because while it might work on this task you are going to run into more complicated scenarios where it too easily breaks.
How to handle a 45k string.
In reality you won't run into too many string of this size but it is nothing that a modern computer of any capacity can't easily handle. Insofar as this is for learning purposes then learn iteratively.
The easiest first approach is to fread() the entire line/file into an appropriately sized buffer and parse it yourself. You can use strtok() to break up the comma-delimited tokens and then pass the tokens to a function that strips the quotes and returns the word. Add the word to your array.
For a second pass you can do away with strtok() and just parse the string yourself by iterating over the buffer and breaking up the comma tokens yourself.
Last but not least you can write a version that reads smaller chunks of the file into a smaller buffer and parses them. This has the added complexity of handling multiple reads and managing the buffers to account for half-read tokens at the end of a buffer and so on.
In any case, break the problem into chunks and learn with each refinement.
EDIT
#define MAX_STRINGS 5000
#define MAX_NAME_LENGTH 30
char* stripQuotes(char *str, char *newstr)
{
char *temp = newstr;
while (*str)
{
if (*str != '"')
{
*temp = *str;
temp++;
}
str++;
}
return(newstr);
}
int main(int argc, char *argv[])
{
char fakeline[] = "\"Nameone\",\"Nametwo\",\"billy\",\"bobby\",\"frank\"";
char *token;
char namebuffer[MAX_NAME_LENGTH] = {'\0'};
char *name;
int index = 0;
char nameArray[MAX_STRINGS][MAX_NAME_LENGTH];
token = strtok(fakeline, ",");
if (token)
{
name = stripQuotes(token, namebuffer);
strcpy(nameArray[index++], name);
}
while (token != NULL)
{
token = strtok(NULL, ",");
if (token)
{
memset(namebuffer, '\0', sizeof(namebuffer));
name = stripQuotes(token, namebuffer);
strcpy(nameArray[index++], name);
}
}
return(0);
}
fscanf("%s", input) reads one token (a string surrounded by spaces) at a time. You can either scan the input until you encounter a specific "end-of-input" string, such as "!", or you can wait for the end-of-file signal, which is achieved by pressing "Ctrl+D" on a Unix console or by pressing "Ctrl+Z" on a Windows console.
The first option:
fscanf("%s", input);
if (input[0] == '!') {
break;
}
// Put input on the array...
The second option:
result = fscanf("%s", input);
if (result == EOF) {
break;
}
// Put input on the array...
Either way, as you read one token at a time, there are no limits on the size of the input.
Why not search the giant string for quote characters instead? Something like this:
#include <stdio.h>
#include <string.h>
int main(void)
{
char mydata[] = "\"John\",\"Smith\",\"Foo\",\"Bar\"";
char namebuffer[20];
unsigned int i, j;
int begin = 1;
unsigned int beginName, endName;
for (i = 0; i < sizeof(mydata); i++)
{
if (mydata[i] == '"')
{
if (begin)
{
beginName = i;
}
else
{
endName = i;
for (j = beginName + 1; j < endName; j++)
{
namebuffer[j-beginName-1] = mydata[j];
}
namebuffer[endName-beginName-1] = '\0';
printf("%s\n", namebuffer);
}
begin = !begin;
}
}
}
You find the first double quote, then the second, and then read out the characters in between to your name string. Then you process those characters as needed for the problem in question.

Resources