C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 10-06-2009, 10:22 PM   #1
Registered User
 
Join Date: Oct 2009
Posts: 3
Structs, dynamic memory, and phone book entries

I am working on the classic phone book program in a C programming course, and am having a bit of difficulty with the structs, pointers, and dynamic memory allocation. The program should dynamically allocate and free memory as it moves along (as the user adds or deletes entries). For now I am focusing mainly on case 1, which is add an entry to the phone book. Later, I will move the add, delete, and print functionality to functions, but am keeping everything inside main for simplicity until then.

Can someone help me understand where I am going wrong in the add an entry part? When I run this code and examine the debug output, it seems there is an error writing to the memory address... so I assume I have an error in my pointers. Thanks for any help you can provide, I greatly appreciate it!

Code:
Description:
A program utilizing data structures to create, manipulate, and display phone book entries.  User can add, delete, and print the phone book entries.
*/

#include <stdio.h>     // Standard C input & output library
#include <stdlib.h>    // mallac, callac, and free functions


typedef struct PhoneBookEntry         // Declaration of phone book structure
{
     char FirstName[21];
     char LastName[21];
     int PhoneNum;
} person; 


int main() {             // Main driving function

    int select=0; // Integer variable for user input of phone book operation
    int contact_ctr=0; // Counter to track number of contacts
    int i=0; // Index for printing "for" loop
    
    person contacts[50];   // Declare an array of phone book entries
    person* pcontacts;  // Declare a pointer for array Entries
	//   pcontacts = &contacts[0];         // Initialize the pointer to the array's first position
    pcontacts = (person*) calloc(0, sizeof(person));    // Set pointer to allocated/initialized block of memory, size of person struct
    if (pcontacts == NULL)
       {printf("Out of memory!  Aborting...");
       return 1;}
    else  {}    // Do nothing!

    
    do {  // Print menu to screen, ask user for selection...
        printf("\nPhone Book Application:\n\n");
        printf("1) Add friend\n");
        printf("2) Delete friend\n");
        printf("3) Show phone book\n");
        printf("4) Exit\n");
        printf("What do you want to do? ");
        scanf("%d", &select);    // Store user input in variable "select"
        getchar();               // Clear the input buffer
   
        switch (select)
        {
               case 1:     // User wants to add an entry
                    contact_ctr++;
                    pcontacts = realloc(pcontacts, contact_ctr * sizeof(person));     // Reallocate memory for additional contact
                    printf("\nFirst name: ");
                    scanf("%s", contacts[contact_ctr-1].FirstName);
                    printf("Last name: ");
                    scanf("%s", contacts[contact_ctr-1].LastName);
                    printf("Phone number: ");
                    scanf("%d", contacts[contact_ctr-1].PhoneNum);
                    printf("Record added to the phone book\n\n");
                    break;
               case 2:    // User wants to delete an entry
               case 3:    // User wants to print the phone book
                    for(i=0; i<contact_ctr; i++)
                    {
                             printf("\n\nPhone Book Entries:\n\n");
                             printf("%s %s %d", contacts[contact_ctr-1].FirstName, contacts[contact_ctr-1].LastName, contacts[contact_ctr-1].PhoneNum);
                    } // end for loop
                    break;
               case 4:    // User wants to quit, break the switch and exit to loop
                    break;
               default:   // User entered a value other than 1,2,3, or 4.
                    printf("You entered an invalid selection.  Try again.\n\n\n"); 
                    break;
        }  // End switch statement
        }  // End do loop
        
   while (select!=4);
   
   printf("\nThis phone book will now close.  Goodbye!\n");
   // Pause program until user inputs any character
   getchar();
   // Return statement
   return 0;
}      // End main
wkfcs is offline   Reply With Quote
Old 10-06-2009, 10:40 PM   #2
cas
Registered User
 
Join Date: Sep 2007
Posts: 372
Code:
scanf("%d", contacts[contact_ctr-1].PhoneNum);
When reading an integer with scanf(), you must pass the address of the int, not the int itself, so scanf() knows where to write (you always need to pass an address for scanf() to know where to write, but it happens automatically with arrays, so you don't see problems with %s). Use & to get the address of the int.

Your compiler should be able to detect problems like this. If you're using gcc, always build with at least the -Wall option. Check your compiler's documentation for various diagnostic switches. And don't make the common mistake of thinking of warnings as being non-serious: often times (most of the time with gcc's -Wall flag) a warning points to a real problem in the code.
cas is offline   Reply With Quote
Old 10-06-2009, 11:25 PM   #3
Registered User
 
datainjector's Avatar
 
Join Date: Mar 2002
Posts: 354
I once also did such a thing .. After having had enought pills .. i wasnt satified as being a normal human ..so instead of proving to my self that the medication which makes me a zombie .. might not be true ..

i wrote this program ..so i could prove to myself i wasnt being brain washed by doctors for there money pills ..

Address Book
__________________
"I wish i could wish my wishs away"

"By indirections find directions out" -- William Shakespears

"Do what thou wilt shall be the whole of the law" -- Crowley "THE BEAST 666"

Mizra -> love = Death...
RDB(Rocks yooo)..

http://www.cbeginnersunited.com

Are you ready for the Trix ???
datainjector is offline   Reply With Quote
Old 10-07-2009, 06:39 AM   #4
Registered User
 
Join Date: Oct 2009
Posts: 3
Quote:
Originally Posted by cas View Post
Code:
scanf("%d", contacts[contact_ctr-1].PhoneNum);
When reading an integer with scanf(), you must pass the address of the int, not the int itself, so scanf() knows where to write (you always need to pass an address for scanf() to know where to write, but it happens automatically with arrays, so you don't see problems with %s). Use & to get the address of the int.

Your compiler should be able to detect problems like this. If you're using gcc, always build with at least the -Wall option. Check your compiler's documentation for various diagnostic switches. And don't make the common mistake of thinking of warnings as being non-serious: often times (most of the time with gcc's -Wall flag) a warning points to a real problem in the code.
Thanks cas! I was so focused on directing the input into the correct array cell that I forgot about passing the actual address. I also turned on warnings in my compiler, so hopefully that will help me out some.
wkfcs is offline   Reply With Quote
Old 10-09-2009, 06:30 AM   #5
Registered User
 
Join Date: Oct 2009
Posts: 3
After some more work, I finally ended up with a working phone book program. I have since moved the add, delete, and print entries functionality into separate functions, and now I have two new issues:

1) A warning at compile time that states:
Code:
117 [Warning] passing arg 1 of `strcpy' makes pointer from integer without a cast
and that line of code is inside the Del function:
Code:
strcpy(contacts[i].PhoneNum, nullStr);
Phone Num is an int and nullStr is a char but so far I have been unsuccessful at typecasting this.

2) The add and print functions appear to work correctly. When trying to delete an entry from the book, the program crashes. I assume I have some error in passing arguments and pointers to this function, since the delete worked before I broke the program into functions. Any suggestions?
Code:
/*
Description:
A program utilizing data structures to create, delete, and display phone book entries.
User can add, delete, and print the phone book entries.
*/

#include <stdio.h>     // Standard C input & output library
#include <stdlib.h>    // mallac, callac, and free functions
#include <string.h>		// String functions (string copy, string compare)


typedef struct PhoneBookEntry         // Declaration of phone book structure
{
     char FirstName[21];
     char LastName[21];
     int PhoneNum;
} person; 

// FUNCTION PROTOTYPES:
void Add (int*, int, person*);	// Function to add an entry
void Del (int*, int, person*);	// Function to delete an entry
void Print (int*, int, person*);	// Function to print the phone book


int main() {             // Main driving function

    int select=0; // Integer variable for user input of phone book operation
    int contact_ctr=0; // Counter to track number of contacts
    int i=0; // Index for printing "for" loop
	
    
    person contacts[50];   // Declare an array of phone book entries
    person* pcontacts;  // Declare a pointer for array Entries
    pcontacts = (person*) calloc(0, sizeof(person));    // Set pointer to allocated/initialized block of memory, size of person struct
    if (pcontacts == NULL)
       {printf("Out of memory!  Aborting...");
       return 1;}
    else  {}    // Do nothing!

    
    do {  // Print menu to screen, ask user for selection...
        printf("\n\nPhone Book Application:\n\n");
        printf("1) Add friend\n");
        printf("2) Delete friend\n");
        printf("3) Show phone book\n");
        printf("4) Exit\n");
        printf("What do you want to do? ");
        scanf("%d", &select);    // Store user input in variable "select"
        getchar();               // Clear the input buffer
   
        switch (select)
        {
               case 1:     // User wants to add an entry
				    pcontacts = realloc(pcontacts, contact_ctr * sizeof(person));     // Reallocate memory for additional contact
					Add (&contact_ctr, i, contacts);
                    break;
               case 2:    // User wants to delete an entry
					Del (&contact_ctr, i, contacts);
                    break;
               case 3:    // User wants to print the phone book
					Print (&contact_ctr, i, contacts);
					break;
               case 4:    // User wants to quit, break the switch and exit to loop
                    break;
               default:   // User entered a value other than 1,2,3, or 4.
                    printf("You entered an invalid selection.  Try again.\n\n\n"); 
                    break;
        }  // End switch statement
        }  // End do loop
        
   while (select!=4);
   
   printf("\nThis phone book will now close.  Goodbye!\n");
   // Pause program until user inputs any character
   getchar();
   // Return statement
   return 0;
}      // End main


void Add (int *contact_ctr, int i, person *contacts)
{
	(*contact_ctr)++;
	// Need to add realloc failsafe, if NULL
    printf("\nFirst name: ");
    scanf("%s", &contacts[*contact_ctr-1].FirstName);
    printf("Last name: ");
    scanf("%s",  &contacts[*contact_ctr-1].LastName);
    printf("Phone number (7-digit, no dash): ");
    scanf("%d",  &contacts[*contact_ctr-1].PhoneNum);
    printf("Record added to the phone book\n\n");
}	// End function Add

void Del (int *contact_ctr, int i, person *contacts)
{
	char delTempf[21];	// Temporary string for deletion of an entry - first name
	char delTempl[21];	// Temporary string for deletion of any array - last name
	char nullStr[21] = {"\0"};	// Null string for use in deleting entries

	printf("\nFirst name: ");
	scanf("%s", &delTempf);
    printf("Last name: ");
	scanf("%s", &delTempl);
	// compare strings, find entry or return entry not found
	for (i=0; i<*contact_ctr; i++)
	{
		if (strcmp(delTempf, contacts[i].FirstName) == 0)
		{
			strcpy(contacts[i].FirstName, nullStr);
			strcpy(contacts[i].LastName, nullStr);
			strcpy(contacts[i].PhoneNum, nullStr);
			free(&contacts[i]);
			(*contact_ctr)--;	// Contact deleted, update the contact total counter
			break;
		}
		else
		{
			printf("\nEntry not found.\n\n");				
		}
	}	// End for loop

    printf("Record deleted from the phone book\n\n");
}	// End function Del

void Print (int *contact_ctr, int i, person *contacts)
{
	char nullStr[21] = {"\0"};	// Null string
	if (*contact_ctr > 0)	// If there are entries, print them
	{
		printf("\n\nPhone Book Entries:\n\n");
		for(i=0; i<*contact_ctr; i++)
		{
			if (strcmp(nullStr, contacts[i].FirstName) != 0)	// If this index is NOT null, print it
			{
				printf("%s %s %d\n", contacts[i].FirstName, contacts[i].LastName, contacts[i].PhoneNum);
			}
			else {}	// Do nothing (skip this index because no entry exists)
		} // end for loop
	}
	else	// Else the book is empty, tell the user
	{
		printf("\n\nThe phone book is currently empty.\n\n");
	}
}	// End function Print
wkfcs is offline   Reply With Quote
Old 10-09-2009, 03:57 PM   #6
cas
Registered User
 
Join Date: Sep 2007
Posts: 372
Quote:
I have been unsuccessful at typecasting this.
When you're having problems, your first response should not be to cast. Casting is rarely the right thing to do. In the case here, you have an int. Why would you try to copy a string into it? Just set it to zero, or whatever value you think means empty for an int.

As for the crash, you should always use a debugger. If it supports your platform, I'd recommend valgrind. As a start, though, you should absolutely never call free() on memory that wasn't allocated with malloc()/realloc()/calloc() (or other function your platform might provide, such as strdup()).

Finally, when you're using scanf() with %s, don't add a & to your string. It's either totally wrong (if your string is a pointer), or technically wrong (if your string is an array). It will probably work with an array, but it's still not right.
cas is offline   Reply With Quote
Reply

Tags
dynamic memory, phone book, struct

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Phone memory error geek@02 Tech Board 2 08-07-2009 01:32 AM
a phone book program mackieinva C Programming 2 09-19-2007 06:31 AM
Moral dillema Bubba A Brief History of Cprogramming.com 40 08-22-2004 03:23 PM
Contest Results - May 27, 2002 ygfperson A Brief History of Cprogramming.com 18 06-18-2002 01:27 PM
Linked Lists bigblack C++ Programming 7 02-05-2002 05:21 PM


All times are GMT -6. The time now is 05:30 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22