如何在C中编写过滤程序?

时间:2012-04-03 07:23:00

标签: c filter

由于UNIX具有所有那些精彩的类似过滤器的程序(例如grepsedtr等),因此在标准C中编写其中一个程序的最简单方法是什么?

通过过滤器,我的意思是一个程序,它读取标准输入,执行一些数据操作,然后将其写入标准输出。这在构造命令管道时很有用,每个命令都执行一些额外的数据操作,例如:

grep xyzzy input.file | tr '[A-Z]' '[a-z]' | sed 's/plugh/PLUGH/g'

(每个|管道符号将前一个命令的标准输出连接到下一个命令的标准输入,因此是管道隐喻。

假设我需要一个将所有大写字符转换为小写的字符。而且,是的,我意识到这个特定的问题可以通过UNIX来解决:

tr '[A-Z]' '[a-z]'

但这只是一个示例。

我真正想要的是做这种过滤器的最简单的标准C源代码。

4 个答案:

答案 0 :(得分:6)

您可以使用@hroptatyr所描述的getline,但您可以做一些更简单的事情:

#include <stdio.h>
#include <ctype.h>
int main(void) {
    int c;
    while ((c = getchar()) != EOF)
        putchar(tolower(c));
    return 0;
}

答案 1 :(得分:3)

在伪代码中:

do
  line = read(stdin);
  filter(line);
  print(line);
until no_more_lines

在实际代码中:

char *line = NULL;
size_t len = 0U;
ssize_t n;

while ((n = getline(&line, &len, stdin)) >= 0) {
        /* LINE is of length N, filter it */
        filter(line, n);
        /* print it */
        fputs(line, stdout);
}
free(line);

filter()看起来像:

static void filter(char *line, size_t length)
{
        while ((*line++ = tolower(*line)));
}

修改:不要忘记定义_POSIX_C_SOURCE >= 200809L_XOPEN_SOURCE >= 700。 不要忘记为stdio.h添加getline(),为ctype.h添加tolower()

答案 2 :(得分:3)

“过滤器”程序只是一个程序,它从标准输入流(stdin)读取并写入标准输出流(stdout)。在写入读取数据之前,数据通常以某种方式进行转换(如果您不进行任何转换或过滤,您基本上编写了一个cat程序,它只打印出给它的任何内容)。过滤器程序的强大之处在于它们不会决定输入来自何处或输出的位置。相反,由程序的调用者来提供输入/输出通道。

过滤程序的核心可能看起来像这样(您可以将其用作自己的过滤程序的模板):

#include <stdio.h>

int filter( FILE *input, FILE *output );

int main( void )
{
    const int retval = filter( stdin, stdout );
    fflush( stdout );
    return retval;
}

就是这样。实际工作由filter函数完成,该函数执行您想要的转换。例如,这是一个简单的程序,它从输入文件中读取字符,将它们转换为小写,然后将它们打印到输出文件中:

#include <stdio.h>
#include <ctype.h> /* for tolower */

int filter( FILE *input, FILE *output )
{
    while ( !feof( input ) ) {
        if ( ferror( input ) ) {
            return 1;
        }
        fputc( tolower( fgetc( input ) ), output );
    }
    return 0;
}

int main( void )
{
    const int retval = filter( stdin, stdout );
    fflush( stdout );
    return retval;
}

如果您编译并运行此程序,它只会坐在那里耐心地等待数据从标准输入文件stdin中读取。此文件通常绑定到控制台,这意味着您必须手动输入一些数据。但是,命令shell实现了一个名为pipes的功能,允许您将一个命令的输出传递给另一个命令的输入。这允许将多个程序组合成pipeline以形成强大的命令。

以下是我们如何使用我们的过滤器程序(假设您调用了生成的二进制文件lower):

$ echo Hello | lower
hello
$

由于我们的过滤程序没有定义要读取的数据的来源,我们可以将它与在stdout上产生输出的各种程序相结合。例如,以下是如何将整个文件作为小写(您可以在Windows机器上使用type):

$ cat myfile.txt
Hello, World!
This is a simple test.

$ cat myfile.txt | lower
hello, world!
this is a simple test.

$

答案 3 :(得分:-4)

L1:
 mov dx,081
 mov cx,1
 mov bx,0
 mov ax,03f00
 int 021
 cmp ax,0
 je L2
 cmp b[081],'a'
 jb L3
 cmp b[081],'z'
 ja L3
 sub b[081],020
L3:
 mov dx,081
 mov cx,1
 mov bx,1
 mov ax,04000
 int 021
 jmp L1
L2:
 mov ax,04c00
 int 021

; Example in A86 Assembler see eji.com for A86/D86