将malloc与c中的结构一起使用

将malloc与c中的结构一起使用,c,struct,malloc,C,Struct,Malloc,所以我尝试将malloc添加到我创建的一个电话簿应用程序中,但由于我是C语言的新手,我不确定我所做的是否正确。我遇到了一个小问题,但我已经读完了我的入门书,它没有我想要的那么详细,我无法通过搜索谷歌来判断我是完全错误地设置了malloc,还是我错过了其他一些东西 基本上,我的结构中有4个数组,名字,姓,主页,单元格。其中每一个都有两个函数,一个是从用户处获取信息的函数,另一个是打印用户信息并将其添加到电话簿中的函数。我现在得到的是原始代码的一个小片段,它只将名字添加到电话簿中(因此不是全部代码)

所以我尝试将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);
}

...