如何更改 C 中结构属性的大小?

How to change size of a struct's attribute in C?

我是 C 编程的新手,我需要编写一本 phone 书。每个条目必须有一个名称、一个 phone 编号和一个注释部分。问题是注释部分的大小应该可以根据输入进行更改。例如,如果用户输入一个包含 30 个字符的字符串,则注释的大小应为 30。我不知道该怎么做。

到目前为止,这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <note>

struct Entries {
    char name[50];
    char phoneNumber[11];
    char * note;
    note = (char *)malloc(5*sizeof(char));
}Entries;

int main()
{
int command;
int counter = 0;
char tempNote[50];
char tempName[50];
char tempPhoneNumber[11];

while(1){
    printf("Welcome to myPhoneBook! Please select an option:\n   1) New entry\n   2) List all entries\n   3) Edit\n   4) Delete\n   5) Search\n");
    scanf("%d", &command);

    if(command == 1){
        struct Entries entry;

        printf( "Enter a name:\n");
        scanf("%s",tempName);
        strcpy(entry.name, tempName);

        printf( "Enter a phone:\n");
        scanf("%s",tempPhoneNumber);
        strcpy(entry.phoneNumber, tempPhoneNumber);

        printf( "Enter a note:\n");
        scanf("%s",tempNote);
        entry.note = (char *)realloc(entry.note,strlen(tempNote));
        strcpy(entry.note, tempNote);

        counter++;
    }
}
return 0;
}

当用户第一次输入姓名、phone号码和备注时,程序会自动停止工作,尽管它本应要求永远使用这些属性。

您可以使用 flexible array member。这是更好的方法。

引自 C11 标准,章节 §6.7.2.1

[...] the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

和例子

EXAMPLE 2 After the declaration:

  struct s { int n; double d[]; };

the structure struct s has a flexible array member d. A typical way to use this is:

int m = /* some value */;

struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));

and assuming that the call to malloc succeeds, the object pointed to by p behaves, for most purposes, as if p had been declared as:

struct { int n; double d[m]; } *p;

现在,按照上面的步骤,您可以扫描输入,使用输入长度作为m,然后,分配足够的内存来容纳输入。

替换

entry.note = (char *)realloc(entry.note,strlen(tempNote));

entry.note = malloc(strlen(tempNote) + 1);

还有

移除

note = (char *)malloc(5*sizeof(char)

来自 struct 定义。它不属于那里。

我建议先学习 C 的基础知识。 C 实际上只是一个带有宏的可移植汇编器。在你完成任何事情之前,你绝对需要知道指针和内存分配是如何工作的:)

顺便说一句,恭喜你开始学习 C,这会让你对计算机和编程语言的本质有很多深刻的见解:):)

关闭,

If the user enters a string with 30 characters, size of note should be 30.

C 中的字符串以 null 结尾,因此您需要为终止字符('\0')保留 space。您可以交替将字符串存储为字符串的长度和字符,但是您需要确定可表达的最大字符数。

最简单的方法是使用 strdup() 为字符串和空终止符分配足够的 space。

if( entry.note ) free(entry.note); //avoid leaking memory
entry.note = strdup(tempNote);

或者您可以使用包含长度和数据的结构,使用以下方法进行分配、分配和释放,

typedef struct {
    unsigned short int len;
    char str[1];
} strwlen_t;
strwlen_t* string_withlen_alloc(unsigned short int size) {
    strwlen_t* p = malloc( size + sizeof(strwlen_t) );
    p->str[0] = '[=11=]';
    p->len = 0;
    return p;
}
strwlen_t* strwlen_dup(char* str) {
    unsigned short int len = strlen(str);
    strwlen_t* p = malloc( len + sizeof(strwlen_t) );
    memcpy(p->str,str);
    p->len = len;
    return p;
}
void strwlen_free(strwlen_t* p) {
    free(p);
}
strwlen_t* strwlen_cpy(strwlen_t* dp,char* sp) {
    strcpy(dp->str,sp);
    dp->len = len(sp);
    return(dp);
}

声明您的条目结构,

struct Entries {
    char name[50];
    char phoneNumber[11];
    strwlen_t* note;
} Entries;

那么你可以使用,

if( entry.note ) free(entry.note);
entry.note = strwlen_dup(tempNote);

并使用

打印 entry.note
printf("note: %s\n",entry.note.str);