无论是从stdin读取还是从文件读取,过程基本相同。您可以使用 line-oriented 输入(fgets 或 getline)读取每一行,或者使用 character-oriented 输入(getchar、fgetc 等)。 (scanf 家族位于中间)。阅读lines时,一般来说最好的选择是line-oriented输入。
在将用户输入读入数组时,您有两种选择,要么声明一个静态指针数组并希望分配足够多的指针开始,要么动态根据需要分配指针数组和realloc 以保存所有输入。 (谁知道,用户可能会重定向文件以供阅读)。当您动态分配任何内容时,您有责任跟踪其使用情况,保留指向内存块原始起始地址的指针,并在不再需要内存时freeing 内存。 p>
以下是从stdin 获取输入并将其存储在动态分配的数组中的标准示例。有一个转折。该代码可以处理来自文件 或stdin 的输入。如果文件名作为第一个参数给出,那么它将读取文件,否则从标准输入读取。它希望用户提供所需的尽可能多的输入,然后在完成后按[ctrl+d]。 (手动生成EOF)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NMAX 128
int main (int argc, char **argv) {
char *ln = NULL; /* NULL forces getline to allocate */
size_t n = 0; /* initial ln size, getline decides */
ssize_t nchr = 0; /* number of chars actually read */
size_t idx = 0; /* array index counter */
size_t nmax = NMAX; /* check for reallocation */
char **array = NULL; /* array to hold lines read */
FILE *fp = NULL; /* file pointer to open file fn */
if (argc > 1) {
if (!(fp = fopen (argv[1], "r"))) {
fprintf (stderr, "error: file open failed for '%s'\n", argv[1]);
return 1;
}
}
else
fp = stdin;
/* allocate NMAX pointers to char* */
if (!(array = calloc (NMAX, sizeof *array))) {
fprintf (stderr, "error: memory allocation failed.");
return 1;
}
if (fp == stdin)
printf ("\nEnter information to store in array on each line, [ctrl+d] when done:\n\n");
/* read each line from file or stdin - dynamicallly allocated */
while ((nchr = getline (&ln, &n, fp)) != -1)
{
/* strip newline or carriage rtn */
while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
ln[--nchr] = 0;
array[idx] = strdup (ln); /* allocate/copy ln to array */
idx++; /* increment value at index */
if (idx == nmax) { /* if lines exceed nmax, reallocate */
char **tmp = realloc (array, nmax * 2 * sizeof *tmp);
if (!tmp) {
fprintf (stderr, "error: memory exhausted.\n");
break;
}
array = tmp;
nmax *= 2;
}
}
if (ln) free (ln); /* free memory allocated by getline */
if (fp != stdin) fclose (fp); /* close open file descriptor */
size_t i = 0;
/* print array */
printf ("\nThe lines in the file are:\n\n");
for (i = 0; i < idx; i++)
printf (" line[%3zu] : %s\n", i, array[i]);
/* free array */
for (i = 0; i < idx; i++)
free (array[i]);
free (array);
return 0;
}
示例/输出
$ ./bin/getline_readstdin_dyn
Enter information to store in array on each line, [ctrl+d] when done:
This is a line of input
This is another
and another
etc..
The lines in the file are:
line[ 0] : This is a line of input
line[ 1] : This is another
line[ 2] : and another
line[ 3] : etc..
或者从文件中读取:
$ ./bin/getline_readstdin_dyn dat/ll_replace_poem.txt
The lines in the file are:
line[ 0] : Eye have a spelling chequer,
line[ 1] : It came with my Pea Sea.
line[ 2] : It plane lee marks four my revue,
line[ 3] : Miss Steaks I can knot sea.
line[ 4] : Eye strike the quays and type a whirred,
line[ 5] : And weight four it two say,
line[ 6] : Weather eye am write oar wrong,
line[ 7] : It tells me straight aweigh.
line[ 8] : Eye ran this poem threw it,
line[ 9] : Your shore real glad two no.
line[ 10] : Its vary polished in its weigh.
line[ 11] : My chequer tolled me sew.
line[ 12] : A chequer is a bless thing,
line[ 13] : It freeze yew lodes of thyme.
line[ 14] : It helps me right all stiles of righting,
line[ 15] : And aides me when eye rime.
line[ 16] : Each frays come posed up on my screen,
line[ 17] : Eye trussed too bee a joule.
line[ 18] : The chequer pours over every word,
line[ 19] : Two cheque sum spelling rule.
重定向输入也很好。例如:
$ ./bin/getline_readstdin_dyn < dat/ll_replace_poem.txt