strncmp gives 0 even when strings are NOT equal - C - c

I am having a situation with strncmp function in C, it is returning 0 even when the words do not match, in the example below, I am testing it with the letter 'R' and when running the code it returns 0 even when the compared word in the txt document is 'RUN'. Do you happen to know whether
Am I missing something in the strncmp function or somewhere else in my code?
Thank you for your input.
bool lookup(string s);
int main(void) {
char *s;
s = "R";
if (lookup(s)) {
printf("Word found =)\n");
} else {
printf("Word not found =(\n");
}
}
// Looks up word, s, in txt document.
bool lookup(string s)
{
// TODO
char *wordtosearch;
wordtosearch = s;
int lenwordtosearch = strlen(wordtosearch);
char arraywordindic[50];
// Open txt file
FILE *file = fopen("text.txt", "r");
if (file == NULL)
{
printf("Cannot open file, please try again...\n");
return false;
}
while (!feof(file)) {
if (fgets(arraywordindic, 50, file) != NULL) {
char *wordindic;
wordindic = arraywordindic;
int result = strncmp(wordindic, wordtosearch, lenwordtosearch);
if (result == 0) {
printf("%i\n", result);
printf("%s\n", wordindic);
printf("%s\n", wordtosearch);
fclose(file);
return true;
}
}
}
fclose(file);
return false;
}

The thing is that it compares R with RUN and it gives 0. I want it to
return 0 when it finds R only.
In this case you need to compare whole words using the function strcmp instead of comparing only lenwordtosearch characters using the function strncmp.
Take into account that the function fgets can append the new line character '\n' to the entered string. You need to remove it before comparing strings.
if (fgets(arraywordindic, 50, file) != NULL) {
arraywordindic[ strcspn( arraywordindic, "\n" ) ] = '\0';
int result = strcmp(arraywordindic, wordtosearch);
if (result == 0) {
printf("%i\n", result);
printf("%s\n", arraywordindic);
printf("%s\n", wordtosearch);
As a result these declarations
int lenwordtosearch = strlen(wordtosearch);
and
char *wordindic;
wordindic = arraywordindic
may be removed.
And the condition of the while loop should be written like
while ( fgets(arraywordindic, 50, file) != NULL ) {
arraywordindic[ strcspn( arraywordindic, "\n" ) ] = '\0';
int result = strcmp(arraywordindic, wordtosearch);
if (result == 0) {
printf("%i\n", result);
printf("%s\n", arraywordindic);
printf("%s\n", wordtosearch);
//...

int result = strncmp(wordindic, wordtosearch, lenwordtosearch);
This is going to give you zero if the first lenwordtosearch characters of wordtosearch matches the first lenwordtosearch characters of any word in the dictionary.
Given that the word you're searching for is S, any word in the dictioanary that starts with S is going to give you a match.
You should probably be checking the entire word. That probably means cleaning up the word you've read in from the file (i.e., removing newline) and using strcmp() instead, something like:
wordindic = arraywordindic;
// Add this:
size_t sz = strlen(wordindic);
if (sz > 0 && wordindic[sz - 1] == '\n')
wordindic[sz - 1] = '\0';
// Modify this:
// int result = strncmp(wordindic, wordtosearch, lenwordtosearch);
int result = strcmp(wordindic, wordtosearch);

Related

Best way to iterate through a file with new line separators

Let's say I want to read a file where each line has a string, and when there is a new line or the end of the file, I print the number of characters read. For example,
abcdf
asd
sdfsd
aa
This would print (counting new line characters at the end of each string):
10
8
(there is no new line at the end of the last line, so we get 8 instead of 9). I could do something like this
FILE* f;
// ...
int charCount = 0;
char line[20];
while (fgets(line, sizeof line, f))
{
if (strcmp(line, "\n") == 0)
{
printf("%d\n", charCount);
charCount = 0;
}
else
{
charCount += strlen(line);
}
}
printf("%d\n", charCount);
Notice that I have to repeat the printf after the loop ends, because if I don't, I wouldn't print the last value (because the file reached the end and there is not a new line at the end). For a printf, this is not that bad, but if I had something more complicated, it would result in a lot of repeated code. My workaround is putting what I want inside a function and just call the function after the loop, but I feel like there has to be a better way. Is there a better way to parse through a file like this? Preferably not character by character in case I have some formatted data that I need to use fscanf with.
You can move your fgets call into the body of the while loop, while checking its result in the loop condition and in the printing condition. It should be properly initialized before the loop to a non-NULL value.
FILE* f;
// ...
int charCount = 0;
char line[20];
char *result = line;
while (result)
{
result = fgets(line, sizeof line, f);
if ( result == NULL || strcmp(line, "\n") == 0 )
{
printf("%d\n", charCount);
charCount = 0;
}
else
{
charCount += strlen(line);
}
}
You could just do it the caveman way...
char ch;
int i = 0;
FILE *fp = fopen("yourfile.txt", "r");
while (feof(fp) == 0)
{
i++;
if ((ch = fgetc(fp)) == '\n')
printf("%d\n", --i), i = 0;
}
if (i > 1) printf("%d\n", --i);
fclose(fp);

How do i read an array of strings from a file?

I have a file with different words separated by newlines. How can i read and store each word in an array of strings?
1 word, 1 row of the array.
I'm posting this code, but im pretty sure it doesnt work, because i can't understand if i should use fgets or fscanf and how i can write each word in each line of my array.
int file_string_temp_number_rows=200;
int file_string_temp_number_cols=200;
char **file_string_arr = (char**)malloc (file_string_temp_number_rows*sizeof(char));
for ( i = 0 ; i < file_string_temp_number_rows ; i++){
file_string_arr[i] = (char*)malloc(file_string_temp_number_cols*sizeof(char));
}
if ((file_ptr= fopen(filename, "r"))){
if((file_ptr=fopen(filename,"r"))==NULL)
{
printf("errore apertura file");
return 1;
}
else{
while(!feof(file_ptr)){
for(i = 0 ; i < file_string_temp_number_rows ; i++){
for(j = 0 ; j < file_string_temp_number ; j++){
fgets(file_string_arr , 40 , filename);
}
}
}
}
}
}
Addressing your title question: How do i read an array of strings from a file?
There are many approaches to do this. Here is a list of basic steps that could be used.
1) Using fopen(), open file and scan to determine the following:
- Maximum word length.
- Count of words in file.
2) Create container: - Use calloc() to create an array of strings for words.
3) Using fopen() (again), fgets() and strtok() (or variant) to parse content of file into string array.
Note, The sample implementation snippets below use particular functions and techniques, but you should not limit your implementation to only these. There are many paths that would work just as well, so do not be afraid to experiment. For example, either fgets() or fscanf() could be used to solve this problem. The methods highlighted below are just examples of one way to do the task.
Scan example
// provides count of words, and longest word
int longestWord(char *file, int *nWords)
{
FILE *fp=0;
int cnt=0, longest=0, numWords=0;
char c;
fp = fopen(file, "r");
if(fp)
{
// if((strlen(buf) > 0) && (buf[0] != '\t') && (buf[0] != '\n') && (buf[0] != '\0')&& (buf[0] > 0))
while ( (c = fgetc(fp) ) != EOF )
{
if ( isalnum (c) ) cnt++;
else if ( ( ispunct (c) ) || ( isspace(c) ) || (c == '\0' ))
{
(cnt > longest) ? (longest = cnt, cnt=0) : (cnt=0);
numWords++;
}
}
*nWords = numWords;
fclose(fp);
}
else return -1;
return longest;
}
//in main eg:
int longest;
int count;
...
longest = longestWord(".\\file.txt", &count);//longest and count will be
//used to create string arrays
Create string array example
//Create string arrays to contain words using result from original scan of file
char ** Create2DStr(ssize_t numStrings, ssize_t maxStrLen)
{
int i;
char **a = {0};
a = calloc(numStrings, sizeof(char *));
for(i=0;i<numStrings; i++)
{
a[i] = calloc(maxStrLen + 1, 1);
}
return a;
}
// in main(): Create array of words
char **words = Create2DStr(count, longest);//Using values obtained from scan section above
if(words) { //continue
Parse into word strings example
// in main(), after performing scan and array creation:
const char delim[] = {" \n\t"};
char line[260];
char *buf = NULL;
fp = fopen(".\\file.txt", "r");
cnt=0;
while(fgets(line, 260, fp))//keep reading lines until EOF
{
buf = strtok(line, delim);
while(buf)//continue until last word in line is parsed
{
if((strlen(buf) > 0)
{
strcpy(words[cnt], buf);
cnt++; //use as accurate count of words.
}
buf = strtok(NULL, DELIM);
}
}
fclose(fp);

Counting characters in comments in c program

Hi I'm trying to figure how to count characters in comments in c program. So far i had written a function that doesn't work, but seems logical. Can you please help me complete my task.My quest is to fill buffer with all the characters from the comments and then count them.
void FileProcess3(char* FilePath)
{
char myString [1000];
char buffer[1000];
FILE* pFile;
int i = 0;
pFile = fopen (FilePath, "r");
while(fgets( myString, 1000, pFile) != NULL)
{
int jj = -1;
while(++jj < strlen(myString))
{
if ( myString[jj] == '/' && myString[jj+1] == '*')
{
check = 1;
jj++;
jj++;
}
if( check == 1 )
{
if ( myString[jj] == '*' && myString[jj+1] == '/')
{
check = 0;
break;
}
strcat( buffer, myString[jj] );
}
}
}
printf(" %s ", buffer );
fclose(pFile);
}
E.g. fix to
int i = 0, check = 0;
...
if( check == 1 )
{
if ( myString[jj] == '*' && myString[jj+1] == '/')
{
check = 0;
break;
}
buffer[i++] = myString[jj];
}
}
}
buffer[i]='\0';/* add */
strcat() concatenates (NUL-terminated) strings, so this is definitely wrong
(and should give a compiler warning due to the wrong type of the second argument):
strcat( buffer, myString[jj]);
You could do something like
buffer[length] = myString[jj];
buffer[length+1] = 0;
length++;
where length is an integer initialized to zero that keeps track of the current length.
Of course you should check the length against the available size of the buffer
to avoid a buffer(!) overflow.
If your intention is only to count the characters, then you don't have to copy
them to a separate buffer at all. Just increment a counter.
You should also note that fgets() does not remove the newline characters from the
input. So you have to check for that if you don't want to include the newlines
in the count.

How do I return a specific line from a file if it partially matches a string parameter? [C]

I am new to C but I am trying to write a function that returns a line from a file depending on the parameter used. It will return the last line that contains that parameter. I think it's better explained using an example:
Here is the contents of the file:
1 one onehello
2 two twohello
3 one threehello
So, if I call the function like this:
lineContaining("one")
It should return "one threehello"
Here is what I have so far, it also includes a main function that tests the function:
char *readStringedCommand(char *str1)
{
int size = 1024;
char *buffer = malloc(size);
char *result = malloc(size);
FILE *fp;
fp = fopen("test.txt", "r");
while(fgets(buffer, 1024, fp)) //get a line from a file
{
printf("while1 entered: %s", buffer);
int i = 0;
int j = 0;
int k = 0;
while(buffer[i] != '\n') //read all the way to the end of a line
{
printf("while2 entered: %s", buffer+i);
k = i;
while(buffer[k]==str1[j]) //while two characters match
{
printf("while3 entered");
k++;
j++;
strcat(result, buffer+k); //append the character to the result
if(str1[j] = '\0') //if the next character of str1 is the last one
{
strncat(result, buffer+k, 20); //append the rest of buffer to the result
return result;
printf("result = %s", result);
}
}
result[0] = '\0'; //clear result for the next line
j = 0; //set str1's position to 0
k = 0;
i++;
}
}
return "errorrrrrr";
}
int main(int argc, const char* argv[])
{
int num1 = 1;
char str1[] = "one onehello";
int num2 = 2;
char str2[] = "two twohello";
int num3 = 3;
char str3[] = "one threehello";
hwrite(num1, str1); //a function I made that writes a line to a file
hwrite(num2, str2);
hwrite(num3, str3);
printf("%s", readStringedCommand("one"));
return 0;
}
Okay, the function gives me an error:
while1 entered: 1 one onehello
while2 entered: 1 one onehello
while2 entered: one onehello
while2 entered: one onehello
Segmentation fault (core dumped)
Considering it gives me the error at the third while loop, I think the problem is there. I unfortunately don't know what is wrong here. I am sure there are more errors after that point but this one is confusing me.
MY QUESTIONS:
How do I fix this segmentation error?
The code is obviously very ugly but I suck at C. Is there a better way to solve this question?
Thanks for reading all of this and I would appreciate some help. =(
EDIT: After fixing some errors suggested by you guys, I no longer get the segmentation error. The function returns " onehello" instead, which is wrong. It should return "one threehello". But I am making progress, and for that I am thankful.
if(str1[j] = '\0')
should be
if(str1[j] == '\0')
you probably want to compare values
the loop while(buffer[i] != '\n') might not exit if your file is missing a newline character, what might happen in the last line of in .txt file.
So if I understand your problem correctly, your goal can be achieved in a much simpler way:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *readStringedCommand(char *str1)
{
int size = 1024;
char *buffer = malloc(size);
char *result = malloc(size);
/* Check allocations */
if (!buffer || !result) {
fprintf(stderr, "Allocation failure, exiting.\n");
exit(EXIT_FAILURE);
}
result[0] = 0; // 0-terminate result
FILE *fp;
fp = fopen("test.txt", "r");
/* Check whether file was opened successfully */
if (!fp) {
fprintf(stderr, "Couldn't open file.\n");
exit(EXIT_FAILURE);
}
while(fgets(buffer, size, fp)) //get a line from a file
{
if (strstr(buffer, str1)) { // Check whether the line contains the needle
strcpy(result, buffer); // Copy the line if it does
}
}
// close file
fclose(fp);
// Free memory we don't need anymore
free(buffer);
// Now, what if no line contained the needle?
if (result[0] == 0) {
// Hmm, maybe
free(result);
return NULL; // ?
} else {
return result;
}
}
Just use strstr from the standard library to check whether str1 is contained in each line, copy each line that contains it to result, ignore the others. Then at the end, result contains the last line that contained str1 - if any.
If you don't want the entire line, but only the part starting at the first occurrence of str1, capture the pointer that strstr returns, and use that as the source for the strcpy:
char *needle;
if ((needle = strstr(buffer, str1))) {
strcpy(result, needle);
}

The curse of the \n character in C

I've made a simple spellchecker that reads in a dictionary and user text file to check against it. The program needs to display the line and word index of any word not in the dictionary. So it works fine until the user text file has a return \n character in it (at the end of a paragraph or sentence). So Hello is actually tested against the dictionary as Hello\n and the program believes its spelled incorrectly. Can anyone advise a method to remove the \n character? Here is my code:
#include <stdio.h>
#include <string.h>
void StrLower(char str[])
{
int i;
for (i = 0; str[i] != '\0'; i++)
str[i] = (char)tolower(str[i]);
}
int main (int argc, const char * argv[]) {
FILE *fpDict, *fpWords;
fpWords = fopen(argv[2], "r");
if((fpDict = fopen(argv[1], "r")) == NULL) {
printf("No dictionary file\n");
return 1;
}
char dictionaryWord[50]; // current word read from dictionary
char line[100]; // line read from spell check file (max 50 chars)
int isWordfound = 0; // 1 if word found in dictionary
int lineCount = 0; // line in spellcheck file we are currently on
int wordCount = 0; // word on line of spellcheck file we are currently on
while ( fgets ( line, sizeof line, fpWords ) != NULL )
{
lineCount ++;
wordCount = 0;
char *spellCheckWord;
spellCheckWord = strtok(line, " ");
while (spellCheckWord != NULL) {
wordCount++;
spellCheckWord = strtok(NULL, " ,");
if(spellCheckWord==NULL)
continue;
StrLower(spellCheckWord);
printf("'%s'\n", spellCheckWord);
while(!feof(fpDict))
{
fscanf(fpDict,"%s",dictionaryWord);
int res = strcmp(dictionaryWord, spellCheckWord);
if(res==0)
{
isWordfound = 1;
break;
}
}
if(!isWordfound){
printf("word '%s' not found in Dictionary on line: %d, word index: %d\n", spellCheckWord, lineCount, wordCount); //print word and line not in dictionary
}
rewind(fpDict); //resets dictionarry file pointer
isWordfound = 0; //resets wordfound for next iteration
}
}
fclose(fpDict);
fclose(fpWords);
return 0;
}
Wow thanks for the quick responses everyone. You guys are great, over the moon with that!
Remove the '\n' Immediately after the fgets() call:
while ( fgets ( line, sizeof line, fpWords ) != NULL )
{
size_t linelen = strlen(line);
assert((linelen > 0) && "this can happen only when file is binary");
if (line[linelen - 1] == '\n') line[--linelen] = 0; /* remove trailing '\n' and update linelen */
Try adding \n to the argument you pass to strtok.
If you simply want to remove the character for the sake of comparison, and know it will be at the end of a line, then when you read the word into your buffer, do a strchr() for \n and then replace that position with \0 if you find it.
How about:
size_t length = strlen(dictionaryWord);
if (length > 0 && dictionaryWord[length-1] == '\n') {
dictionaryWord[length-1] = 0;
}

Resources