Thread: Problem using strcmp and strlen in a Linked List

  1. #1
    Registered User matrixx333's Avatar
    Join Date
    Mar 2009
    Posts
    67

    Problem using strcmp and strlen in a Linked List

    Hello everyone,

    I have created a program that counts, prints, adds and deletes nodes in a linked list. I am having a problem with the delete function of the program. The struct contains a name value (ex. Paul).

    When I call the fuction del_node, I am using strcmp to see if the value returned is 0, if it is, the function should mark the current pointer as "del_node" and free the space allocated for that node at the end of the function call, relinking the pointers as needed.

    It seems that strcmp in the del_node function isn't comparing my two pointers correctly. Below is the code:

    Code:
    #include <stdio.h>
    #include <string.h>
    #define DEBUG
    
    typedef struct linked_list LIST;
    
    int print_menu(void);
    void print_nodes(LIST *head, int *reval);
    int count_nodes(LIST *head);
    LIST *add_node(LIST *head, int *reval);
    LIST *del_node(LIST *head);
    
    struct linked_list {
    	struct linked_list *next;
    	char name[30];
    };		
    
    enum reval {SUCCESS, FAIL}; 
    
    int main(void)
    {
    	char line[100];
    	int i, count = 0;
    	int option;
    	int reval = SUCCESS;
    
    	LIST *first_node = NULL;
    	LIST *node_2 = NULL;
    	LIST *head = NULL; // Points to first node in the list
    		
    	first_node = malloc(sizeof(LIST));
    	if (first_node == NULL) {
    		printf("Out of memory.\n");
    		return 1;
    	}		
    
    	node_2 = malloc(sizeof(LIST));
    	if (node_2 == NULL) {
    		printf("Out of memory.\n");
    		return 1;
    	}
    
    	strcpy(first_node->name, "Paul");
    	strcpy(node_2->name, "Susan");
    
    	head = first_node;
    	first_node->next = node_2;
    	node_2->next = NULL;
    
    	while (1) {
    		option = print_menu();
    			
    		switch (option) {
    			case 1:
    				count = count_nodes(head);
    				printf("\nNumber of nodes in list: %d\n", count);
    				break;
    			case 2:
    				print_nodes(head, &reval);
    				break;
    			case 3:
    				head = add_node(head, &reval);
    				break;
    			case 4:
    				head = del_node(head);
    				break;
    			default:
    				printf("Incorrect menu option.\n");
    				break;
    		}
    				
    		printf("\nWould you like to continue? (Y)es or (N)o? ");
    		fgets(line, sizeof(line), stdin);
    		printf("\n");
    		
    		if ((line[0] == 'y') || (line[0] == 'Y'))
    			continue;
    		else
    			break;
    	}	
    		
    	if (count != 0) {
    		free(first_node);
    		free(node_2);
    	}
    		
    	return reval;
    } 
    
    // print_menu() definition
    int print_menu(void)
    {
    	char line[100];
    	int option;
    	
    	printf("Linked Lists\n");
    	printf("------------\n");
    	printf("1. Count number of links\n");
    	printf("2. Print names in list\n");
    	printf("3. Add a name to the list\n");
    	printf("4. Delete a name from the list.\n\n");
    	printf("What would you like to do: ");
    		
    	fgets(line, sizeof(line), stdin);
    	sscanf(line, "%d", &option);
    	
    	return option;
    }
    
    // node_count() definition
    void print_nodes(LIST *head, int *reval)
    {
    	LIST *current;
    		
    	if (head == NULL) {
    		printf("\nThere are no names in the list.");
    		*reval = FAIL;
    	}
    		
    	current = head;
    	printf("\n");
    	while (current != NULL) {
    		printf("Name: %s\n", current->name);
    		current = current->next;
    	}
    }
    
    int count_nodes(LIST *head)
    {
    	LIST *current;
    	int count = 0;
    		
    	current = head;
    	while (current != NULL) {
    		count++;
    		current = current->next;
    	}
    		
    		return count;
    }
    
    // add_node() definition
    LIST *add_node(LIST *head, int *reval)
    {
    	LIST *current = NULL, *before = NULL, *after = NULL, *new_node = NULL;
    	char line[100];
    	int count = 0;
    	int value;
    		
    	new_node = malloc(sizeof(LIST));
    	if (new_node == NULL) {
    		printf("Out of memory.\n");
    		*reval = FAIL;
    	}
    		
    	current = head;
    		
    	printf("Enter a name: ");
    	fgets(line, sizeof(line), stdin);
    	sscanf(line, "%s", new_node->name);
    		
    	while (1) {
    		
    		value = strcmp(new_node->name, current->name);
    				
    		if (current == NULL)
    			break;				
    
    		if ((value < 0) && (count == 0)) {
    			new_node->next = current;
    			head = new_node;
    			break;
    		}
    		else if ((value < 0) && (count != 0)) {
    			new_node->next = current;
    			before->next = new_node;
    			break;
    		}
    		else if (value > 0) {
    			if (current->next == NULL) {
    					new_node->next = NULL;
    					current->next = new_node;
    					break;
    			}
    			before = current;
    			current = current->next;
    			count++;						
    		}
    		else if (value == 0)
    			break;
    	}
    		
    	return head;
    }
    
    // del_node() definition
    LIST *del_node(LIST *head)
    {
    	LIST *current = NULL, *del_node = NULL, *before = NULL, *after = NULL;
    	char name[100];
    	int count = 0;
    	int value;
    		
    	current = head;
    		
    	printf("Enter a name to remove from the list: ");
    	fgets(name, sizeof(name), stdin);
    		
    	#ifdef DEBUG
    	int i;
    		
    	printf("\n");	
    	for (i=0; i<strlen(name); i++)
    		printf("name[%d]: %c\n", i, name[i]);			
    
    	printf("string length of name is: %d\n", strlen(name));
    	printf("string length of current->name is: %d\n\n", strlen(current->name));
    		
    	printf("current->name[0] is: %c\n", current->name[0]);
    	printf("current->name[1] is: %c\n", current->name[1]);
    	printf("current->name[2] is: %c\n", current->name[2]);
    	printf("current->name[3] is: %c\n", current->name[3]);
    	printf("current->name[4] is: %c\n", current->name[4]);
    		
    	printf("\nBegin for loop\n");
    	for (i=0; i<strlen(current->name); i++);
    		printf("current->name[%d]: %c\n", i, current->name[i]);
    	#endif
    		
    	value = strcmp(name, current->name);					
    	printf("value is: %d\n", value);
    		
    	while (current != NULL) {		
    				
    		if (value == 0) {
    			if (count == 0) { // check to see if first_node contains the name
    				head = current->next;
    				del_node = current;
    				break;
    			}						
    			del_node = current;
    			after = current->next;						
    			before->next = after;
    			break;
    		}
    		else {
    			count++;
    			before = current;
    			current = current->next;
    		}
    	}
    		
    	if (del_node == NULL)
    		printf("\nName not found.\n");
    		
    	free(del_node);		
    		
    	return head;
    }
    The output of the debug section is:

    Code:
    Enter a name to remove from the list: Paul
    
    name[0]: P
    name[1]: a
    name[2]: u
    name[3]: l
    name[4]:
    
    string length of name is: 5
    string length of current->name is: 4
    
    current->name[0] is: P
    current->name[1] is: a
    current->name[2] is: u
    current->name[3] is: l
    current->name[4] is:
    
    Begin for loop
    current->name[4]:
    value is: 10
    
    Name not found.
    From what I can see, the value returned from strlen(current->name) isn't the same as strlen(name). Does this have to do with the fact that current->name is on the heap and name is in the stack?

    If I print each element from current->name array individually, it prints successfully, but when I try to use the "for" loop, it only prints the last character (current->name[4]). I'm pretty sure this is the reason strcmp is failing....

    Any help would be appreciated. Thank you.

  2. #2
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    First, #include <stdlib.h>.

    fgets() stores the newline that it reads. As such when you type in "Paul" you are giving five characters: 'P', 'a', 'u', 'l', and '\n'. The easiest way to remove the newline is probably to use strchr() to find it, and then replace it with a 0 (not '0').

    As for your loop, observe:
    Code:
    for (i=0; i<strlen(current->name); i++);
    The loop body is empty (just a semicolon, which is called a null statement). Thus the statement you meant to execute inside of the loop only gets called once, at the end.

  3. #3
    Registered User matrixx333's Avatar
    Join Date
    Mar 2009
    Posts
    67
    Ahhhh, thank you cas!

    fgets always gets me tripped up with that newline it puts in there.

    Below is the code I implemented to get it out of there.

    Code:
    printf("Enter a name to remove from the list: ");
    fgets(name, sizeof(name), stdin);		
    name[strlen(name) - 1] = '\0';
    And I see where I made the null typo at the end of the for loop.....I'm always making typo's

    Thanks again!

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by matrixx333
    Below is the code I implemented to get it out of there.
    What happens if the string does not contain a newline? You would then have removed a character that you would like to keep. So, you should check if that character is a newline. Personally, I would use strchr() instead of strlen().
    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

  5. #5
    Registered User matrixx333's Avatar
    Join Date
    Mar 2009
    Posts
    67
    I can see your point laserlight. Thank you for your input.

    As you can see I am still learning, so any advise is appreciated.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Unknown memory leak with linked lists...
    By RaDeuX in forum C Programming
    Replies: 6
    Last Post: 12-07-2008, 04:09 AM
  2. Replies: 3
    Last Post: 12-06-2008, 07:54 PM
  3. For some reason I end up with memory leak...
    By RaDeuX in forum C Programming
    Replies: 10
    Last Post: 11-26-2008, 12:43 AM
  4. Replies: 7
    Last Post: 06-16-2006, 09:23 PM