我问了这个yesterday,但我仍然遇到问题。我在C中编写了一个程序,它有一个处理可以通过文件指针传递给它的文件的函数。
void process_my_file(FILE *fptr, ...) {
/* do work */
}
我问如何从标准输入读取输入并将其传递给我的函数,我建议尝试使用stdin作为参数调用函数:
my_process_file(stdin, ...);
这样可行,但我真正想做的是从stdin读取直到遇到EOF,然后立即将所有输入传递给函数。将stdin作为参数传递的问题是,每次用户输入一行输入并按下“enter”时,程序就会过早地吐出相应的输出行。
我希望输入和输出能够清晰分离,这样只有在用户说出EOF(Control-d)后输出才会出现。
提前再次感谢。我是一个学习编程的新手,你的提示是一个很大的帮助。我非常感谢这个网站。
- 拉里
答案 0 :(得分:0)
你必须自己进行预缓冲,即读取stdin直到看到EOF,然后将一个长字符串(可能是\ n分隔线的常量)传递给你的函数。或者你的预缓冲读取例程可以分配一个指向分配行的char *数组。或者您的预缓冲例程将解析stdin并返回预处理的信息。取决于您想要对信息做什么。
答案 1 :(得分:0)
你现在拥有的是'filter'。过滤器是很棒的程序,但当然不适用于所有情况。无论如何,看看你是否可以让你的程序作为过滤器工作。
如果你真的必须在处理之前读取所有输入,你必须在某处保存输入,并且用FILE*
调用处理函数是没有意义的(FILE *中的所有数据都已经被读);你可以将所有输入读入一个char数组并将该数组传递给你的函数。
void process_data(char data[], size_t data_len) { /* do work */ }
答案 2 :(得分:0)
假设您要打开一个文件,然后将文件句柄传递给您的函数。您在函数中的代码仍然必须在该常规文件上读取EOF。此外,它必须处理分配足够的空间来存储文件,并处理短读取。
所有这些只是stdin必须处理的同一组问题 - 唯一可能的区别是来自终端的stdin会为每行输入提供简短的读取,而每次从管道读取都会给出你读管道缓冲区的大小(或原子写入小于缓冲区大小),普通磁盘文件通常只会给你一个文件的最后一个块的简短读取。由于您的函数无法提前知道需要多少空间(当然不是管道或终端输入),您必须准备好处理动态内存分配 - malloc()
和realloc()
。
另外,如果你的函数期望获取已经为它读取的数据,为什么它传递文件句柄(FILE指针)而不是字符缓冲区及其长度?当您需要函数使用它时,您可以将文件句柄传递给函数 - 从可读句柄读取,或写入可写句柄(如果句柄打开以进行读写,则只是偶尔)。 / p>
这是一个有效的示例程序。我必须找出一些需要将整个文件粘贴到内存中,处理它并发出一些答案的东西 - 所以我选择按字符对文件进行排序。中等无意义,但它演示了该怎么做。它还有一个操作变量参数错误报告功能。
玩得开心!
/*
* Demo code for StackOverflow question 1484693
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
static char *arg0;
static void error(const char *fmt, ...)
{
va_list args;
int errnum = errno; /* Catch errno before it changes */
fprintf(stderr, "%s: ", arg0);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
fputc('\n', stderr);
exit(1);
}
static int char_compare(const void *v1, const void *v2)
{
char c1 = *(const char *)v1;
char c2 = *(const char *)v2;
if (c1 < c2)
return -1;
else if (c1 > c2)
return +1;
else
return 0;
}
static void process_my_file(FILE *fp)
{
char *buffer;
size_t buflen = 1024;
size_t in_use = 0;
ssize_t nbytes;
if ((buffer = malloc(buflen)) == 0)
error("out of memory - malloc()");
while ((nbytes = fread(buffer + in_use, sizeof(char), buflen - in_use, fp)) > 0)
{
if (nbytes < 0)
error("error from fread()");
in_use += nbytes;
if (in_use >= buflen)
{
char *newbuf;
buflen += 1024;
if ((newbuf = realloc(buffer, buflen)) == 0)
error("out of memory - realloc()");
buffer = newbuf;
}
}
/* Consistency - number/size vs size/number! */
qsort(buffer, in_use, sizeof(char), char_compare);
fwrite(buffer, sizeof(char), in_use, stdout);
putchar('\n');
free(buffer);
}
int main(int argc, char **argv)
{
arg0 = argv[0];
if (argc > 1)
{
for (int i = 1; i < argc; i++)
{
FILE *fp;
if ((fp = fopen(argv[i], "r")) == 0)
error("failed to open file %s", argv[i]);
process_my_file(fp);
fclose(fp);
}
}
else
process_my_file(stdin);
return(0);
}
您可以使用一个或多个文件名作为参数来调用它;每个文件名都单独排序。你可以把东西塞进去;你可以从标准输入中读取它。
我选择忽略fwrite()
和fclose()
可能失败的可能性;我还选择忽略buflen
中process_my_file()
溢出的可能性。如果您愿意,可以查看它们。 (请注意,每个文件的输出包含比输入更多的换行符。)
读者练习: