我对使用 stdin
的 fgets
读取输入相对较新,我正在尝试阅读 int max_length = 50;
char lines[max_length][max_length];
char current_line[max_length];
int idx = 0;
while(fgets(current_line, max_length, stdin) != NULL) {
strcopy(lines[idx], current_line);
idx++;
}
的输入。
首先,我考虑阅读最多50行,每行最多50个字符,并且有类似的内容:
lines
上面的代码片段成功读取输入并将其存储到{{1}}数组中,我可以对其进行排序和打印。
我的问题是如何处理未知数量的行,每行都有未知数量的字符? (请记住,我必须对线条进行排序并打印出来)。
答案 0 :(得分:1)
查看找到here的GetString函数。
答案 1 :(得分:1)
虽然已经回答了这个问题的许多不同变体,但是如何解决这个问题可以使用一个段落。遇到这个问题时,无论您使用哪种库或POSIX函数组合,方法都是相同的。
基本上,您将动态分配合理数量的字符来保存每一行。 POSIX getline
将自动为您执行此操作,使用fgets
您只需读取一个充满字符的固定缓冲区并附加它们(根据需要重新分配存储),直到读取'\n'
字符(或已达到EOF
如果使用getline
,则必须为其分配内存,并复制已填充的缓冲区。否则,您将在每次读取新行时覆盖以前的行,当您尝试free
每一行时,您可能会反复尝试释放双重免费或损坏的SegFault相同的记忆块。
您可以使用strdup
简单地复制缓冲区。但是,由于strdup
分配了存储空间,因此在将指向新内存块的指针指向行集合之前,应验证成功分配。
要访问每一行,您需要一个指向每行开头的指针(每行的内存块)。通常使用指向char 指针的指针。 (例如char **lines;
)内存分配通常通过分配一些合理数量的指针来开始处理,跟踪你使用的数字,当你达到你分配的数字时,你realloc
和双指针的数量。
与每次阅读一样,您需要 验证 每次内存分配。 (每个malloc
,calloc
或realloc
)您还需要通过内存错误检查程序(例如{{}运行程序来验证程序使用您分配的内存的方式。 1}} for Linux)。它们易于使用,仅valgrind
。
将这些部分组合在一起,您可以执行与以下类似的操作。以下代码将读取作为程序的第一个参数提供的文件名中的所有行(如果未提供参数,则默认从valgrind yourexename
读取)并将行号和行打印到stdin
(保留该行)记住,如果你在50,000行文件上运行它)
stdout
如果您没有#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NPTR 8
int main (int argc, char **argv) {
size_t ndx = 0, /* line index */
nptrs = NPTR, /* initial number of pointers */
n = 0; /* line alloc size (0, getline decides) */
ssize_t nchr = 0; /* return (no. of chars read by getline) */
char *line = NULL, /* buffer to read each line */
**lines = NULL; /* pointer to pointer to each line */
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;
}
/* allocate/validate initial 'nptrs' pointers */
if (!(lines = calloc (nptrs, sizeof *lines))) {
fprintf (stderr, "error: memory exhausted - lines.\n");
return 1;
}
/* read each line with POSIX getline */
while ((nchr = getline (&line, &n, fp)) != -1) {
if (nchr && line[nchr - 1] == '\n') /* check trailing '\n' */
line[--nchr] = 0; /* overwrite with nul-char */
char *buf = strdup (line); /* allocate/copy line */
if (!buf) { /* strdup allocates, so validate */
fprintf (stderr, "error: strdup allocation failed.\n");
break;
}
lines[ndx++] = buf; /* assign start address for buf to lines */
if (ndx == nptrs) { /* if pointer limit reached, realloc */
/* always realloc to temporary pointer, to validate success */
void *tmp = realloc (lines, sizeof *lines * nptrs * 2);
if (!tmp) { /* if realloc fails, bail with lines intact */
fprintf (stderr, "read_input: memory exhausted - realloc.\n");
break;
}
lines = tmp; /* assign reallocted block to lines */
/* zero all new memory (optional) */
memset (lines + nptrs, 0, nptrs * sizeof *lines);
nptrs *= 2; /* increment number of allocated pointers */
}
}
free (line); /* free memory allocated by getline */
if (fp != stdin) fclose (fp); /* close file if not stdin */
for (size_t i = 0; i < ndx; i++) {
printf ("line[%3zu] : %s\n", i, lines[i]);
free (lines[i]); /* free memory for each line */
}
free (lines); /* free pointers */
return 0;
}
或getline
,则可以轻松实现每项。网站上有多个例子。如果找不到,请告诉我。如果您还有其他问题,请与我联系。