#1
  1. The bad and the ugly...
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2007
    Location
    Oz... No??? Neverland then?
    Posts
    142
    Rep Power
    0

    Linked list woes (read from file to linked list)


    well i finished the last homework assignment my teacher assigned thanks to everyones help. I received the warm and fuzzy grade of A+!

    So for our next assignment he has us messing around with a "phonebook" of sorts using linked lists.

    our input file: "data.txt"
    Code:
    Smith		Joe		8046688446
    Thomas		Fred		1234567890
    Gates		Bill		1023456789
    Hilton 		Paris		5789146512
    im trying to read this in to create a linked list. each node will have first, last and number.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_LENGTH	20
    #define MAXCHAR	256
    
    struct member_node{
    	char first[MAX_LENGTH];
    	char last[MAX_LENGTH];
    	long int number;
    	struct member_node *next;
    };
    
    
    void main(void)
    {
    	//declaration variables
    	//
    	FILE *filename; 	//input filename handle
    	char *fname = NULL;
    	int n = 0; //used for prompting user for file name
    	char *first_name;
    	char *last_name;
    	long int phone_number;
    	
    	struct member_node *head;// Create entry point to the linked list
    	struct member_node *current;// Create pointer for keeping track of the node 
    //currently being read, written, deleted, added, ....
    	// Add the first elemet to the list
               head = (struct member_node *)malloc(sizeof(struct member_node));
    	
    	//allocate memory for size of filename (char = 1 bit)
    	fname = (char *)malloc(MAXCHAR * sizeof(char));
    	first_name = (char *)malloc(MAXCHAR * sizeof(char));
    	last_name = (char *)malloc(MAXCHAR * sizeof(char));
    	
    	//
    	//prompt user for file name and continue to do so until a valid file name is given
    	while (n != 1)
    		{
    			printf("Enter file name: ");
    			scanf("%s", fname);
    			
    			//filename is just the handle to that file. have to go through 
                                     //filename for IO operation
    			filename = fopen(fname, "r"); 
    			
    			if (filename == NULL)
    				{
    					printf("Please enter a valid file name.\n");
    				}
    			else	
    				{
    					printf("File was successfully opened.\n");
    					n = 1;
    				}
    		}
    	
    	printf("before while loop\n");
    	while (fscanf(filename, "%s\t\t%s\t\t%ld\n", &first_name, &last_name, &phone_number) != EOF)
    		{
    			printf("iteration\n");
    			strcpy(head -> first, first_name);
    			printf("1\n");
    			strcpy(head -> last, last_name);
    			printf("2\n");
    			head -> number = phone_number;
    			printf("3\n");
    			head -> next = NULL;
    			printf("add to list\n");
    			// Add next element
    			current = head;
    			current -> next = (struct member_node *)malloc(sizeof(struct member_node));
    			current = current -> next;
    			printf("end while\n");
    			
    		}
    	printf("after while loop\n");	
    	
    	// Print the list
    	printf("Member name\tage\n");
    	printf("---------------------\n");
    	
    	// Start at the beginning of the list
    	current = head; 
    	printf("asdf");
    	while(current != NULL)
    		{
    			printf("%s\t\t%s\t\t%ld\n", current -> first, current -> last, current -> number);
    			current = current -> next;
    		}
    }	/* end main */


    Phew... okay. So I'm using the printf's for debugging help since I'm coding in Notepad++. The code compiles fine but crashes when it gets to
    Code:
    strcpy(head -> first, first_name);
    Dereferencing it does nothing either... should i scrap this approach all together and attack it from a different angle? I'm trying to read through the file and instead of just using the buffer in fscanf to find the length (for creating the correct number of nodes) I want to create nodes and fill them as fscanf works its way through the file.

    thanks in advance
    ~Tim
    "Life is not a journey with the intent on arriving at the finish line in a pretty and well preserved body. But rather to skid in broadside, totally worn out, thoroughly used up and loudly proclaiming, "Wow! What a ride!" -Anonymous
    Halo! || Diablo 2 LOD Modding || OLGA's BACK!
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2012
    Posts
    156
    Rep Power
    34
    first_name is a pointer to char;
    fscanf("%s") wants a pointer to char;
    Code:
    while (fscanf(filename, "%s\t\t%s\t\t%ld\n", &first_name, ...
    you're passing a pointer to pointer.
    The result is that first_name itself no longer points to where it should (and crashes on the next statement)

    (The same for last_name)

    Also, you need to include <string.h> (for strcpy())
  4. #3
  5. The bad and the ugly...
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2007
    Location
    Oz... No??? Neverland then?
    Posts
    142
    Rep Power
    0
    ah gotcha. well, i scrapped that last plan and started working backwards from one of my teacher's examples.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAX_LENGTH	20
    #define MAXCHAR	256
    
    int main(void)
    {
    	//declaration variables
    	//
    	FILE *filename; 	//input filename handle
    	char *fname = NULL;
    	int n = 0;			//used for prompting user for file name
    	int c = 0;
    	char *first_name;
    	char *last_name;
    	char phone_number[10];
    	
    	struct phonebook *head;// Create entry point to the linked list
    	struct phonebook *current;// Create pointer for keeping track of the node currently being read, written, deleted, added, ....
    	
    	//allocate memory for size of filename (char = 1 bit)
    	fname = (char *)malloc(MAXCHAR * sizeof(char));
    	
    	//
    	//prompt user for file name and continue to do so until a valid file name is given
    	while (n != 1)
    		{
    			printf("Enter file name: ");
    			scanf("%s", fname);
    			
    			//filename is just the handle to that file. have to go through filename for IO operation
    			filename = fopen(fname, "r"); 
    			
    			if (filename == NULL)
    				{
    					printf("Please enter a valid file name.\n");
    				}
    			else	
    				{
    					printf("File was successfully opened.\n");
    					n = 1;
    				}
    		}
    	
    	while(fscanf(filename, "%s %s %s\n", last_name, first_name, phone_number) != EOF)
    		{
    			head = add_to_head(head, last_name, first_name, phone_number);
    			//printf("%s \t %s \t %s", lbuffer, fbuffer, phone);
    			//printf("\n");
    		}
    		
    	printf("Last\t\tFirst\t\tNumber\n");
    	printf("---------------------\n");
    	for(current = head; current != NULL; current = current->next)
    		printf("%s\t\t%s\t\t%s\n", current->last_name, current->first_name, current->phone_number);
    	
    }	/* end main */
    also including these functions
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAX_LENGTH 20
    
    struct phonebook
    	{
    		char fname[MAX_LENGTH];
    		char lname[MAX_LENGTH];
    		char phone[10];
    		struct phonebook *next;
    	};
    
    struct phonebook *add_to_head(struct phonebook *list, char *lname, char *fname, char *phone) 
    {
    	struct phonebook *current;
    
    	if(list == NULL) 
    	{
    		list = (struct phonebook *)malloc(sizeof(struct phonebook));
    		strcpy(list->lname, lname);
    		strcpy(list->fname, fname);
    		strcpy(list->phone, phone);
    		list->next = NULL;
    		return(list);
    	}
    	else 
    	{
    		current = (struct phonebook *)malloc(sizeof(struct phonebook));
    		strcpy(current->lname, lname);
    		strcpy(current->fname, fname);
    		strcpy(current->phone, phone);
    		current->next = list;
    		return(current);
    	}
    }	// end add_to_head

    im getting several compiler errors and 1 warning.
    warning: '=' 'phonebook *' differs in levels of indirection from int on this line:
    Code:
    head = add_to_head(head, last_name, first_name, phone_number);
    and
    Code:
    for(current = head; current != NULL; current = current->next)
    		printf("%s\t\t%s\t\t%s\n", current->last_name, current->first_name, current->phone_number);
    the compiler hates this line too haha. current specifies undefined struct or union 'phonebook?"
    "Life is not a journey with the intent on arriving at the finish line in a pretty and well preserved body. But rather to skid in broadside, totally worn out, thoroughly used up and loudly proclaiming, "Wow! What a ride!" -Anonymous
    Halo! || Diablo 2 LOD Modding || OLGA's BACK!
  6. #4
  7. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,997
    Rep Power
    481
    I stuck all your code into a single file. You'll need to decide between

    lname

    and

    last_name

    and resolve those issues.
    I'll resolve them in my copy and maybe post again.
    [code]Code tags[/code] are essential for python code and Makefiles!
  8. #5
  9. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,997
    Rep Power
    481
    Your compiler messages don't work for me. Oh well.

    Some difficulties:

    Failure to initialize head = NULL in main.

    Failure to test memory allocation success.

    Failure to explicitly return a value from main.

    Potential buffer overrun in [f]scanf("%s",...) because a first name could be three hundred thousand characters long---you could fight this by preprocessing the input file I suppose.

    [I think]Your fscanf should test that it returns 3, not EOF. Testing for EOF won't properly trap a partially complete last line of the phone book file.[/I think]


    add_to_head is too complicated.
    Suppose list were NULL...I think you'll see that you can discard
    Code:
    	if(list == NULL) 
    	{
    		list = (struct phonebook *)malloc(sizeof(struct phonebook));
    		strcpy(list->lname, lname);
    		strcpy(list->fname, fname);
    		strcpy(list->phone, phone);
    		list->next = NULL;
    		return(list);
    	}
    	else

    I made a working version of your program with these changes and maybe some others.
    Last edited by b49P23TIvg; September 11th, 2012 at 09:44 PM.
    [code]Code tags[/code] are essential for python code and Makefiles!

IMN logo majestic logo threadwatch logo seochat tools logo