[英]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
malloc
, calloc
或realloc
的结果; 这是不必要的,在C89下,编译器可以掩盖错误。 您确实需要在C ++代码中强制转换这些函数的结果,但是如果您正在编写C ++,则无论如何都不应该使用malloc
, calloc
或realloc
。
其次,避免在可以帮助您的地方使用类型名称作为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.