- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在编写一个程序,它接受用户提供的文件并继续读取它。但是,我也想使用尽可能少的内存,因此除非完全有必要,否则不想为数组分配 100000 个字符。这是我目前必须读取文件的代码。
char *read_input(const char *file)
{
int fd;
int read_stat;
int i;
char tmp[1000000];
char buffer[1];
i = 0;
if ((fd = open(file, O_RDONLY)) == -1)
printf("Error");
while ((read_stat = read(fd, buffer, 1)))
{
tmp[i++] = buffer[0];
if (i > 1000000)
printf("Error");
}
tmp[i] = '\0';
if (close(fd) == -1)
printf("Error");
return (ft_strdup(tmp));
}
有什么建议吗?
最佳答案
有几种方法可以解决这个问题。传统的方法是动态分配一个指针指向每一行,并为每一行分配内存。该方案非常简单。在 read_input
中分配一些初始数量的指针,连续读取每一行,为每一行分配存储空间并将内存块的地址分配给下一个可用指针,跟踪使用的指针数量,根据需要重新分配指针的数量,并在函数结束时最后一次调用 realloc
以调整分配给所需数量的指针数量。
当你消化这个方案时,它基本上分配的内存不会超过保存文件所需的内存(每行+一个指针)。它与读取包含未知长度行的未知大小文件的内存效率差不多。
话虽如此,read_input
需要做一些调整。通常,文件在调用函数(此处为 main()
)中打开,并将文件流指针(或文件描述符)作为参数传递给 read_input
。您还应该将指向 size_t
的指针作为第二个参数传递给 read_input
,并用 read_input
中读取的行数更新指针,以便值在调用者中可用。
(您还可以在末尾分配一个额外的指针作为哨兵 NULL
允许您确定读取的行数而无需将指针传递给 大小_t
)
您将从 read_input
返回一个指向 char 的指针(例如,char**
而不是 char*
) 使所有行对调用函数可用。
要处理文件操作,您可以自由使用文件描述符和低级 read
/write
函数,但 C 具有文件流函数可用于完成这项工作阅读/处理文本文件更容易一些。 (例如,使用 fgets
或 POSIX getline
进行读取,如下所示)
将所有这些放在一起,您可以执行类似下面的操作,它将读取作为第一个参数给出的文件(如果没有提供参数,则默认从 stdin
读取)。它将读取任意长度的任意大小的文件,直到到达文件末尾(除非内存在到达文件末尾之前耗尽)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXPTRS 32
char **read_input (FILE *fp, size_t *ndx)
{
size_t maxp = MAXPTRS, /* initial number of pointers */
n = 0; /* initial memory for line (0, getline decides) */
ssize_t nchr = 0; /* number of chars read by getline */
char *line = NULL, /* buffer to read each line */
**lines = NULL; /* pointer to pointer to all stored lines */
*ndx = 0; /* zero index pointer passed from caller */
if (!(lines = calloc (maxp, sizeof *lines))) { /* allocate pointers */
fprintf (stderr, "read_input: memory exhausted.\n");
return NULL;
}
/* read each line (into line) */
while ((nchr = getline (&line, &n, fp)) != -1) {
if (nchr && line[nchr - 1] == '\n') /* chk/trim trailing '\n' */
line[--nchr] = 0;
lines[*ndx] = strdup (line); /* duplicate line (belongs to getline) */
if (++(*ndx) == maxp) { /* check if reallocation of ptrs req'd */
void *tmp = realloc (lines, sizeof *lines * maxp * 2);
if (!tmp) { /* if realloc fails, bail */
fprintf (stderr, "read_input: memory exhausted - realloc.\n");
goto memlimit;
}
lines = tmp; /* assign reallocted block to lines */
/* zero all new memory (optional) */
memset (lines + maxp, 0, maxp * sizeof *lines);
maxp *= 2; /* increment number of allocated pointers */
}
}
/* final realloc to reduce to exact number of pointers */
void *tmp = realloc (lines, *ndx * sizeof *lines);
if (tmp)
lines = tmp;
if (*ndx == 0) { /* protect against realloc returning NULL or a */
free (lines); /* pointer suitable to be passed to free ambiguity */
lines = NULL;
}
memlimit:; /* label for goto */
free (line); /* free line (it belongs to getline) */
return lines;
}
int main (int argc, char **argv) {
size_t n = 0; /* number of lines read by read_input */
char **lines = NULL; /* ptr to ptr to char for lines returned */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* call read_input/validate return */
if (!(lines = read_input (fp, &n)) || n == 0) {
fprintf (stderr, "error: read_input failed.\n");
return 1;
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
for (size_t i = 0; i < n; i++) { /* iterate over each line */
printf ("line[%3zu] : %s\n", i, lines[i]);
free (lines[i]); /* free memory for line */
}
free (lines); /* free pointers */
return 0;
}
示例输入文件
$ cat ../dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.
示例使用/输出
$ ./bin/getline_read_input <../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.
内存使用/错误检查
您必须使用内存错误检查程序来确保您不会尝试写入超出/超出分配的内存块边界、尝试读取或基于未初始化值的条件跳转,最后,确认您释放了所有已分配的内存。
对于 Linux valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/getline_read_input <../dat/captnjack.txt
==20213== Memcheck, a memory error detector
==20213== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==20213== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==20213== Command: ./bin/getline_read_input
==20213==
line[ 0] : This is a tale
line[ 1] : Of Captain Jack Sparrow
line[ 2] : A Pirate So Brave
line[ 3] : On the Seven Seas.
==20213==
==20213== HEAP SUMMARY:
==20213== in use at exit: 0 bytes in 0 blocks
==20213== total heap usage: 7 allocs, 7 frees, 484 bytes allocated
==20213==
==20213== All heap blocks were freed -- no leaks are possible
==20213==
==20213== For counts of detected and suppressed errors, rerun with: -v
==20213== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放所有分配的内存并且没有内存错误。
检查一下,如果您还有其他问题,请告诉我。
关于c - 如何找出分配一个字符数组的空间大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46480902/
我有一个应用程序,它会抛出 GKSession 并在各种条件下(连接超时、 session 失败等)创建一个新的 GKSession。不过,我遇到了内存泄漏问题,并且有时会在重新连接几次循环后崩溃。
比如我在宿主代码中有一个浮点指针 float *p 是否可以确定他指向的内存类型(设备/主机)? 最佳答案 在 UVA system 中, 运行时 API 函数 cudaPointerGetAttri
我已将项目转换为 .Net 4.0 并且以下代码不起作用: typeof(RuntimeTypeHandle).GetMethod("Allocate", BindingFlags.Instance
当我声明 char ch = 'ab' 时,ch 只包含 'b',为什么它不存储 'a'? #include int main() { char ch = 'ab'; printf("%c"
我对 Disk Sector 和 Block 有疑问。扇区是一个单位,通常为 512 字节或 1k、2k、4k 等取决于硬件。文件系统 block 大小是一组扇区大小。 假设我正在存储一个 5KB 的
假设我有 8 个人和5000 个苹果。 我想将所有苹果分发给所有 8 个人,这样我就没有苹果了。 但每个人都应该得到不同数量 将它们全部分发出去的最佳方式是什么? 我是这样开始的: let peopl
我正在构建的网站顶部有一个搜索栏。与 Trello 或 Gmail 类似,我希望当用户按下“/”键时,他们的焦点就会转到该搜索框。 我的 JavaScript 看起来像这样: document.onk
我有一小段代码: if (PZ_APP.dom.isAnyDomElement($textInputs)){ $textInputs.on("focus", function(){
我观察到以下行为。 接受了两个属性变量。 @property (nonatomic, retain) NSString *stringOne; @property (nonatomic, assign
我正在解决这样的问题 - 实现一个计算由以下内容组成的表达式的函数以下操作数:“(”、“)”、“+”、“-”、“*”、“/”。中的每个数字表达式可能很大(与由字符串表示的一样大)1000 位)。 “/
我有一组主机和一组任务。 每个主机都有 cpu、mem 和任务容量,每个任务都有 cpu、mem 要求。 每个主机都属于一个延迟类别,并且可以与具有特定延迟值的其他主机通信。 每个任务可能需要以等于或
该程序的作用:从文件中读取一个包含 nrRows 行和 nrColomns 列的矩阵(二维数组)。矩阵的所有元素都是 [0,100) 之间的整数。程序必须重新排列矩阵内的所有元素,使每个元素等于其所在
世界!我有个问题。今天我尝试创建一个代码,它可以找到加泰罗尼亚语号码。但是在我的程序中可以是长数字。我找到了分子和分母。但我不能分割长数字!此外,只有标准库必须在此程序中使用。请帮帮我。这是我的代码
我确定我遗漏了一些明显的东西,但我想在 Objective C 中创建一个 NSInteger 指针的实例。 -(NSInteger*) getIntegerPointer{ NSInteger
这个问题在这里已经有了答案: Difference between self.ivar and ivar? (4 个答案) 关闭 9 年前。
我如何将 v[i] 分配给一系列整数(v 的类型是 vector )而无需最初填充 最佳答案 你的意思是将 std::vector 初始化为一系列整数? int i[] = {1, 2, 3, 4,
我想寻求分配方面的帮助....我把这个作业带到了学校......我必须编写程序来加载一个 G 矩阵和第二个 G 矩阵,并搜索第二个 G 矩阵以获取存在数第一个 G 矩阵的......但是,当我尝试运行
我必须管理资源。它基本上是一个唯一的编号,用于标识交换机中的第 2 层连接。可以有 16k 个这样的连接,因此每次用户希望配置连接时,他/她都需要分配一个唯一索引。同样,当用户希望删除连接时,资源(号
是否有任何通用的命名约定来区分已分配和未分配的字符串?我正在寻找的是希望类似于 us/s 来自 Making Wrong Code Look Wrong ,但我宁愿使用常见的东西也不愿自己动手。 最佳
我需要读取一个 .txt 文件并将文件中的每个单词分配到一个结构中,该结构从结构 vector 指向。我将在下面更好地解释。 感谢您的帮助。 我的程序只分配文件的第一个字... 我知道问题出在函数 i
我是一名优秀的程序员,十分优秀!