Thread: Struct Pointer Problems. (Warning: Long Post.)

  1. #1
    Registered User
    Join Date
    Oct 2008
    Posts
    3

    Struct Pointer Problems. (Warning: Long Post.)

    Hello everyone,

    I have a homework problem that I can't seem to over come. I am given the skeleton on this site: http://www.cs.colostate.edu/~cs157/wiki/CS157/HW3 and the requirements, and I have to write a sorting program. I have got most of it down except the insertion sort method when using the sort pattern "year" (See below code.) There seem to be several other errors in the other code too. The first seems to stem from a fault by the instructor in that main has no way of detecting whether an argument is good or bad. (Not that it makes to much of a difference). Second, I commented out a blank "hero" in the hero struct (I am not really supposed to tamper with anything in main). I don't think it serves any purpose, and only seems to hamper the sorting (may be another instructor fault).

    But now on the the big problems. First when I compile the program, and run it 20 times like this
    ./hero stuff name alias
    A quarter of the time the program segfaults. Why, I can't figure out at all.
    If I run it some other ways like ./hero stuff name stuff alias name it won't segfault.


    Second and the most major, is that I can't figure out how to make the insertion sort work.
    Logically it looks good but it puts out bad output and segfaults:
    $ ./hero year
    *** Unsorted:
    Name Alias Year
    Spider-Man Peter Parker 1962
    Wonder Woman Diana Prince 1941
    Captain America Steve Rogers 1941
    Superman Clark Kent 1938
    Buffy the Vampire Slayer Buffy Summers 1992
    Zorro Don Diego de la Vega 1919
    0:1962, 1941

    *** Sorted by "year":
    Name Alias Year
    ..!►aD↑@ ♦☺PI" 1994477072
    Buffy the Vampire Slayer Buffy Summers 1992
    Buffy the Vampire Slayer Buffy Summers 1992
    Buffy the Vampire Slayer Buffy Summers 1992
    Buffy the Vampire Slayer Buffy Summers 1992
    Buffy the Vampire Slayer Buffy Summers 1992
    30 [main] hero 4172 _cygtls::handle_exceptions: Error while dumping state (
    probably corrupted stack)
    Segmentation fault (core dumped)

    Can anyone tell me where I went wrong? Any help is appreciated.
    Code:
    #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
    	//Needs a define for the number of heros in the struct below.
        #define MAX_NAME_SIZE 26
    
        struct hero
        {
           char name[MAX_NAME_SIZE];
           char alias[MAX_NAME_SIZE];
           int year;
        };
    
    
        void printRecords(struct hero *club);
        void sortRecords(char *key, struct hero *club);
    
    
        int main(int argc, char *argv[])
        {
            struct hero heroes[] = {
                // name                       alias                    year
                {"Spider-Man",                "Peter Parker",          1962},
                {"Wonder Woman",              "Diana Prince",          1941},
                {"Captain America",           "Steve Rogers",          1941},
                {"Superman",                  "Clark Kent",            1938},
                {"Buffy the Vampire Slayer",  "Buffy Summers",         1992},
                {"Zorro",                     "Don Diego de la Vega",  1919},
                //{"",                          "",                      0000} //Is this necessary?
            };
    
            if (argc == 1) {
                printf("Usage: %s sort-key ...\n", argv[0]);
                return 1;
            }
    
            printf("*** Unsorted:\n");
            printRecords(heroes);
    
            for (int i=1; i<argc; i++) { //Problematic. Runs even if there is an error in the argument
                char *key = argv[i];
                sortRecords(key, heroes);
                printf("\n*** Sorted by \"%s\":\n", key); //This needs a check to see if the argument was good or bad.
                printRecords(heroes);
            }
    
            return 0;
        }
    
    
        // Print the records, with a nice header.
    
        void printRecords(struct hero *club)
        {
            //Prints the list.
        	printf("Name                       Alias                      Year\n");
            for(int i=0; i<6; i++){
        		printf("%-26s %-26s %-4d\n", club->name, club->alias, club->year);
        		club = club + 1;
        	}
        }
    
        // Sort the array of records,
        // according to the parameter key.
        //
        // That is, if key is "name", then sort the records
        // by the name of the hero: Batman first, Zorro last.
        //
        // If key is "alias", then sort by the alter ego:
        // Buffy Summers is first, Steve Rogers is last.
        //
        // If key is "year", then sort in DESCENDING ORDER by year.
        //
        // Anything else, print an error message.
        //
        // You must use each type of sorting that we discussed in class.
        // Three sort keys, three different types of sorting.
    
        void sortRecords(char *key, struct hero *club)
        {
            struct hero *temphero, *temphero2, temphero3;
    	    //Note: Switch method does not appear to work since GCC says switchs only work with "case labels that reduce to integer constants."
    	    
    	    if( strcmp(key, "name") == 0 ){ //Bubble sort for hero names.
    		    //Bubble sort.
    		    int chgcnt = 1; /*A variable for the do while loops to see if any changes have occured when the sort was run. Initialized to 1 for safety.*/
    			do{
    				chgcnt = 0;
    				temphero = club; //Sets the memory address of the club struct to a new temporary hero struct
    				for( int i=0; i<6; i++){ //Runs for each hero in the hero struct array.
    					temphero2 = temphero + 1; //Sets a new pointer to one address ahead of the current one for swapping
    					if(strcmp(temphero->name, temphero2->name) > 0){
    							temphero3 = *temphero; //Rearranging values
    							*temphero = *temphero2;
    							*temphero2 = temphero3; 
    							chgcnt = 1;
    					}
    					temphero++;	
    				}
    			}while(chgcnt != 0);
    		}
        	else if( strcmp(key, "alias") == 0){ //Selection Sort for Hero Alias.
    	    	//Selection Sort.
    	    	int i, j, k = 6; //Ints for for and while loops.
    	    	char tempalias[MAX_NAME_SIZE];
    	    	struct hero *tempclub, *tempclub2, *tempclub3, temphero;
    	    	tempclub = club; //Assigns the same address to temp club as to club.
    	    	for( i=0; i<6; i++){ //Runs five times for each sorting hero moved
    		    	tempclub2 = tempclub; //(tempclub2) Pointer for the first hero that is yet unsorted
    		    	tempclub3 = tempclub; //Sets the temporary value for the lowest unsorted alias to the first hero in the unsorted list.
    		    	strcpy(tempalias, tempclub2->alias); //Defaults the first alias to the one with the lowest ascii value.
    		    	for( j = 0; j < k; j++){ //Runs for the number of unsorted 
    		    		tempclub2++;
    		    		if( strcmp( tempalias, tempclub2->alias) > 0){ //If the current hero has a lower ascii value in the alias (e.g. the name comes before the on in memory),
    		    													   //make that new value the next value to be put at the end of the sorted list.
    			    		strcpy( tempalias, tempclub2->alias); //Sets the new alias to compare all remaining aliases to
    		    			tempclub3 = tempclub2; //Sets the location of the new found lowest alias for the later data swap.
    			    	}	
    	    		}
    		    	temphero = *tempclub; // Data from lowest alias dumped to new first and old first moved to position that is now freed up.
    	    		*tempclub = *tempclub3;
    		    	*tempclub3 = temphero;
    	    		tempclub++;
    		    	k--; //Reduces the number of unsorted heros.
    		    }
     		}	
        	else if( strcmp(key, "year") == 0){
    	    	//Insertion sort.
    	    	int i, j, k, l, m, n; //Tons of ints to run below for and while loops.	
    			struct hero *tempclub, *tempclub2, *tempclub3, temphero, temphero2;
    			tempclub = club + 1; //Sets the value of the first hero to be sorted to be the second hero in the list (first is by default already inserted).
    			printf("0:%d, %d\n", club->year, tempclub->year); //Debugging.
    			for( i=0; i<6; i++){ //Runs for the number of times the sort will run.
    		    	tempclub2 = club; //Defaults the beginning of the sorted list to the beginning of the array.
    		    	j = 0; //Initializes the constant for the below while loop.
    		    	while(j <= i){ //Runs for the number of already sorted numbers.
    			    	m = i + 1 - j; //m is a value for the remaining number of heros that have not been compared in the if loop below, that are in the sorted list at the beginning.
    			    	if(tempclub-> year > tempclub2->year){ //If the currently selected number is greater than the current position in the sorted list, place it there.
    			    		tempclub3 = tempclub2; //Current position in the sorted list. Used to shift heros one over.
    				    	temphero = *tempclub;
    			    		n = 0;
    				    	for( l = 0; l < m; l++){ //Shifts all sorted heros after the current hero being placed, over one position.
    			    			tempclub3[n+1] = tempclub3[n];
    			    			n++; //The position in the tempclub3 list.
    		    			}
    			    		*tempclub2 = temphero;	
    				    	break; //Breaks out of the parent while loop since the values already been sorted.
    				    }
    			    	tempclub2++; //Moves to the next sorted hero in the list.
    		    		j++; //Increments the counter on the sorted hero list.
    	    		}
    		    	if( i < 5 ){	
    		    		tempclub++;	//Moves the hero to be sorted over by one since the previous while loop has been completed. Does not need to be run on the fifth time?
    	    			
    		    	}
        		}
    	    }
    		else{
    			printf("\nBad. Unsorted. %s is not a recognized sort method.\n", key);
    			printf("Usage: Hero [name alias year]\n");
    			//Bad argument.
    		}
    	}
    Best Regards,
    Robert

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    The point of the blank hero is so that you know when to stop. I.e., any appearance of "6" in your code is a coincidence and should probably be removed.

    As for the insertion sort, this bit:
    Code:
    for( l = 0; l < m; l++){ //Shifts all sorted heros after the current hero being placed, over one position.
    			    			tempclub3[n+1] = tempclub3[n];
    			    			n++; //The position in the tempclub3 list.
    		    			}
    has a comment that bears no resemblance to the code in any way. Since the comment does match what you want to do there, you should probably change this code and instead actually shift all sorted heros after the one being placed.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. memory issue
    By t014y in forum C Programming
    Replies: 2
    Last Post: 02-21-2009, 12:37 AM
  2. Problems passing a file pointer to functions
    By smitchell in forum C Programming
    Replies: 4
    Last Post: 09-30-2008, 02:29 PM
  3. Direct3D problem
    By cboard_member in forum Game Programming
    Replies: 10
    Last Post: 04-09-2006, 03:36 AM
  4. Passing pointers between functions
    By heygirls_uk in forum C Programming
    Replies: 5
    Last Post: 01-09-2004, 06:58 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM