使用动态内存分配i C时输出奇怪

时间:2015-06-03 15:19:08

标签: c

我正在处理此代码,但尚未完成。但是在测试添加新的联系人功能和打印功能时,我得到了这个奇怪的输出。只要我没有添加多个联系人,Everythin看起来就好了。我在这里做错了什么?

//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;
}
//---------------------------------------------------------

2 个答案:

答案 0 :(得分:2)

问题在于:

printf("\n%s %d\n", &cPhoneBook_name[i], iPhoneBook_nr[i]);
{p> cPhoneBook_name如果是char[]类型。例如,表达式char[1]为您提供列表中的第二个字符。虽然代码中的名称宽度为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(&#34;%s&#34;,&amp; cPhoneBook_name [80 * iContacts]);

答案 1 :(得分:2)

这很可能是你&#34;奇怪的输出&#34;的根源。当您输入多个联系人时:

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

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

话虽如此,这整个方法都是错误的;如果您没有创建字符串数组,那么每次添加联系人时都会创建一个扩展的单个字符串(不成功),并且iContacts索引将指向i字符串的字符,而不是字符串列表中的i&#39;字符串。

这是一种应该有效的方法:

#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代码中投射malloccallocrealloc的结果;这是不必要的,在C89编译器下可以掩盖错误。您需要在C ++代码中强制转换这些函数的结果,但如果您正在编写C ++,那么您不应该使用malloccalloc,或者realloc无论如何。

其次,避免使用类型名称作为sizeof参数来帮助它。请改用以下内容:

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

表达式的类型 *pT,因此sizeof *p相当于sizeof (T)。这样,malloc将始终分配正确的内存量,而不管T,如果您决定更改T,则只需在一个位置进行更改。

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

第四,realloc电话费用可能很昂贵,所以当你感觉这样做时,你想要最小化它们。将阵列的大小加倍是一种常见技术。