将malloc与c中的结构一起使用
所以我尝试将malloc添加到我创建的一个电话簿应用程序中,但由于我是C语言的新手,我不确定我所做的是否正确。我遇到了一个小问题,但我已经读完了我的入门书,它没有我想要的那么详细,我无法通过搜索谷歌来判断我是完全错误地设置了malloc,还是我错过了其他一些东西 基本上,我的结构中有4个数组,将malloc与c中的结构一起使用,c,struct,malloc,C,Struct,Malloc,所以我尝试将malloc添加到我创建的一个电话簿应用程序中,但由于我是C语言的新手,我不确定我所做的是否正确。我遇到了一个小问题,但我已经读完了我的入门书,它没有我想要的那么详细,我无法通过搜索谷歌来判断我是完全错误地设置了malloc,还是我错过了其他一些东西 基本上,我的结构中有4个数组,名字,姓,主页,单元格。其中每一个都有两个函数,一个是从用户处获取信息的函数,另一个是打印用户信息并将其添加到电话簿中的函数。我现在得到的是原始代码的一个小片段,它只将名字添加到电话簿中(因此不是全部代码)
名字
,姓
,主页
,单元格
。其中每一个都有两个函数,一个是从用户处获取信息的函数,另一个是打印用户信息并将其添加到电话簿中的函数。我现在得到的是原始代码的一个小片段,它只将名字添加到电话簿中(因此不是全部代码),在每个获得用户输入的函数中,我想添加malloc函数。现在我只得到了第一个名字和第一个malloc设置,但问题是当我去检查电话簿看名字是否输入成功时,程序退出了。如果我取出malloc,它会成功工作
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#define BUFFER 50
//Structure for contacts
typedef struct friends_contact {
char *First_Name;
char *Last_Name;
char *home;
char *cell;
} fr;
void menu(fr * friends, int *counter, int user_entry, int i);
void setFirst(fr *, int *, int i);
char getFirst(fr *, int i);
void add_contact(fr * friends, int *counter, int i);
void print_contact(fr * friends, int *counter, int i);
int main()
{
int user_entry = 0;
fr *friends;
int counter = 0;
int i = 0;
menu(friends, &counter, user_entry, i);
getch();
return 0;
}
//Menu function
void menu(fr * friends, int *counter, int user_entry, int i)
{
do {
int result;
printf("\nPhone Book Application\n");
printf
("1) Add friend\n2) Delete friend\n3) Show a friend\n4)Showphonebook\n5)Exit\n");
scanf("%d", &user_entry);
if (user_entry == 1) {
add_contact(friends, counter, i);
}
if (user_entry == 2) {
}
if (user_entry == 3) {
}
if (user_entry == 4) {
print_contact(friends, counter, i);
}
} while (user_entry != 5);
}
void setFirst(fr * friends, int *counter, int i)
{
// THE MALLOC FUNCTION!
friends = (fr *) malloc(BUFFER * sizeof(fr));
printf("Enter a first name \n");
scanf("%s", friends[*counter].First_Name);
if (friends != NULL) {
free(friends);
}
}
char getFirst(fr * friends, int pos)
{
printf("%s ", friends[pos].First_Name);
return *friends[pos].First_Name;
}
void add_contact(fr * friends, int *counter, int i)
{
setFirst(friends, counter, i);
(*counter)++;
}
void print_contact(fr * friends, int *counter, int i)
{
for (i = 0; i < *counter; i++)
if (strlen(friends[i].First_Name)) {
getFirst(friends, i);
}
}
#包括
#包括
#包括
#包括
#定义缓冲区50
//联系人的结构
typedef struct friends\u联系人{
char*名字;
字符*姓氏;
查尔*家;
字符*单元;
}fr;
无效菜单(fr*朋友、int*计数器、int用户输入、int i);
void setFirst(fr*,int*,int i);
char getFirst(fr*,int i);
无效添加联系人(fr*朋友、int*计数器、int i);
无效打印联系人(fr*朋友、int*计数器、int i);
int main()
{
int user_entry=0;
fr*朋友;
int计数器=0;
int i=0;
菜单(朋友、计数器、用户输入、i);
getch();
返回0;
}
//菜单功能
无效菜单(fr*朋友、int*计数器、int user_条目、int i)
{
做{
int结果;
printf(“\n电话簿应用程序\n”);
printf
(“1)添加朋友\n2)删除朋友\n3)显示朋友\n4)显示电话簿\n5)退出\n”);
scanf(“%d”和用户输入);
如果(用户输入==1){
添加联系人(朋友、柜台、我);
}
如果(用户输入==2){
}
如果(用户输入==3){
}
如果(用户输入==4){
打印联系人(朋友、柜台、我);
}
}while(用户输入!=5);
}
void setFirst(fr*友元,int*计数器,int i)
{
//MALLOC函数!
friends=(fr*)malloc(BUFFER*sizeof(fr));
printf(“输入名字”);
scanf(“%s”,朋友[*计数器]。名字);
如果(朋友!=NULL){
免费(朋友);
}
}
char getFirst(fr*好友,int pos)
{
printf(“%s”,朋友[pos]。名字);
return*friends[pos]。名字;
}
无效添加联系人(fr*朋友、int*计数器、int i)
{
setFirst(朋友、柜台、我);
(*计数器)+;
}
无效打印联系人(fr*朋友、int*计数器、int i)
{
用于(i=0;i<*计数器;i++)
if(strlen(朋友[i].名字)){
getFirst(朋友,我);
}
}
希望在这里给任何能帮助我的人一个大大的绿色复选标记。您的结构只包含指针,而不包含分配的内存。您最好将其定义为包含写入名称的数组等:
typedef struct friends_contact{
char First_Name[20];
char Last_Name[20];
char home[20];
char cell[20];
} fr;
在这里,我将每个字段设置为20个字符长,但您可以根据需要进行更改
编辑:是的,当然你可以使用动态内存,但它值得这么麻烦吗?动态字符串的优点是它们的大小可以完全正确;您可以节省几个字节,并保证能够将名称放入字段中。但是有很多名字超过20个字符,是否需要缩写一些?当然,在malloc中,有很多微妙的分配(每个分配都可能失败)和释放 作为一种折衷办法,你可以让电话号码固定大小(不会改变),名字动态变化;然后使用
strdup
(也可能失败)分配名称
这里有一些问题:
void setFirst(fr*friends, int* counter, int i) {
// THE MALLOC FUNCTION!
friends=(fr*) malloc(BUFFER*sizeof(fr)); <-- This is not doing what you're thinking
现在,您正在malloc'ing 16*缓冲区或16x50=800字节。这允许您拥有50个“fr”结构的数组
fr * friend
|
+--------> FirstName*
| LastName*
| home*
| cell*
+----> FirstName*
| LastName*
| home*
| cell*
...
所以你有50个结构的内存,但是这些结构的内容仍然没有内存。您需要将内存分配给结构的每个成员(并且不要忘记释放所有这些成员),或者您可以使用数组而不是指针使它们成为静态成员
第二个问题:
if(friends != NULL) <-- if malloc was successful
{
free(friends); <-- release the memory
<代码>如果(朋友!= NULL)
这里有更多的事情要考虑,但首先考虑以下内容:
在
setFirst
中,您可以释放您的朋友缓冲区,本质上是说“我不再需要这个了”。当您这样做时,内存就会消失。如果要为调用方动态分配结构,则必须提供单独的释放函数,或者让用户知道清理该结构是他们的责任
此外,您只更改好友指针的本地副本。如果要将调用者的指针指向新的缓冲区,则需要将参数类型更改为fr**
您需要为整个记录和每个字段分别分配内存。例如:
void string_realloc_and_copy (char **dest, const char *src)
{
size_t len = strlen (src);
*dest = realloc (*dest, len + 1);
memcpy (*dest, src, len + 1);
}
typedef struct
{
char *name;
char *title;
} record;
record * record_new ()
{
record *r = malloc (sizeof (record));
r->name = NULL;
r->title = NULL;
return r;
}
void record_free (record *r)
{
free (r->name);
free (r->title);
free (r);
}
void record_set_name (record *r, const char *name)
{
string_realloc_and_copy (&r->name, name);
}
void record_set_title (record *r, const char *title)
{
string_realloc_and_copy (&r->title, title);
}
现在,要创建记录并用从用户读取的值填充它,请执行以下操作:
record *r;
char buffer[100 + 1];
r = record_new ();
printf("Enter a first name \n");
if (scanf ("%100s", buffer) == 1) {
record_set_name (r, buffer);
}
...
在setFirst
中,你是自由的
你的朋友
缓冲区,本质上说我不再需要这个了。当你这样做的时候,记忆就消失了。如果要为调用方动态分配结构,则必须提供单独的释放函数,或者让用户知道清理该结构是他们的责任。此外,您只更改好友指针的本地副本。如果您想将调用者的指针指向一个新的缓冲区,您需要将参数类型更改为fr**
@jpm:这是一个答案!销售时点情报系统
void string_realloc_and_copy (char **dest, const char *src)
{
size_t len = strlen (src);
*dest = realloc (*dest, len + 1);
memcpy (*dest, src, len + 1);
}
typedef struct
{
char *name;
char *title;
} record;
record * record_new ()
{
record *r = malloc (sizeof (record));
r->name = NULL;
r->title = NULL;
return r;
}
void record_free (record *r)
{
free (r->name);
free (r->title);
free (r);
}
void record_set_name (record *r, const char *name)
{
string_realloc_and_copy (&r->name, name);
}
void record_set_title (record *r, const char *title)
{
string_realloc_and_copy (&r->title, title);
}
record *r;
char buffer[100 + 1];
r = record_new ();
printf("Enter a first name \n");
if (scanf ("%100s", buffer) == 1) {
record_set_name (r, buffer);
}
...