2013-10-18 142 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問題。一切都很好,再次感謝! –