Thread: Searching and matching strings: segmentation fault

  1. #1
    Registered User
    Join Date
    Jul 2005
    Posts
    7

    Searching and matching strings: segmentation fault (EDIT: code posted!)

    I am programming a simulation of a library catalogue and am using a switch statement for selections of types of data to be searched. searching year, edition, and price are all working just fine. however, searching book name, author, and publisher receive segmentation faults after they have been found. I suspect its somewhere in my while loop but I have yet to find it.

    i should mention that i am reading the data from a separate text file. when searching the first entry in the text file, that is, its book name, i receive a segmentation fault immediately. however the other books show up, but then get a segfault error.

    When searching another aspect of the first file, such as edition, the info comes up, but its missing the book name at the beginning. its very confusing and difficult to explain, but i have attached both files to this post. if there is a genius out there who can give me some insight within the next couple of hours, i would be greatly in your debt!


    EDIT: I have decided that for ease to you programmers out there, that I will post all the code and the file. There isn't really that much I suppose...


    Code:
    #include <stdio.h>
    
    struct record{
    	
    		char book_name[50];
    		char author[50];
    		char publisher[50];
    		int year;
    		int edition;
    		float price;
    };
    /*
    void add_record(char b_name,char author, char publisher, int year, int
    edition, float price)
    {
    */
    main(){
    	FILE *fp;
    	struct record r[100];
    	fp=fopen("file1.txt","r");
    	char category;      
            int counter=0;
            char book_search,author_search,publisher_search;
    	int i=0;
    	int year_search,edition_search;
    	float price_search;
    /*	
    	while(counter<2){
    	printf("Enter the name,author,publisher,year: ");
      */      
    
        while(    	
    
    	fscanf (fp,"%s%s%s%d%d%f",
    		r[counter].book_name,
    		r[counter].author,
    		r[counter].publisher, 
    		&(r[counter].year),
    		&(r[counter].edition),
    		&(r[counter].price))==6
    	 )
    		
    		{
    			counter++; 	
    		}
    /*
      	printf(" the first record is %s\t%s\t%s\t%d\t%d\t%f\n"
              ,r[0].book_name,r[0].author,r[0].publisher,
              r[0].year, r[0].edition, r[0].price);
     
      	printf(" the fourth author is %s\n" , r[3].author);
    	printf(" The number of records is %d \n" , counter);
     */ 
    
    
    	printf("Type b,a,u,y,e,or p to search for book,author,publisher,year, edition, or price:  " );
            scanf("%s", &category);
            
    	switch(category){
    	case 'b':
    		 
    		printf("Type the name of the book: ");
       	        scanf("%s", &book_search);	
    		while(i<counter){
    			
    			if(strcmp( r[i].book_name,&book_search)==0){
    							
    				printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
      				,r[i].book_name,r[i].author,r[i].publisher,
      				r[i].year, r[i].edition, r[i].price);
    			}
    			i++;
    				}
    			i=0;
    			break;
    	
    	case 'a':
    	
    	printf("Type the author of the book: ");
    	scanf("%s", &author_search);
    
      		while(i<counter){
    
              if(strcmp(&author_search, r[i].author)==0){
    
                      printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
                      ,r[i].book_name,r[i].author,r[i].publisher,
                      r[i].year, r[i].edition, r[i].price);
              }
              i++;
                      }
              i=0;
    	break;
    	
    	case 'u':
    	printf("Type the publisher of the book: ");
    	scanf("%s", &publisher_search);
    
             while(i<counter){
    
       	  if(strcmp(&publisher_search, r[i].publisher)==0){
    
               printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
               ,r[i].book_name,r[i].author,r[i].publisher,
               r[i].year, r[i].edition, r[i].price);
          	}
       	i++;
             	 }
       	i=0;	
    	break;
    
    	case 'y':
    	printf("Type the year of the book: ");
    	scanf("%d", &year_search);
    
      	while(i<counter){
    
       	if(year_search==r[i].year){
    
        		printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
        		,r[i].book_name,r[i].author,r[i].publisher,
        		r[i].year, r[i].edition, r[i].price);
     			}
     		i++;
              	}
     		i=0;
    	break;
    
    	case 'e':
    	printf("Type the edition of the book: ");
    	 scanf("%d", &edition_search);
    
     	while(i<counter){
    
     	if(edition_search==r[i].edition){
    
             printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
             ,r[i].book_name,r[i].author,r[i].publisher,
             r[i].year, r[i].edition, r[i].price);
                     }
             i++;
             }
             i=0;
     	break;
    
    
    	case 'p':
    	printf("Type the price of the book: ");
    	 
      	scanf("%f", &price_search);
    
     	while(i<counter){
    
    	 if(price_search==r[i].price){
    
     	 printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
      	 ,r[i].book_name,r[i].author,r[i].publisher,
     	 r[i].year, r[i].edition, r[i].price);
              }
      i++;
      }
      i=0;
    
    	break;	
    }	
    
    
    fclose(fp);
    	
    
            
    		
    
    }

    and here is what is contained in the text file:

    Code:
    River James pub1 1980 4.50
    Lake John pub2 1981 6.50
    Ocean Luke pub3 1982 7.65
    Pond Peter pub4 1983 8.91
    Water Jesus pub5 1985 4.75
    Last edited by Smola; 07-06-2005 at 06:33 PM.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Code:
    char book_search,author_search,publisher_search;
    Code:
    if(strcmp(&publisher_search, r[i].publisher)==0){
    A pointer to a character is not a string.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jul 2005
    Posts
    7
    So should i just remove all the ampersands? why does it work with the other records? did you try compiling it yourself as well?


    EDIT: and why is it not reading only the FIRST record book name?

    I deleted the ampersand on that small piece of code you posted and i now get this compiler error:

    "passing arg 2 of 'strcmp' makes pointer from integer without a cast"

    ??
    Last edited by Smola; 07-06-2005 at 07:15 PM.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    A single character is not a string. I don't need to compile it myself to know it's wrong. That's the benifit of knowing what you're talking about I suppose. At any rate, a single character is not a string. I suggest you go back to your C book of choice, and read the chapter on strings over again.


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Jul 2005
    Posts
    7
    Yes I read a bit on the subject. A string is simply a character array. The variables you referred to "author_search" and "publisher_search" have now been declared as

    Code:
    char author_search[50];
    char publisher_search[50];
    along with book_search.

    However now when I read the items into memory using

    Code:
    printf("Choose the category blah blah: ");
    scanf("%s", &category);
    I get problems in my switch statement when using the strcmp function. I get these errors on 2 similar cases:

    warning: passing arg 1 of 'strcmp' from incompatible pointer type


    Now, I've tried to read up on pointers, but its hard because I can't ask questions or present examples to a tutorial. I have a feeling all my problems lie within pointers and variable declarations...but I just can't quite put my finger on it.


    EDIT: Apparently I can run the app even with the warnings, and it works! No segmentation errors. However that one problem still remains: the very first word in the text file (River) is getting erased from r[0].book_name right before the program asks for a category. It will print out right before the prompt, but right after I enter a category selection, it disappears. Every other value is preserved. What in the heck could be causing that?!
    Last edited by Smola; 07-06-2005 at 10:41 PM.

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Yes I read a bit on the subject. A string is simply a character array. The variables you referred to "author_search" and "publisher_search" have now been declared as
    Close, but no cigar. A string is an array of characters terminated by a null character. You can have arrays of characters that are not strings.

    I get problems in my switch statement when using the strcmp function. I get these errors on 2 similar cases:

    warning: passing arg 1 of 'strcmp' from incompatible pointer type
    How about posting your latest code? I can't seem to find my crystal ball.

    Apparently I can run the app even with the warnings, and it works! No segmentation errors. However that one problem still remains:
    Working and just "not crashing" are two entirely different things.


    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    Jul 2005
    Posts
    7
    Here it is:

    Code:
    #include <stdio.h>
    
    struct record{
    
                    char book_name[50];
                    char author[50];
                    char publisher[50];
                    int year;
                    int edition;
                    float price;
    };
    /*
    void add_record(char b_name,char author, char publisher, int year, int
    edition, float price)
    {
    */
    main(){
            FILE *fp;
            struct record r[100];
            fp=fopen("file1.txt","r");
            char category;
            char book_search[50];
            char author_search[50];
            char publisher_search[50];
            int i = 0;
            int counter = 0;
            int year_search;
            int edition_search;
            float price_search;
    
    
        while(
    
            fscanf (fp,"%s%s%s%d%d%f",
                    r[counter].book_name,
                    r[counter].author,
                    r[counter].publisher,
                    &r[counter].year,
                    &r[counter].edition,
                    &r[counter].price)==6 )
                    {
                            counter++;
                    }
    
            printf("counter = %d\n", counter);
    
            printf(" the first record is %s\t%s\t%s\t%d\t%d\t%f\n"
              ,r[0].book_name,r[0].author,r[0].publisher,
              r[0].year, r[0].edition, r[0].price);
    
    /*      printf(" the fourth author is %s\n" , r[3].author);
            printf(" The number of records is %d \n" , counter);
     */
    
    
    
            printf("Type b,a,u,y,e,or p to search for book,author,publisher,year, e$
            scanf("%s", &category);
    
            printf("%s", r[0].book_name);
            switch(category){
    case 'b':
    
            printf("counter = %d\n", counter);
            printf("%s", r[0].book_name);
            printf("Type the name of the book: ");
            scanf("%s", &book_search);
            while(i < counter){
                    printf("i = %d counter = %d\n", i,counter);
                    if(strcmp(r[i].book_name,book_search)==0){
    
                            printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
                            ,r[i].book_name,r[i].author,r[i].publisher,
                            r[i].year, r[i].edition, r[i].price);
                    }
                    i++;
                    if(i>counter){
                            break;
                    }
                            }
                    i=0;
    break;
    
    case 'a':
    
    printf("Type the author of the book: ");
    scanf("%s", &author_search);
    
            while(i<counter){
    
      if(strcmp(&author_search, r[i].author)==0){
    
              printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
              ,r[i].book_name,r[i].author,r[i].publisher,
              r[i].year, r[i].edition, r[i].price);
      }
      i++;
          }
    
       i=0;
     break;
    
     case 'u':
     printf("Type the publisher of the book: ");
     scanf("%s", &publisher_search);
    
      while(i<counter){
    
       if(strcmp(&publisher_search, r[i].publisher)==0){
    
        printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
        ,r[i].book_name,r[i].author,r[i].publisher,
        r[i].year, r[i].edition, r[i].price);
     }
     i++;
              }
     i=0;
     break;
    
     case 'y':
     printf("Type the year of the book: ");
     scanf("%d", &year_search);
    
     while(i<counter){
    
     if(year_search==r[i].year){
    
             printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
             ,r[i].book_name,r[i].author,r[i].publisher,
             r[i].year, r[i].edition, r[i].price);
                     }
             i++;
             }
             i=0;
     break;
    
     case 'e':
     printf("Type the edition of the book: ");
      scanf("%d", &edition_search);
    
     while(i<counter){
    
     if(edition_search==r[i].edition){
    
      printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
      ,r[i].book_name,r[i].author,r[i].publisher,
      r[i].year, r[i].edition, r[i].price);
              }
      i++;
      }
      i=0;
     break;
    
    
     case 'p':
     printf("Type the price of the book: ");
    
     scanf("%f", &price_search);
    
            while(i<counter){
    
             if(price_search==r[i].price){
    
             printf(" %s\t%s\t%s\t%d\t%d\t%f\n"
             ,r[i].book_name,r[i].author,r[i].publisher,
             r[i].year, r[i].edition, r[i].price);
              }
      i++;
      }
      i=0;
    
            break;
    }
    
    
    fclose(fp);
    
    
    
    
    
    }

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Ok, now how about some code that actually compiles?

    Also, you still aren't paying attention to my first post:
    Code:
     char category;
    Code:
    scanf("%s", &category);

    Quzah.
    Last edited by quzah; 07-07-2005 at 12:51 AM.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Jul 2005
    Posts
    7
    1st: the code compiles just fine for me. i am using telnet with a compiler on the other end. no problems happen for me. it may be the line that goes off the screen. it is shown in the code box as ending in "$" when it should be more code and a closing parenthesis and semicolon.

    2nd: if i get rid of the ampersand on &category like you suggest, i get a segmentation fault after i enter a letter for category. why would it work fine with the ampersand there, but segfault when its taken away?

    3rd: I had to copy and paste in sections the code. That might also be a reason you couldnt get it to compile. I do not know the telnet command to copy the remote file to my local system. It is using the SunOS 5.8 if that's any help.

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    1) What you've posted won't compile. Here's specificly what I'm talking about:
    Code:
        while(
    
            fscanf (fp,"%s%s%s%d%d%f",
                    r[counter].book_name,
                    r[counter].author,
                    r[counter].publisher,
                    &r[counter].year,
                    &r[counter].edition,
                    &r[counter].price)==6 )
                    {
                            counter++;
                    }
    Your while is not complete. As such, it won't compile. That aside...

    2) I didn't suggest you not use the ampersand. I suggested you actually pay attention to what you're declaring and use it correctly:
    a) If you want a string or an array, declare it as such.
    b) If you want a single character, then stop using %s in your scanf call.

    Quzah.
    Hope is the first step on the road to disappointment.

  11. #11
    I typecast anyway.
    Join Date
    Jun 2005
    Posts
    25
    Correct me if I'm wrong, but isn't scanf a dangerous way to read in a string? Wouldn't it have the same issue as gets? I'm not seeing a length arguement (I guess you could try something like %50.50s in the formatting part... not sure if that fixes it though).

    Obviously that's not the biggest problem here, but something to consider anyway.

  12. #12
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Sure there are better ways to read input. However, since they can't decide if they're using single characters or strings, I suspect they'd still be having the same problems with something like fgets.


    Quzah.
    Hope is the first step on the road to disappointment.

  13. #13
    Registered User
    Join Date
    Jul 2005
    Posts
    7
    i dont see what isnt complete about it. perhaps your compiler is old or too new or something. like i said, it is compiling fine for me. i dont know what the problem is for you.

    how do i declare a string? it is my understanding there is only a character array declaration. if you know of a string declaration i would greatly appreciate the insight.

    my scanf for my category selection is not a problem. you have been addressing only syntax and not what the problem is. i suppose its because you cant get it to compile, but i would at least think you would have a suggestion.

    and finally, there's no need to be indirectly condescending to me through conversation with other members. remember, there are people out there who do not have the vast knowledge of the almighty "Quzah." Your replies seem only to identify problems, and give no solutions. It is because I have no solutions that I am here in the first place.


    Smola.

  14. #14
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Smola
    i dont see what isnt complete about it. perhaps your compiler is old or too new or something. like i said, it is compiling fine for me. i dont know what the problem is for you.
    Ah, I misread that block. At any rate, it still doesn't compile as you posted it due to what you say is a "$" that should be ");", so I was not incorrect when I stated that what you have posted doesn't compile.

    However, even if we fix that, you're still not paying attention to your compiler:
    Code:
    howabout.c:17: warning: return type defaults to `int'
    howabout.c: In function `main':
    howabout.c:21: warning: ISO C90 forbids mixed declarations and code
    howabout.c:67: warning: char format, different type arg (arg 2)
    howabout.c:70: warning: implicit declaration of function `strcmp'
    howabout.c:87: warning: char format, different type arg (arg 2)
    howabout.c:91: warning: passing arg 1 of `strcmp' from incompatible pointer type
    howabout.c:105: warning: char format, different type arg (arg 2)
    howabout.c:109: warning: passing arg 1 of `strcmp' from incompatible pointer type
    howabout.c:182: warning: control reaches end of non-void function
    Quote Originally Posted by Smola
    how do i declare a string? it is my understanding there is only a character array declaration. if you know of a string declaration i would greatly appreciate the insight.
    Like I said, read your chapter on strings over again. Also, actually pay attention to your code. You didn't declare a string. That's the whole problem.
    Code:
     char category;
    Do you see an array there? I sure don't. You can't blame this one on bad pasting either.

    Quote Originally Posted by Smola
    my scanf for my category selection is not a problem. you have been addressing only syntax and not what the problem is. i suppose its because you cant get it to compile, but i would at least think you would have a suggestion.
    Yes it is wrong. Look, I know more than you here. Don't get all huffy because it's a fact. This wrong, and no matter how you want to pretend it's not, it still is:
    Code:
    scanf("%s", &category);
    One more time, because you're still not paying attention:

    You do not use %s for single characters.

    Now, combine that with the above line, which most definately is a single character:
    Code:
     char category;
    This is not a string. It never will be a string. Passing its address to be used in the scanf call to try and pretend it is a string won't make it right. If you want a single character, call the correct format specificer. Otherwise, declare category to be more than just one character.

    Quote Originally Posted by Smola
    and finally, there's no need to be indirectly condescending to me through conversation with other members. remember, there are people out there who do not have the vast knowledge of the almighty "Quzah." Your replies seem only to identify problems, and give no solutions. It is because I have no solutions that I am here in the first place.


    Smola.
    Would you rather I be directly condescending? I can do that if you'd prefer. Of course my replies identify the problem. I also told you how to find the answer, if you actually pay attention. Hell, I even quoted the lines of code so you could easily find the problem. Did it help? No. Because people today don't want help. They want everything done for them. You don't want to learn from your mistakes. You want some one else to fix them for you so you don't have to think about anything.

    Sorry pal, I don't work that way.


    Quzah.
    Hope is the first step on the road to disappointment.

  15. #15
    Registered User
    Join Date
    Jun 2004
    Posts
    201
    Quote Originally Posted by Smola
    how do i declare a string? it is my understanding there is only a character array declaration. if you know of a string declaration i would greatly appreciate the insight.

    my scanf for my category selection is not a problem. you have been addressing only syntax and not what the problem is. i suppose its because you cant get it to compile, but i would at least think you would have a suggestion.
    You're just having trouble with pointers at this point which is what most people have in the beginning

    there's 2 separate things:

    If you want to read a string with scanf you need %s as format specifier. If you want to read 1 char you need the %c specifier.

    The parameter that scanf expects when it sees %s is a "char *" that has enough space allocated to hold a string. Your category variable can only hold 1 char which can never be a string because the '\0' alone is already 1 char.
    When scanf sees %c it will expect a char * too but only read 1 char into it.

    Beware though that if you change category into an array of chars that the current scanf("%s", &category) is not correct anymore. (it will compile though!) You need to know that arrays decay into pointers when passed as parameter.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM