繁体   English   中英

使用动态内存分配时出现奇怪的输出

[英]Strange output while using dynamic memory allocation i C

我正在处理此代码,但尚未完成。 但是在测试添加新的联系人功能和打印功能时,我得到了这个奇怪的输出。 只要我不添加多个联系人,一切都可以。 我在这里做错了什么?

//Libraries:
#include <stdio.h>
#include <stdlib.h>

//Function prototypes
int showMenu(); //Shows user options

//Main function
int main() {

    //Variable declerations
    int i = 0;
    int iOption = 0;
    int iContacts = 0;
    char *cPhoneBook_name;
    int *iPhoneBook_nr;

    cPhoneBook_name = (char *) calloc(1, 80 * sizeof(char));
    iPhoneBook_nr = (int *) calloc(1, sizeof(int));

    do {

        //Memory check
        if(cPhoneBook_name == NULL || iPhoneBook_nr == NULL){
            printf("\nOut of Memory!\n");
            return;
        }

        //Show menu
        iOption = showMenu();

        switch (iOption) {
            case 1: //Add contact
                printf("\nEnter name:\n");
                scanf("%s", &cPhoneBook_name[iContacts]);
                printf("\nEnter number:\n");
                scanf("%d", &iPhoneBook_nr[iContacts]);
                cPhoneBook_name = realloc(cPhoneBook_name, 80 * sizeof(char));
                iPhoneBook_nr = realloc(iPhoneBook_nr, sizeof(int));
                iContacts += 1;
                break;
            case 2: //Modify contact
                //Code here
                break;
            case 3: //Show contacts
                for(i = 0 ; i < iContacts ; i++) {
                    printf("\n%s %d\n", &cPhoneBook_name[i], iPhoneBook_nr[i]);
                }
                break;
            case 4: //Free memory (delete contacts)
                free(cPhoneBook_name);
                free(iPhoneBook_nr);
                break;
        }
    }while(iOption != 5);//Exit if iOption is 5;

    system("clear");
    return 0;
}


//Function definition - showMenu()
int showMenu() {

    int iOption = 0;

    //system("clear");

    printf("\n   Phone book   \n");
    printf("------------------------\n");
    printf("1. Add new contact.\n");
    printf("2. Edit existing contact\n");
    printf("3. Show contact(s)\n");
    printf("4. Clear phone book\n");
    printf("5. Exit\n");
    printf("------------------------\n");
    printf("Option --> ");
    scanf("%d", &iOption);

    return iOption;
}
//---------------------------------------------------------

问题在于:

printf("\n%s %d\n", &cPhoneBook_name[i], iPhoneBook_nr[i]);

cPhoneBook_name如果类型为char[] 因此,例如,表达式char[1]为您提供列表中的第二个char[1] 虽然代码中的名称为80个char宽。 因此,请尝试:

printf("\n%s %d\n", &cPhoneBook_name[i*80], iPhoneBook_nr[i]);

编辑:

我还发现这:

cPhoneBook_name = realloc(cPhoneBook_name, 80 * sizeof(char));

无效,因为您要将cPhoneBook_name大小从80调整为80。请尝试:

    cPhoneBook_name = realloc(cPhoneBook_name, (iContacts+1) 80 * sizeof(char)); 

并且:scanf(“%s”,&cPhoneBook_name [80 * iContacts]);

输入多个联系人时,这很可能是“奇怪输出”的根源:

cPhoneBook_name = realloc(cPhoneBook_name, 80 * sizeof(char));

您实际上并没有扩展cPhoneBook_name数组的大小。 realloc调用中,第二个参数是数组的新大小 ,而不是要添加到现有大小的数量。

话虽如此,整个方法是错误的。 您没有创建字符串数组,而是(未成功)创建了一个字符串,该字符串在每次添加联系人时都会扩展,并且iContacts索引将指向字符串的第i字符 ,而不是第i字符字符串列表中的第一个字符串。

这是一种可行的方法:

#define ROWS 5 // start with 5 rows in your contact list

// Create a type to store a single phone book entry
struct PhoneBookEntry {
  char name[80];  // fixed size to keep things simple
  int number;
};

// Create an array that can initially store ROWS
// phone book entries
struct PhoneBookEntry *phoneBook = malloc ( sizeof *phoneBook * ROWS );
size_t phoneBookRows = ROWS;
...
case 1: // Add contact
  // Before adding a contact, see if we need to extend the phone book
  // array
  if ( iContacts == phoneBookRows )
  {
    // double the size of the phone book array
    struct PhoneBookEntry *tmp = realloc( phoneBook, 2 * sizeof *phoneBook * phoneBookRows );
    if ( tmp )
    {
      phoneBook = tmp;
      phoneBookRows *= 2; 
    }
    else
    {
      fprintf( stderr, "Could not extend phone book!\n" );
      break;
    }
  }
  ...
  scanf( "%s", phoneBook[iContacts].name ); // note no & operator; arrays are special
  ...
  scanf( "%d", &phoneBook[iContacts].number );

注意事项:

首先, 不要在C代码中realloc malloccallocrealloc的结果; 这是不必要的,在C89下,编译器可以掩盖错误。 确实需要在C ++代码中强制转换这些函数的结果,但是如果您正在编写C ++,则无论如何都不应该使用malloccallocrealloc

其次,避免在可以帮助您的地方使用类型名称作为sizeof参数。 使用类似以下的内容:

T *p = malloc( N * sizeof *p );

表达式 *p的类型为T ,因此sizeof *p等效于sizeof (T) 这样,无论T为何, malloc都会始终分配正确的内存量,并且如果您决定更改T ,则只需在一个位置进行更改。

第三,如果realloc无法满足请求,它将返回NULL 如果将NULL分配给phoneBook变量,则将丢失对已分配内存的引用。 realloc的结果分配给一个临时变量,测试NULL ,然后将其分配给您的phoneBook变量,是更安全的方法。

第四,重新realloc调用可能会很昂贵,因此您想在不合理的情况下尽量减少调用。 将数组的大小加倍是一种常见的技术。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM