2013-10-18 103 views
0

我不明白为什么我的程序输出看似随机的Windows路径,如下所示。程序打印Windows路径?

\maven, : ORS=4 (id: 4677968) 
m32\cmd.exe, ò: Æ (id: 5525087) 
, : (id: 4653392) 

它这样做,当循环通过我有的结构数组并显示里面的值。有趣的是,它的作品完美。如果我添加5个条目,它仍然准确地显示所有条目。然而,在一切之前,它会打印上面显示的随机路径。

我打算附上整个程序,因为我实在不知道该把问题缩小到什么地方。我是C新手,特别是手动处理内存的新手。所以这可能是问题所在。提前致谢。

程序:

#include<stdio.h> 
#include<string.h> 

// Define structures 
typedef struct Contact 
{ 
    int id; 
    char fname[24]; 
    char lname[24]; 
    char number[16];  
} Contact; 

typedef struct Phonebook 
{ 
    Contact* contacts; 
    int contacts_length; 
    int id_tracking; 
} Phonebook; 

// Define prototypes 
Phonebook addContact(Phonebook); 
Phonebook removeContact(Phonebook); // removeContact() prompts the user for information about whom they want to remove. 
void viewContacts(Phonebook); 
void exportContacts(Phonebook); 
Contact findEntry(int, Phonebook); 
Phonebook removeEntry(int, Phonebook); // removeEntry() can be called to explicitly remove the entry with the passed in integer id. 

int main() 
{  
    // Define variables 
    int menuChoice = 0, status = 1; 
    Phonebook phonebook; 
    phonebook.contacts = (Contact*) malloc(sizeof(Contact)); 

    // Check memory allocation 
    if(phonebook.contacts == NULL) 
    { 
     printf("\nFatal error: Out of memory... now exiting."); 
     return; 
    } 

    // Handle the user 
    do 
    { 
     // Begin collecting and assigning data 
     printf("\nContact Menu\n"); 
     printf("\n(1.) Add contact"); 
     printf("\n(2.) Remove contact"); 
     printf("\n(3.) View contacts"); 
     printf("\n(4.) Export contacts"); 
     printf("\n(5.) Exit"); 
     printf("\n\nPlease choose a menu option (enter the number): "); 
     scanf("%d", &menuChoice); 

     // Interpret menu choice 
     switch(menuChoice) 
     { 
      case 1:  
       // Begin adding contact 
       phonebook = addContact(phonebook); 
       status = 1; 
       break; 
      case 2: 
       phonebook = removeContact(phonebook); 
       status = 1; 
       break; 
      case 3: 
       viewContacts(phonebook); 
       status = 1; 
       break; 
      case 4: 
       exportContacts(phonebook); 
       status = 1; 
       break; 
      case 5:   
       // Free memory 
       free(phonebook.contacts); 

       // See ya! 
       printf("\nGoodbye!"); 
       status = 0; 
       break; 
      default: 
       printf("I'm sorry, I didn't quite understand that. Please try again."); 
       status = 1; 
       break; 
     }   
    } 
    while(status != 0); 

    // Return 0 for exit 
    return 0; 
} 

Phonebook addContact(Phonebook phonebook) 
{ 
    // Clear screen first 
    system("cls"); 

    // Define contact and set random id 
    Contact entry; 
    entry.id = phonebook.id_tracking; 
    phonebook.id_tracking++; 

    // Obtain information 
    printf("First name (24 characters max): "); 
    scanf("%s", &entry.fname); 
    printf("Last name (24 characters max): "); 
    scanf("%s", &entry.lname); 
    printf("Telephone number (recommended format: ###-###-####): "); 
    scanf("%s", &entry.number); 

    // Handle memory allocation 
    if(phonebook.contacts_length > 1) 
    { 
     phonebook.contacts = (Contact*) realloc(phonebook.contacts, sizeof(Contact) * (phonebook.contacts_length + 1)); 
    } 

    // Save the contact to the array and count up 
    phonebook.contacts[phonebook.contacts_length] = entry; 
    phonebook.contacts_length++; 

    printf("Contact saved!\n"); 
    return phonebook; 
} 

Phonebook removeContact(Phonebook phonebook) 
{ 
    // First check to make sure they have saved contacts 
    if(phonebook.contacts_length < 1) 
    { 
     // No contacts saved, tell them 
     printf("\nYou haven't saved any contacts.\n"); 
     return; 
    } 

    // Define variables 
    int i, chosenId = 0;  

    // Display contacts with their ids 
    for(i = 0; i < phonebook.contacts_length; i++) 
    { 
     Contact entry = phonebook.contacts[i]; 
     printf("\n%s, %s (id: %d)", entry.lname, entry.fname, entry.id); 
    } 

    // Handle removal 
    printf("\n\nPlease enter the ID of the contact you would like to remove: "); 
    scanf("%d", &chosenId); 

    // Remove 
    Phonebook updatedPhonebook = removeEntry(chosenId, phonebook); 
    printf("Contact removed!\n"); 

    return updatedPhonebook;  
} 

void viewContacts(Phonebook phonebook) 
{ 
    // First check to make sure they have saved contacts 
    if(phonebook.contacts_length < 1) 
    { 
     // No contacts saved, tell them 
     printf("\nYou haven't saved any contacts.\n"); 
     return; 
    } 

    // Define variables 
    int i; 

    // Display contacts with their ids 
    for(i = 0; i < phonebook.contacts_length; i++) 
    { 
     Contact entry = phonebook.contacts[i]; 
     printf("\n%s, %s: %s (id: %d)", entry.lname, entry.fname, entry.number, entry.id); 
    } 

    printf("\n"); 

    return; 
} 

/* 
    * Experimenting with I/O in C 
    */ 
void exportContacts(Phonebook phonebook) 
{ 
    // First check to make sure they have saved contacts 
    if(phonebook.contacts_length < 1) 
    { 
     // No contacts saved, tell them 
     printf("\nYou have no contacts to be exported.\n"); 
     return; 
    } 

    // Define and initialize variables 
    int i; 
    char outputName[] = "contacts.txt"; 
    FILE *contactFile = fopen(outputName, "w"); 

    // Print message 
    printf("\nExporting contacts to .txt file... "); 

    // Print to the file  
    for(i = 0; i < phonebook.contacts_length; i++) 
    { 
     Contact entry = phonebook.contacts[i]; 
     fprintf(contactFile, "%s, %s (id: %d): %s\n", entry.lname, entry.fname, entry.id, entry.number); 
    } 

    // Close the file 
    fclose(contactFile); 

    // Done 
    printf("Done!"); 
    printf("\nData exported to contacts.txt located where this program was launched."); 
} 

Contact findEntry(int id, Phonebook phonebook) 
{ 
    int i; 

    for(i = 0; i < phonebook.contacts_length; i++) 
    { 
     Contact entry = phonebook.contacts[i]; 

     if(entry.id == id) 
     { 
      return entry; 
     } 
    } 
} 

Phonebook removeEntry(int id, Phonebook phonebook) 
{ 
    // Define variables 
    int i, positionToFree; 

    // Search for the index of the entry to remove 
    for(i = 0; i < phonebook.contacts_length; i++) 
    {  
     Contact entry = phonebook.contacts[i]; 

     if(entry.id == id) 
     { 
      positionToFree = i; // This is the position to be freed 
     } 

     // We've found what we need, break now 
     break; 
    } 

    // Loop starting at that entry and remove 
    for(i = positionToFree; i < phonebook.contacts_length; i++) 
    {  
     Contact temp = phonebook.contacts[i + 1]; 
     phonebook.contacts[i] = temp; 
    } 

    // Count down for contacts_length 
    phonebook.contacts_length--; 

    // Return the updated contacts 
    return phonebook; 
} 

回答

0

这听起来像是未定义行为。

您从未初始化phonebook.contacts_length。它可以有任何价值。当你去添加一个条目时,很有可能realloc调用失败。你不检查返回值,所以你不知道。

坏juju。

+0

我什至没有意识到......我会补充说,我一定会添加内存检查。就像我说的,我是手动内存管理的新手。 –

+0

我刚注意到一些东西。如果'phonebook.contacts_length> 1',则只能重新分配。这意味着第一个realloc是在添加了两个联系人并且即将添加第三个联系人之后。但是你只用一个元素初始化数组。当你添加第二个联系人时,你将有一个缓冲区溢出。这是不明确的。尝试使用'> 0'或'> = 1'代替。或者用NULL初始化数组,并且总是重新分配。 – paddy

+0

初始化变量修复它!谢谢你,稻田。我从来没有想过初始化,因为我总是从0开始整数。我还修复了你提到的realloc问题。一切都很好,再次感谢! –