views:

343

answers:

7

So my code isn't working...

test.c:27: warning: passing argument 1 of ‘search’ from incompatible pointer type

which is the fgets line.

My code opens a file, reads the file line by line, and I'm trying to create a "search" function that will return a value that indicates whether that string is found on that line of the file.

My ultimate goal is to achieve a search and replace program. But one step at a time eh? this is what I have so far:

#include <stdio.h>
#include <string.h>

int search(const char *content[], const char *search_term)
{
    int t;

    for(t=0; content[t]; ++t){
        if(!strcmp(content[t], search_term)){
            return t; // found
        }
    }
    return 0; // not found
}


int main(int argc, char *argv[])
{
    FILE *file;
    char line[BUFSIZ];
    int linenumber=0;
    char term[20] = "hello world";

    file = fopen(argv[1], "r");
    if(file != NULL){
        while(fgets(line, sizeof(line), file)){
            if(search(line, term) != -1){
                printf("Search Term Found!!\n");
            }
            ++linenumber;
        }
    }       
    else{
        perror(argv[1]); 
    }

    fclose(file);
    return 0;
}
+2  A: 

If I understand you correctly you are just re-implementing the strstr() libc function in a very inefficient way.

Thorsten79
+1: for the "your question isn't bad, the fact you are asking it is" ... unless it is homework ;)
Aiden Bell
yes, but the problem I have here is that strstr does not search as a whole word, but any thing that it matches, first. (Am I right?) Example, say I have string "Hello Wonderful World", using strstr("Hello Wonderful World", "Wonder"), but I'm saying does "Wonder" in the string exist? the strstr function will say yes and return "Wonderful World", which is not what I want.
chutsu
@chutsu: strstr doesn't return a string, it returns a pointer to a position in the string, or NULL if the search term is not found. If you want to figure out if the term was found on the line, just compare the result to NULL.
Phil
@chutsu, If you use the pointer returned by `strstr` (or `strcasestr`) and use only match the length of the "needle" (e.g. `strlen("Wonder")`), then it will match your search string "in situ".
mctylr
+2  A: 

Change

int search(const char *content[], const char *search_term)

to

int search(const char content[], const char *search_term)

EDIT:

Also change:

if(!strcmp(content[t], search_term)){

to

if(!strcmp(&content[t], search_term)){

or

if(!strcmp(content + t, search_term)){

Since you are using strcmp to find the match, you'll not be able to find all occurrences of the search string the the file. You'll find only those lines that end in the search_string.

Example: your search string is "hello world" and say the file has 2 lines:

I wrote hello world
hello world is good

In this case your program will be able to find only the 1st occurrence and not the 2nd.

Even for this match to be found there are some more changes needed to your code:

The string read by fgets has a trailing newline, you'll have to get rid of it like:

while(fgets(line, sizeof(line), file)){
  line[strlen(line)-1] = 0;

Also when the search fails you are returning 0, which should be changed to -1.

codaddict
if I do that I get:test.c:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast
chutsu
+1  A: 

try this :

int search(const char *content, const char *search_term)
Seb
+2  A: 

The argument type:

const char *content[]

Is incorrect. Use :

const char *content  

/

#include <stdio.h>
#include <string.h>

int search(const char *content, const char *search_term)
{
    int t;

    for(t=0; content+t; ++t){
        if(!strcmp(content[t], search_term)){
            return t; // found
        }
    }
    return 0; // not found
}


int main(int argc, char *argv[])
{
    FILE *file;
    char line[BUFSIZ];
    int linenumber=0;
    char term[20] = "hello world";

    file = fopen(argv[1], "r");
    if(file != NULL){
        while(fgets(line, sizeof(line), file)){
            if(search((const char*)line, term) != -1){
                printf("Search Term Found!!\n");
            }
            ++linenumber;
        }
    }       
    else{
        perror(argv[1]); 
    }

    fclose(file);
    return 0;
}
Aiden Bell
what does the: (const char*)line do??
chutsu
Casts the type so the compiler doesn't complain, and so that it handles it in the right way. Providing the cast is to compatible type (in memory structure) you are safe. Otherwise, segfaults and other nasties ensue ... the beauty of C.
Aiden Bell
+1  A: 
  1. fix the argument to search as others have said.
  2. You need to take the address of content[t] to pass to strcmp. content[t] is a character, not a string.
  3. I think you still have a few other issues as well. return 0; for example - perhaps return -1?

  4. Also... I think you might need to use strncmp to find the term in the line.

eg.

int search(char *content, const char *search_term)
{
    int t;

    for(t=0; content[t]; ++t){
        if(!strncmp(&content[t], search_term, strlen(search_term))){
            return t; // found
        }
    }
    return -1; // not found
}
philcolbourn
A: 

An empty array declaration is really just a pointer, so in the parameter list to search, "const char *content[]" is the same as "const char **content". You should change that to "const char *content" or "const char content[]".

Then you'll have to change the call to strcmp to use &(content[t]), which returns a pointer to the memory location of the t'th character in content. You can also use (content + t), though some people find that pointer arithmetic is bad form.

David
A: 

Try this method out instead:

int search(const char *content, const char *search_term)
{
   char *result = strstr(content, search_term);
   if(result == NULL) return 0;
   return (int)(result - content);
}

The difference between result and content is exactly the index at which the result was found. I believe this is what you are looking for?

I think though there is room for improvement. You don't want to return 0 on no match, because that can be confused for a match at the first byte position, which is also 0. Instead, return -1 if you have to return an integer:

if(result == NULL) return -1;

Going further, however, you can see how this method is just a wrapper for functionality you aren't even using later. If all you care about in main is whether the string was found, just remove this function completely and write main like this:

int main(int argc, char *argv[])
{
   FILE *file;
   char line[BUFSIZ];
   int linenumber = 1;
   char term[20] = "hello world";

   file = fopen(argv[1], "r");
   if(file != NULL) {
      while(fgets(line, sizeof(line), file)){
         if(strstr(line, term) != NULL) {
             printf("Search Term Found at line %d!\n", linenumber);
         }
         ++linenumber;
      }
   }
   else {
      perror(argv[1]);
   }

   fclose(file);
   return 0;
}
Phil