我需要创建一个数组I,其中列数组是固定大小,行数组是动态分配的(使用malloc
)。
我查看了其他similar questions,他们要么修复整个事物,要么动态分配。你怎么能两个都做?
char A[malloc][100];
我的猜测是:
char *A[100];
答案 0 :(得分:2)
继续我的评论之后,您可以静态声明一个指针数组,然后为从文件中读取的每一行动态分配存储空间。以下是显示此方法的简短示例。您必须保留读取行数的索引或计数器,以防止写入指针数组的末尾。
注意下面xcalloc
只是calloc
的包装器,它为每一行分配空间并进行错误检查。下面的分配是长期的(注意:您可以用注释中指示的strdup
替换长路)完整的allocate / validate / nul-terminate分配方法如下所示,例如/说明。
您可以通过更改#define MAXL
值来更改声明的指针数,并通过更改#define MAXC
值来调整每行的最大字符数。查看并了解每行的每个部分正在做什么。请注意使用静态缓冲区buf
,在分配内存之前读取初始行,并将内容分配给数组中的索引。这非常有用,因为它允许您在为其分配空间并将sting复制到新内存之前验证您已阅读的内容。它允许你跳过空行等,这比一个不需要的行释放/取消索引要简单得多:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 256 /* max chars per-line */
#define MAXL 100 /* initial num pointers */
void *xcalloc (size_t n, size_t s);
int main (int argc, char **argv) {
char *array[MAXL] = {NULL};
char buf[MAXC] = {0};
size_t i, idx = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (fgets (buf, MAXC, fp)) /* read all lines from fp into array */
{
size_t len = strlen (buf);
/* validate complete line read */
if (len + 1 == MAXC && buf[len - 1] != '\n')
fprintf (stderr, "warning: line[%zu] exceeded '%d' chars.\n",
idx, MAXC);
/* strip trailing '\r', '\n' */
while (len && (buf[len-1] == '\n' || buf[len-1] == '\r'))
buf[--len] = 0;
/* allocate & copy buf to array[idx], nul-terminate
* note: this can all be done with array[idx] = strdup (buf);
*/
array[idx] = xcalloc (len + 1, sizeof **array);
strncpy (array[idx], buf, len);
array[idx++][len] = 0;
/* MAXL limit check - if reached, break */
if (idx == MAXL) break;
}
if (fp != stdin) fclose (fp);
printf ("\n lines read from '%s'\n\n", argc > 1 ? argv[1] : "stdin");
for (i = 0; i < idx; i++)
printf (" line[%3zu] %s\n", i, array[i]);
for (i = 0; i < idx; i++)
free (array[i]); /* free each line */
return 0;
}
/* simple calloc with error checking */
void *xcalloc (size_t n, size_t s)
{
void *memptr = calloc (n, s);
if (memptr == 0) {
fprintf (stderr, "xcalloc() error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
return memptr;
}
<强>编译强>
gcc -Wall -Wextra -O3 -o bin/fgets_lines_stat_dyn fgets_lines_stat_dyn.c
使用/输出强>
$ ./bin/fgets_lines_stat_dyn dat/captnjack.txt
lines read from 'dat/captnjack.txt'
line[ 0] This is a tale
line[ 1] Of Captain Jack Sparrow
line[ 2] A Pirate So Brave
line[ 3] On the Seven Seas.
内存泄漏/错误检查
在你的动态分配内存的任何代码中,你有2个责任关于任何分配的内存块:(1)总是保留一个指向内存块起始地址的指针,所以,(2)它可以在释放时释放它不再需要了。您必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,并确认已释放已分配的所有内存。对于Linux valgrind
是正常的选择。有许多微妙的方法来滥用可能导致实际问题的内存块,没有理由不这样做。每个平台都有类似的记忆检查器。它们都很简单易用。只需通过它运行您的程序。
$ valgrind ./bin/fgets_lines_stat_dyn dat/captnjack.txt
==22770== Memcheck, a memory error detector
==22770== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==22770== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==22770== Command: ./bin/fgets_lines_dyn dat/captnjack.txt
==22770==
lines read from 'dat/captnjack.txt'
line[ 0] This is a tale
line[ 1] Of Captain Jack Sparrow
line[ 2] A Pirate So Brave
line[ 3] On the Seven Seas.
==22770==
==22770== HEAP SUMMARY:
==22770== in use at exit: 0 bytes in 0 blocks
==22770== total heap usage: 6 allocs, 6 frees, 1,156 bytes allocated
==22770==
==22770== All heap blocks were freed -- no leaks are possible
==22770==
==22770== For counts of detected and suppressed errors, rerun with: -v
==22770== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)