【问题标题】:Dynamic Memory Allocation Practice动态内存分配实践
【发布时间】:2014-09-14 02:31:14
【问题描述】:

我打算用 C 语言做一个关于动态内存分配的书本练习。程序要我做以下事情

-read a file and open a file from stdin, for example ./program < input.txt > output.txt
-store each line by dynamically creating an array of strings
 *assume and allocate enough space to store 5 lines of type char*
  when this turns out to insufficient double the amount of space to store more/*realloc?*/ 
 *when allocatingspace to store line,allocate only enough memory to store particular line
-print lines to screen in reverse order
-print number of lines to screen
-print total characters to screen
(we can assume each line can be stored in 1000 bytes)

我试图计划我的方法来做到这一点,并希望得到一些意见。我是动态内存分配的新手,所以如果我屠夫但我已经阅读过它,请原谅我。以下将是我的伪代码方法和问题。假设我们有带行的文件输入

hello world
store these lines
but only enough memory to store these particular lines
then print out these lines in reverse
make sure to keep track of the line count,and character count
this is a 6th line so double the space of the array to store 10 lines

我的伪代码破折号表示一般指令,*更详细一些

-read file in from stdin
    begin index count for the string_array
    /*we can assume line will fit into 1000 bytes*/
      buffer[1000]
    /*allocate memory to store 5 adresses of strings*/
      char** string_array = malloc(5 * sizeof(char))
    /*begin reading file*/
      while(fgets(buffer,sizeof(buffer),stdin != NULL))
-store each line in buffer into the array
    /*allocate only enough space to store the particular line,not sure how to do this but..*/
      string_array[index] = malloc(strlen(buffer) * sizeof(char)) /*afraid buffer will be 1000 like intialized?*/
    /*add characters of line to character sum and add the line to linesum*/
      charactersum = charactersum + strlen(buffer)
      linesum = linesum + 1
    /*fill the array index with each line string*/
      strcpy(string_array[index],buffer
    increment index

我不知道的一件事是如何为 string_array 重新分配空间,因为最终它将需要更多空间来存储 5 个地址。我在想。。

string_array = realloc(string_array, 2*sizeof(string_array)

但是我如何检查我的数组是否没有更多空间来存储字符串地址以便重新分配以及我将它放在哪里?这种方法可行吗?我希望我正确使用 malloc 和 realloc 没有匹配错误,因为我遇到了这些问题。打印,我可以做得很好,但我更关心正确满足动态分配要求并正确构建数组

【问题讨论】:

  • 提示:2*sizeof(string_array) 不会像你想象的那样做。
  • 我认为这是不正确的,我必须在其中的某处包含 char 吗?
  • 它在多个层面上都是错误的。首先它是指针的大小,而不是原始分配的基础大小的大小。其次,它的大小错误的类型string_array 指向的是 char*, not char**` 的动态序列。我认为你只需要在动态分配一章中复习一下。它很容易成为新 C 程序员最难掌握的东西。
  • 当使用char** string_array 创建时,变量string_array 将始终衰减为简单的char *,(通常在32 位机器上为4 字节,在64 位机器上为8 字节),无论分配了多少内存。所以sizeof(string_array) 将返回 4 或 8。这不是你需要的。
  • while(fgets(buffer,sizeof(buffer),stdin != NULL)) --> while(fgets(buffer,sizeof(buffer),stdin) != NULL)

标签: c arrays string dynamic


【解决方案1】:

关于您的陈述:
打印,我可以做得很好,但我更关心正确满足动态分配要求并正确构建数组

这里有一些步骤
char **string_array={0};创建、修改和释放内存 //将变成一个“字符串”数组

注意: C 并没有真正的 string 类型,但是当一个 char 数组以 NULL 字符 (\0),通常称为 C 字符串

1) 确定字符串的数量,以及每个字符串的最大长度。为了简单说明,请使用:

#define NUM_STRINGS 10
#define MAX_STR_LEN 10  

2)为您的每个字符串创建指针(实际上只是创建 NUM_STRINGS 个字符 *)

string_array=malloc(NUM_STRINGS * sizeof(char *));//creates 10 char *  

现在你有 *string_array[0] 到 *string_array[9],每个都有
place 在内存中但没有内存空间。 (大不同)

3)为每个char *分配内存空间,从而创建char数组

for(i=0;i<NUM_STRINGS;i++)
{
    string_array[i]=malloc(MAX_STR_LEN +1);//+1 for null terminator
                                           //note: this could have also been 
                                           //...(MAX_STR_LEN * sizeof(char) +1)
                                           //but because sizeof(char) == 1, it is equivalent
}  

4) 对于string_array 的内存_re_allocation,你可以再次使用#define:

for(i=0;i<NUM_STRINGS;i++)
{
    string_array[i] = realloc(string_array, 2*MAX_STR_LEN +1);
}

注意
realloc 也可以用于增加字符串的number,这里只是
应用于改变每个现有字符串的长度

5) 最后,当完成使用以这种方式创建的任何变量时,它的内存在
而不是 stack,并且必须是 free'd。

for(i=0;i<NUM_STRINGS;i++)
{
    free(string_array[i]);
}
free(string_array);    

总结这里是上面讨论的所有内容(realloc 除外)都包含在两个中
创建 string 数组的函数,然后释放它们:

//Create string arrays
char ** allocMemory(char ** a, int numStrings, int maxStrLen)
{
    int i;
    a = calloc(sizeof(char*)*(numStrings), sizeof(char*));
    for(i=0;i<numStrings; i++)
    {
      a[i] = calloc(sizeof(char)*maxStrLen + 1, sizeof(char));
    }
    return a;
}
//free string arrays
void freeMemory(char ** a, int numStrings)
{
    int i;
    for(i=0;i<numStrings; i++)
        if(a[i]) free(a[i]);
    free(a);
}  

使用示例

int main(void)
{
    char **str=0;
    //create array pointers and space for desired number of strings:
    str = allocMemory(str, NUM_STRINGS, MAX_STR_LEN);//create space for NUM_STRINGS strings, 
                                                     //each with space for MAX_STR_LEN + 1 characters 
                                                     //(+1 for NULL);  
    //use strings...

    //when done using:
    freeMemory(str, NUM_STRINGS);
    return 0;
}

【讨论】:

  • 当你说 NUM_STRINGS 和 MAX_STR_LEN 不是你硬编码每个的长度时,这应该取决于行长度不应该吗?
  • @ZachSantiago - 他们确定字符串的长度,而不是相反。如果要增加内存,请结合#defines 使用乘数。请参阅帖子中的 realloc 部分。有很多方法可以做到这一点,这只是为了让您理解概念,希望根据您的问题进行说明。
【解决方案2】:
    /*allocate memory to store 5 adresses of strings*/
      char** string_array = malloc(5 * sizeof(char))

错了;因为字符串的地址是char * 类型,所以写

        char **string_array = malloc(5 * sizeof(char *));

甚至更好

        char **string_array = malloc(5 * sizeof*string_array);

(在我看来)。

我不知道的一件事是如何为 string_array 因为最终它需要更多的空间来存储 5个地址。我在想。。

string_array = realloc(string_array, 2*sizeof(string_array)

但是我如何检查我的数组是否没有更多空间来存储字符串 地址以便重新分配,我会将它放在哪里?

由于string_arraychar **sizeof(string_array) 没有给出所需的数组大小。我们必须以某种方式存储分配的数组大小,比方说

    int numStrings = 5;

并在需要更多空间时使用它(在我们存储一行之前):

    if (index == numStrings)
        numStrings *= 2,
        string_array = realloc(string_array, numStrings * sizeof*string_array);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 2013-07-01
    相关资源
    最近更新 更多