Thread: Program crashes when a loop is meant to begin

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    28

    Program crashes when a loop is meant to begin

    Hello! I have been spending the last 3 days trying to work out why my program crashes after trying to search an array.

    This happens after using the switch to get to 'Manage>Search Track'. It will display 'Search for which song?', but will then crash, with an error: 'Untitled1.exe has stopped responding'. The lines after this is for a loop to search an array, so I am guessing that the loop could be causing the problem.

    Sorry about the amount of code, but I wasn't sure if more than the code above mentioned would be enough.

    I would appreciate any help.


    Code:
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <unistd.h>
    #include <windows.h>//changing font colour
    #include <string.h>
    
    typedef struct
    {
        char track[99];
        char trackname[99]; 
        char artist[99];
        char genre[99];
    }   song; //creates a struct called song;
    
    song songs[99]; 
    
    int main(void)
    
    {
        system("color f5");//gives the window a white background (f) and purple text (5)
        
        int menu, option, playchoice, manage, managechoice, end = 0, counter=0, space; 
        char target, x, asearch;
        
        
        while(end!=1) //loops switch
        {
            
            space = 100 - counter; //space available
            printf("\nSpace available: %i%%\n", space);
            printf("\nMake a selection:\n");
            
            printf("1=Play\n");
            printf("2=Music\n");
            printf("3=Manage\n");
            printf("4=Four\n");
            printf("5=Quit\n");
            scanf("%d", &menu );
            
            switch( menu ) 
            {
                case 1:
                printf("1=Play by song\n");
                printf("2=Shuffle\n");
                scanf("%d", &playchoice);
                switch (playchoice)
                {
                    case 1:
                    printf("Which song?");
                    gets(songs[0].trackname);
                                                   
                    char buffer[100]; //buffers
                    sprintf( buffer, "mplayer %s", songs[0].trackname ); 
                    system( buffer );
                                                   
                                                   
                    break;
                    case 2: printf("Shuffle\n\n");
                }
                break;
                                               
                case 2:
                
                printf("Music list:\n\n");
                
                for(x=0; x<=3; x++)
                
                
                printf( "Track: %s Artist: %s Genre: %s\n", songs[x].trackname, songs[x].artist, songs[x].genre);
                
                break;
                case 3: 
                printf("1=Add track\n");
                printf("2=Search track\n");
                scanf("%d", &managechoice);
                switch (managechoice)
                {
                    case 1:
                        {
                            if(counter <99)
                            {  
                                counter++;
                                            
                                printf("Filepath for track to add: \n\n");
                                gets(songs[counter].trackname);  //references to the first record and its first variable
                                printf("Name of track: \n\n");
                                gets(songs[counter].trackname);
                                printf("Artist: \n\n");
                                gets(songs[counter].artist);
                                printf("Genre: \n\n");
                                gets(songs[counter].genre);
                            }
                            else if(counter == 99)
                            printf("You cannot store over 100 tracks");
                                     
    
                            break;
    
                       }                                
                    case 2: 
                    {           
                          
                        printf("Search for which song??: \n\n");
                        scanf("%c", asearch);  
                        
                        int i;
                        for(i=0;i<99;i++)
    
                        {
                            if(*songs[i].trackname == asearch)
         	                {	
                                 printf("found it");
                                }
        	                }
                        }   
                        
                    }    
                  // }
                   
                break;
                                               
                case 4:
    
    
                break;
            }
        
        }
            return (0);
    }

  2. #2
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Wow where to begin. OK first with this scanf() call you are just getting a single character:
    Code:
                        printf("Search for which song??: \n\n");
                        scanf("%c", asearch);
    Yet here you are comparing it to an array:
    Code:
                            if(*songs[i].trackname == asearch)
         	                {	
                                 printf("found it");
                                }
        	                }
    Which, even if asearch *was* an array would not work because you cannot compare arrays in such a manner (==)...the way you are doing it is just comparing the address of the array trackname with a single character asearch. Hint: in C you need to use strcmp() to compare two character arrays ... but then you need to make asearch a character array and use the proper scanf() call (%s) to read it...

    However once you *do* fix this you are set up for another problem here:
    Code:
                    case 2: 
                    {           
                          
                        printf("Search for which song??: \n\n");
                        scanf("%c", asearch);  
                        
                        int i;
                        for(i=0;i<99;i++)
    
                        {
                            if(*songs[i].trackname == asearch)
         	                {	
                                 printf("found it");
                                }
        	                }
                        }   
                        
                    }
    What do you think will happen if you have < 99 tracks and you try to compare uninitialized strings? What you need is a variable to establish how many actual tracks you have in your list so instead of for(i = 0; i < 99; i++) you would do something like for(i = 0; i < totalTracksEntered; i++).

    Finally you need to watch for fence-post errors, fixing your switch statements so the breaks are within the code blocks for each case and make sure all cases are covered along with a default case for each in case the user enters something not handled by your cases....then fixing the indenting and the remaining errors should be obvious...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  3. #3
    Registered User
    Join Date
    Feb 2010
    Posts
    28
    Thank you, jeffcob!

    You explained this really well. I have heard of a couple of things (such as strcmp()) and have a book for my module which will explain all this. I was not aware that you would need a 'default' for each case though, so thanks for everything, including your time.

    I will begin to sort these problems out now.

  4. #4
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by m88g88 View Post
    Thank you, jeffcob!

    You explained this really well. I have heard of a couple of things (such as strcmp()) and have a book for my module which will explain all this. I was not aware that you would need a 'default' for each case though, so thanks for everything, including your time.

    I will begin to sort these problems out now.
    Note: you only need a single default for each switch() statement, not each case. The idea is this: if the item in the switch() is handled by a case then you are fine but if it is NOT handled, the default will be called and the code-block there will handle the problem. Something like this:
    Code:
    switch(userChoice)
    {
         case 1: 
         {
               printf("User selected 1...\n");
               break;
         }
    // more cases here
         default:
         {
               printf("User entered illegal choice: %d\n", userChoice);
               break;
         }
    
    }
    Like so...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  5. #5
    Registered User
    Join Date
    Feb 2010
    Posts
    28
    I have changed the code for searching an array to:

    Code:
                    {           
                          
                        printf("Search for which song??: \n\n");
                        scanf("%s", asearch);  
                        
                        int i;
                        for(i = 0; i < counter; i++)
    
                        {
                         if( strcmp( songs[i].trackname, asearch ) == 0 )
                       printf( "Found %s\n", asearch);
                                }
        	                }
    
                       
                        }
    But it seems to only find the result if it is in the second record (not sure of the correct term) of the array.

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Did you change asearch into a string, or is it still a char?

    Your parenthesis might be working, but I would prefer this:

    Code:
                        if(( strcmp( songs[i].trackname, asearch )) == 0 )
                       printf( "Found %s\n", asearch);
                                }
        	                }
    And are you removing the newline on the end of any strings that contain them?

    Also, it will make things much clearer to you, (and everyone else), if you indent properly:

    Code:
    for(blah; blah; blah)
    {
       if(whatever)
          printf(your message);
    }
    Your logic errors are much more apparent to your eye, when you indent this way.

  7. #7
    Registered User
    Join Date
    Feb 2010
    Posts
    28
    Thank you for your replies.

    I have have done my best to make these corrections. I have turned the 'asearch' variable into:

    Code:
     
    
    char asearch[15]
    And have used the parenthesis as suggested, but this did not fix the problem, so I assume it is because I am not removing the new line at the end of the string.

    I searched Google on how to do this and all the tutorials I found were for 'fgets()', however, so would this mean that scanf() doesn't include new lines?

  8. #8
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    scanf() is very literal about what it reads. One way to see what is happening is to drop a printf() in the middle of your search loop, something like this:
    Code:
    printf("record name is %s, len(%d), search key was %s, len(%d)\n", songs[i].trackname, strlen(songs[i].trackname), asearch, strlen(asearch));
    This will probably reveal a lot about what is going on here...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Are you using %s for a string with scanf()?

    Anyway, yeah, it does include the newline. You can chop it this way:
    Code:
    char *ptr;
    strchr((const char*)asearch,'\n');
    ptr[0] = '\0';
    The (const char*) cast may be necessary because for some thunderously dunderheaded reason strchr() is supposed to work only const char strings.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    Registered User
    Join Date
    Feb 2010
    Posts
    28
    Thank you, this worked!!!

    Now I know more about strings, and with all the info provided in this thread, I should be able to complete the program easily.

  11. #11
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Quote Originally Posted by MK27 View Post
    Are you using %s for a string with scanf()?

    Anyway, yeah, it does include the newline. You can chop it this way:
    Code:
    char *ptr;
    strchr((const char*)asearch,'\n');
    ptr[0] = '\0';
    The (const char*) cast may be necessary because for some thunderously dunderheaded reason strchr() is supposed to work only const char strings.
    The promotion to "const" is automatic.

  12. #12
    Registered User
    Join Date
    Feb 2010
    Posts
    28
    Code:
    char *ptr;
    strchr((const char*)asearch,'\n');
    ptr[0] = '\0';
    This does work, but how would you code it so that it does not include 'const char*' (as zac7 said it would happen automatically).

    Also, can anyone explain simply how this works please.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by m88g88
    This does work, but how would you code it so that it does not include 'const char*' (as zac7 said it would happen automatically).
    It should be:
    Code:
    char *ptr = strchr(asearch, '\n');
    if (ptr)
    {
        *ptr = '\0';
    }
    Quote Originally Posted by m88g88
    Also, can anyone explain simply how this works please.
    Basically, you find the position of '\n' in the string. If it is found (i.e., ptr is not a null pointer), you use the pointer returned to set that newline character to a null character, thus removing it.

    The previously suggested example is wrong because it does not assign anything to ptr, and then it does not check that ptr is not a null pointer before dereferencing it.

    I suggest that you post your current code. I actually made an erroneous reply because it was difficult to see what you currently had. In fact, even now I find it hard to tell if you have changed those gets() calls into fgets().
    Last edited by laserlight; 02-19-2010 at 07:59 AM. Reason: Since m88g88 went offline...
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    As you might expect, strchr() is returning the address of the char in the string, that is being searched for.

    It's then assigned the value of the end of string char, which effectively shortens that string, and makes it the same format as your other strings.

    String handling in C is done at a relatively low level, since C has no distinct data type for strings, aside from one or more char's which are marked at the end by an end of string char ('\0').

    Just remember,
    this: abcdefg is just a bunch of letters, not a string.
    this: abcdefg\0 is a string, in C

  15. #15
    Registered User
    Join Date
    Feb 2010
    Posts
    28
    Thanks for the extra information!

    And no, I haven't changed all my gets to fgets, but it seems to work okay for now, so I will go back to that later (need to look up how fgets works first).

    I also haven't changed my indents yet (thought I had done them properly lol), so my code will look like a bit of a mess at the moment if you see.

    None the less, I really do appreciate all this help and will be correcting it after I get my main requirements sorted.

    There is another question about this code, however.

    So it searches compares a string and I have changed it so that it has a boolean to show a message if the string has not been found.

    Code:
              char *ptr = strchr(asearch, '\n'); 
                        if (ptr)
                        {
                           *ptr = '\0';//the pointer is given a null character to remove it
                        }
                        
                        int i, t=0;//t is boolean (false)
                        for(i = 0; i <= counter; i++)
    
                        {
                              if(( strcmp( songs[i].trackname, asearch )) == '\0' ) 
                              {printf( "Found %s\n", asearch); 
                              t=1;}
    
                                            }
                        if (t==0)
                        { printf("\nCould not find %s\n", asearch);}
    I have been looking up how to write code that deletes a record and shifts the records in the array to take up the new NULL space. I found information on a delete[] function, or a loop for doing this. Having seen my code, it must already be obvious that I am new to programming and have not been able to get any of these working.

    It would probably get annoying to keep putting code on here, so I would appreciate a recommended tutorial on this, or an example.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Loop issue in tax program
    By mistymoon1966 in forum C Programming
    Replies: 4
    Last Post: 10-31-2009, 02:04 PM
  2. Loop Entire Program?
    By seanminator in forum C Programming
    Replies: 25
    Last Post: 07-22-2009, 01:23 PM
  3. funcion runs 14 times, then program crashes
    By happyclown in forum C Programming
    Replies: 9
    Last Post: 03-03-2009, 11:58 PM
  4. Using While Loop to write a program
    By Cyberman86 in forum C++ Programming
    Replies: 2
    Last Post: 09-16-2008, 12:52 PM
  5. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 12:39 PM