In order to check if a word exist in a .txt file I've done the following function :
void checkWord (char* word){
FILE* file = fopen("file.txt", "r");
char line[1000] = "";
if(file != NULL){
while(fgets(line, 1000, file) != NULL){
if (strcmp(line, word) == 0){
printf("hello"); }
}
}
fclose(file);
}
Yet this code doesn't print hello when I call : checkWord("hello"); on the file :
aaaaa
hello
aaaaa
but does print hello when I call : checkWord("hello"); on the file :
aaaa
hello
and I don't understand why.
In the first file the string hello is not contained by the last line, so it is followed by a '\n' character. In the second fole the same string is at the end of file (so no trailing '\n').
The core of the issue is that fgets() stops parsing when a newline character is found AND it doesn't remove that character from the returned string. For this reason an exact match is not found in the first file, when the actual string is "hello\n".
In order to solve it you can either remove the trailing '\n' from the string read by fgets or, if the requirements allow it, search just for the presence of the substring by issuing strstr ().
Although you can't see it, the end of every line except the last one in your file contains a new line character. This is represented by \n. When comparing elements line by line, you will have to account for the fact that most lines will have this character at the end.
Related
I have a problem with my code, I'm trying to search a string in a file and I can read it but, when I compare two strings it takes only the last one of the file as equal to the the first string entered with the scanf().
So imagine I wrote in my file three words and each one is returning to the line.
test
test12
test123
If in my scanf() I write test12 for example or test when it's going to read it will return false to the compare so (!== 0). But if I write test123 it will works because it's the last word of the file but I don't know why?
char word[26];
char singleLine[26];
FILE *file = fopen("bin/Release/myWords.txt", "a+");
scanf("%26s", word);
if (file != NULL) {
while (!feof(file)) {
fgets(singleLine, 26, file);
compare = strcmp(singleLine, word);
if (compare == 0) {
printf("\n%s\n",word);
}
}
fclose(file);
}
Your program only works in very special cases and has several problems:
scanf("%26s", word); may affect up to 27 bytes in the destination array, which is defined with a length of only 26.
furthermore, you should check the return value to avoid undefined behavior on invalid input.
fopen("bin/Release/myWords.txt", "a+"); opens the file in append mode: is this necessary?
while (!feof(file)) is always wrong, you should instead check the return value of fgets() that returns NULL at end of file.
compare = strcmp(singleLine, word); only compares for an exact math of the full line, which can only happen if the word has 25 characters, otherwise the trailing newline in singleLine will cause the comparison to fail. Furthermore, broken lines may cause unexpected results, as well as if the file does not end with a newline.
the reason it matches the last word in the file is you forget to write a trailing newline after the last word in the file, so the last fgets() fills the buffer with the exact word and no trailing newline.
if you search for matches inside the line, you should use a larger buffer and search for a match with strstr.
if you search for a exact match, you should strip the trailing newline before the comparison.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int main() {
char word[27];
char singleLine[256];
FILE *file = fopen("bin/Release/myWords.txt", "r");
if (scanf("%26s", word) != 1)
return 1;
if (file != NULL) {
while (fgets(singleLine, sizeof singleLine, file)) {
singleLine[strcspn(singleLine, "\n")] = '\0'; // strip the newline if any
compare = strcmp(singleLine, word);
if (compare == 0) {
printf("\n%s\n", word);
}
}
fclose(file);
}
return 0;
}
I have a weird bug.
I wrote a function that gets a file and returns the length of each line:
void readFile1(char *argv[], int fileNumber,
char *array_of_lines[NUMBER_OF_LINES+1], int *currNumOfLines)
{
FILE* fp;
fp = fopen(argv[fileNumber], "r");
if (fp == NULL)
{
fprintf(stderr, MSG_ERROR_OPEN_FILE, argv[fileNumber]);
exit(EXIT_FAILURE);
}
char line[256];
while (fgets(line, sizeof(line), fp))
{
printf("\n line contains : %s size is : %lu\n",line,strlen(line));
}
}
The function always prints the right number + 2,
For example if file.txt contains only one line with "AAAAA" the function would print that the length is 7 instead of 5,
line contains : AAAAA
size is : 7
Does someone know where is the bug?
Don't forget that fgets leaves the newline in the buffer.
It seems you're reading a file created in Windows (where a newline is the two characters "\r\n") on a system where newline is only "\n". Those two characters are also part of the string and will be counted by strlen.
The reason I'm guessing you're reading a Windows-created file in a non-Windows system is because for files open in text-mode (the default) then the functions reading and writing strings will translate newlines from and to the operating-system dependent format.
For example on Windows, when writing plain "\n" it will be translated and actually written as "\r\n". When reading the opposite translation happens ("\r\n" becomes "\n").
On a system with plain "\n" line endings (like Linux or macOS), no translation is needed, and the "\r" part will be treated as any other character.
printf("\n line contains : %s size is : %lu\n",line,strlen(line));
Here's a giveaway
Obtained output
line contains : AAAAA
size is : 7
Expected output
line contains : AAAAA size is : 7
I have read all the text from a desired file and it is now stored in buff. I want to copy just the string content after identifier strings such as 'Title'.
Example file below:
"Title: I$_D$-V$_{DS}$ Characteristic Curves (Device 1)
MDate: 2016-03-01
XLabel: Drain voltage V$_{DS}$
YLabel: Drain current I$_D$
CLabel: V$_{GS}$
XUnit: V
... "
for(;;) {
size_t n = fread(buff, 1 , DATAHOLD, inFile);
subString = strstr( buff, "Title");
if( subString != NULL) {
strcpy(graph1.title , (subString + 7));
subString = NULL;
}
....more if statements....
if( n < DATAHOLD) {
break;
}
}
I understand that strstr() returns a pointer to location of the search string, I added 7 to get just the text that comes after the search string and this part works fine. The problem is strcpy() copies the rest of buff character array into graph1.title.
How to instruct strcpy() to only copy the text on the same line as the substring pointer? Using strtok() maybe?
I agree with ChuckCottrill, it would be better if you read and process one line at a time.
Also since the file you are dealing with is a text file, you could be opening it in text mode.
FILE *fin = fopen("filename", "r");
Read a line with fgets() into a string str. It should be noted that fgets() will take the trailing \n' to str.
fgets(str, sizeof(str), fin);
char *substring;
if( (substring = strstr(str, "Title: ")) != NULL )
{
strcpy(graph1.title, substring+strlen("Title: "));
}
At this point, graph1.title will have I$_D$-V$_{DS}$ Characteristic Curves (Device 1) in it.
Read and process a single line at a time.
for( ; fgets(line,...); ) {
do stuff on line
}
You could use another strstr to get the position of the end of the line, and then use strncpy which is like strcpy, but accepts a third argument, the number of chars to copy of the input.
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.
I would like to open a directory using opendir but am seeing something unexpected. opendir works for the string returned from getcwd but not the string from my helper function read_cwd, even though the strings appear to be equal.
If I print the strings, both print /Users/gwg/x, which is the current working directory.
Here is my code:
char real_cwd[255];
getcwd(real_cwd, sizeof(real_cwd));
/* This reads a virtual working directory from a file */
char virt_cwd[255];
read_cwd(virt_cwd);
/* This prints "1" */
printf("%d\n", strcmp(real_cwd, virt_cwd) != 0);
/* This works for real_cwd but not virt_cwd */
DIR *d = opendir(/* real_cwd | virt_cwd */);
Here is the code for read_cwd:
char *read_cwd(char *cwd_buff)
{
FILE *f = fopen(X_PATH_FILE, "r");
fgets(cwd_buff, 80, f);
printf("Read cwd %s\n", cwd_buff);
fclose(f);
return cwd_buff;
}
The function fgets includes the final newline in the buffer — so the second string is actually "/Users/gwg/x\n".
The simplest (but not necessarily the cleanest) way to solve this issue is to overwrite the newline with a '\0': add the following at the end of the function read_cwd:
n = strlen(cwd_buff);
if(n > 0 && cwd_buff[n - 1] == '\n')
cwd_buff[n - 1] = '\0';
fgets() includes the newline.
Parsing stops if end-of-file occurs or a newline character is found, in which case str will contain that newline character. — http://en.cppreference.com/w/c/io/fgets
You should trim the white space on both ends of the string when reading input like this.
From the fgets man page:
fgets() reads in at most one less than size characters from stream and
stores them into the buffer pointed to by s. Reading stops after an
EOF or a newline. If a newline is read, it is stored into the buffer.
A terminating null byte (aq\0aq) is stored after the last character in
the buffer.
You need to remove the newline character from the string you are reading in.