如何使用realloc

时间:2015-09-17 19:25:04

标签: c realloc

我有一个程序,它将Name作为输入,如果输入小于允许的大小,它将保存在指针中。

如果输入大于允许的大小,则realloc函数将用于满足所需的内存。 此时程序仅分配6个字节,5代表名称MICHI,1代表'\ 0'。 如果用户键入MICHAEL,则程序会为该指针分配足够的内存以使MICHAEL符合该指针。

以下是该计划:

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

struct person{
    char *name;
}pers;

void addMem(void){
    unsigned int length = 6;
    size_t newLength = 0;
    unsigned int newSize = 0;
    unsigned int i =0;
    char *name;
    int c;

    name = malloc(lenght);
    if(name == NULL){
        exit(1);
    }
    newSize = length;

    printf("Enter your name:>  ");

    while ((c = getchar()) != '\n' && c!=EOF){
        name[i++]=(char)c;

        if(i == newSize){
            newSize = i+length;
            name = realloc(name, newSize);
        }
    }

    name[i] = '\0';

    newLength = strlen(name)+1;
    pers.name = malloc(newLength);

    memcpy(pers.name, name, newLength);

    free(name);
    name = NULL;
}

int main(void){
    addMem();

    printf("Your name is:>  %s\n",pers.name);
    free(pers.name);
    pers.name = NULL;
    return 0;
}

该程序工作正常,但我需要以某种方式使realloc()只给出最大内存大小,因为此时它将重新分配,直到用户输入。

这意味着我 Michi 6 字节('\ 0' 5 + 1 )最大尺寸 8 7 迈克尔 1 '\ 0> < /强>)。

我该怎么做?

修改

我希望你现在明白。

我的程序只接受 5 字母的名称。 在某些时候,我决定程序可以接受最大 10 字母的名称。 我已经为5(michi)分配了内存。 如果你输入迈克尔,我们有7个字母,所以程序应该为迈克尔分配另外两个。 但如果我键入Schwarzernegger,这个名字太长了我不接受它所以我需要让我的程序只为迈克尔分配内存。

3 个答案:

答案 0 :(得分:2)

让我们打破你的主循环:

unsigned int length = 6;
unsigned int newSize = 0;

name = malloc(length);
...
newSize = length;

while ((c = getchar()) != '\n' && c!=EOF){
    name[i++]=(char)c;

    if(i == newSize){
        newSize = i+length;
        name = realloc(name, newSize);
    }
}

您开始为name分配6个字节。这对5个字符加上一个NULL字节有好处。然后,对于您阅读的每个字符,将其添加到name的末尾。

在每次迭代中,检查输入的字符数是否等于缓冲区的分配大小。如果是这样,你realloc缓冲区并再增加6个字节,所以现在它的长度为12个字节。

然后继续前进,阅读更多角色。如果您发现自己输入了12个字符,则realloc多6个字节,所以现在name长度为18个字节。

这是一个很好的方法。通过这种方式,您可以分配足够的内存来容纳用户键入的内容,最多分配5个额外字节。因此,不需要将名称限制为7个字节或任何其他特定数字。您可以添加一个检查,指出如果字符总数超过7个字节,则输出错误并退出,但似乎没有任何理由这样做。

编辑:

如果名称永远不会超过7个字节,则malloc可以执行此操作而不是reallocname

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

struct person{
    char *name;
}pers;

void addMem(void){
    unsigned int i = 0;
    char name[8];
    int c;

    printf("Enter your name:>  ");

    while ((c = getchar()) != '\n' && c!=EOF){
        name[i++]=(char)c;

        if(i == sizeof(name)){
            printf("name too long\n");
            pers.name = NULL;
            return;
        }
    }

    name[i] = '\0';

    pers.name = malloc(strlen(name)+1);
    strcpy(pers.name, name);
}

int main(void){
    addMem();

    printf("Your name is:>  %s\n",pers.name);
    free(pers.name);
    pers.name = NULL;
    return 0;
}

这样,读取名称的内部缓冲区是固定大小的,当您读完该名称时,仍然会分配足够的空间将字符串复制到pers.name

答案 1 :(得分:1)

你应该得到多少内存的计算是错误的。 (正如@dbush在评论中所说,这很好,因为你在=IF(C36>0,LastInputTimeStamp(),"") 的块中分配内存,这比按字节分配更有效率)

无论如何,要改变以6字节为单位分配以分配字节为单位的行为,请执行以下操作:

6 bytes

将打印:

while ((c = getchar()) != '\n' && c != EOF) {
    name[i++] = (char) c;

    /* added IF requests on comments */
    if (i > 7) {
        printf("Names longer than 7 not allowed!\n");
        name[7] = 0x0;
        break;
    }
    else if (i >= length) 
        name = realloc(name, newSize);
}

了解更多

正如dbush Answer所说,你最好分配一个大内存块并尽可能少地使用realloc。第二个环节维持了这一点。它还建议您使用第二个循环来计算所需的大小,因此您只需要拨打$ ./draft Enter your name:> Michael reallocing 7 reallocing 8 Your name is:> Michael $ ./draft Enter your name:> StackOverflow reallocing 7 reallocing 8 reallocing 9 reallocing 10 reallocing 11 reallocing 12 reallocing 13 reallocing 14 Your name is:> StackOverflow $ ./draft Enter your name:> Michi Your name is:> Michi 一次。

答案 2 :(得分:1)

正如Enzo在7封信之后停止的答案,你可以使用。

while ((c = getchar()) != '\n' && c != EOF) {
name[i++] = (char) c;

if (i >= length) {
    if(i+1<=7)
       name = realloc(name, i + 1);
    else
       {
          //generate error message
       }
}
}