还请注意,当使用fgets(或任何面向行的输入函数)进行输入时,fgets 将读取并包含 '\n' 在每行读取的末尾。您应该执行 2 个额外的测试/操作。 (1) 您应该测试fgets 读取的最后一个字符实际上是'\n' 字符。如果不是,则表明您的输入已被fgets 截断,其长度为您在fgets 的第二个参数中指定的长度,并且该行的其他字符仍未读取。如果没有这个检查和一些处理超过指定宽度的行的方法,你接下来调用fgets 将读取 current 行的剩余字符作为你的 next 行输入。
(2) 您应该删除 fgets 包含的换行符,以防止您的字符串在末尾包含嵌入的 '\n' 字符。 (如果您只是从行中解析数字而不是将其存储为字符串,则可以通过几种不同的方式进行处理)。但是,对于一般情况,您使用strlen 来定位字符串的结尾,然后用nul-terminating 字符覆盖'\n'。
除上述之外,仅在读取一行数据后为array 中的每个单独指针分配内存可能更有意义,以防止代码中过度分配空间。由于您指定每个字符串的分配大小将为20,因此可以使用该大小的简单字符缓冲区来获取输入,并且在确认输入后,您可以在array 中为该行分配存储空间。包含检查和分配在input 中的函数的简短示例是:
#define MAXC 20 /* max chars per read */
...
void Input (int value, char **array)
{
int i = 0;
size_t len = 0;
char buf[MAXC] = {0};
while (i < value && fgets (buf, MAXC, stdin)) {
printf ("%d ----\n", i);
len = strlen (buf); /* get length */
if (len + 1 == MAXC && buf[len-1] != '\n') /* validate read */
fprintf (stderr, "warning: chars exceed MAXC, line[%d]\n", i);
else
buf[--len] = 0; /* strip '\n' */
printf ("%d ----\n", i);
array[i++] = strdup (buf); /* allocate/copy */
}
}
最后,为什么选择void作为函数类型?如果值成功读入数组,为什么不返回读入array 的值的数量,否则返回0。这至少可以指示您读取的成功或失败,并提供一种将分配的行数返回给调用函数的方法。
包含调整后分配、必要检查和有用返回类型的代码示例如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 20
void *salloc (int x)
{
char **pointer;
pointer = malloc (sizeof *pointer * x);
if (pointer == NULL)
exit(-1);
return pointer;
}
int input (int value, char **array)
{
int i = 0;
size_t len = 0;
char buf[MAXC] = {0};
while (i < value && fgets (buf, MAXC, stdin)) {
printf ("%d ----\n", i);
len = strlen (buf); /* get length */
if (len + 1 == MAXC && buf[len-1] != '\n') /* validate read */
fprintf (stderr, "warning: chars exceed MAXC, line[%d]\n", i);
else
buf[--len] = 0; /* strip '\n' */
printf ("%d ----\n", i);
array[i++] = strdup (buf); /* allocate/copy */
}
return i;
}
int main (int argc, char *argv[]) {
int i, nlines, value = argc > 1 ? atoi (argv[1]) : 2;
char **array;
array = salloc (value);
if (!(nlines = input (value, array))) /* validate input */
return 1;
for (i = 0; i < nlines; i++) /* print input */
printf (" array[%2d] : %s\n", i, array[i]);
for (i = 0; i < nlines; i++) /* free memory */
free (array[i]);
free (array);
return 0;
}
测试输入文件
以下是第 1 行(第 2 行)超过 S 20 个字符的测试输入文件:
$ cat dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.
示例输出
$ ./bin/readarray 10 <../dat/captnjack.txt
0 ----
0 ----
1 ----
warning: chars exceed MAXC, line[1]
1 ----
2 ----
2 ----
3 ----
3 ----
array[ 0] : This is a tale
array[ 1] : Of Captain Jack Spa
array[ 2] : rrow
array[ 3] : A Pirate So Brave
array[ 4] : On the Seven Seas.
不要忘记使用像valgrind 这样的内存错误检查程序来验证您分配的内存的使用情况,并确保在不再需要它时释放它。如果您有任何其他问题,请告诉我。