zoukankan      html  css  js  c++  java
  • Linuc学习3-输入和输出重定向

    已打开的文件描述符在fork和exec调用后保留下来,我们可以利用对进程这方面知识点的理解来改变程序的行为。

    这个例子涉及一个过滤程序:它从标准输入读取数据,然后向标准输出写数据,同时在输入和输出之间对数据做些有用的转换。

    过滤程序upper.c

    #include<stdio.h>
    #include<stdlib.h>
    #include<ctype.h>
    int main()
    {
        int ch;
        while( EOF != (ch=getchar()))
        {
            putchar(toupper(ch));
        }
        exit(0);    
    
    }

    upper.c执行效果:

     

    如果我们利用shell从定向把一个文件的内容全部转为大写,如下所示:

    如果我们想在另一个程序中使用这个过滤程序会发生什么呢?下一个例子useupper.c接受一个文件名做命令行参数,若果对它调用不正确,他将会响应一个错误信息。

    #include<unistd.h>
    #include<stdio.h>
    #include<stdlib.h>
    int main(int argc,char *argv[])
    {
        char *filename;
        int i;
        if(argc != 2)
        {
            fprintf(stderr,"usage :useupper file
    ");
            exit(1);
        }
        filename = argv[1];
    //重新打开标准输入,并再次检查有无错误发生,然后用execl调用upper程序。
    for (i = 0;i<argc;i++) { printf("the argv[%d] is %s ",i,argv[i]); } if(!freopen(filename,"r",stdin)) { fprintf(stderr,"can't redirect stdin from file %s! ",filename); exit(2); } execl("./upper","upper",0); //execl会替换当前的进程。如果没有发生错误,剩下的语句不会执行。 perror("could not exec ./upper"); exit(3); }

    分析一下这个程序的流程:

    运行时我们应该给他提供一个文件,让他把文件的内容全部转换为大写。这项工作由upper程序完成,但它不会处理文件名参数。注意,我们不需要upper程序的源代码。我们可以利用这种方法

    运行任何可执行程序。

    useupper程序用freopen函数先关闭标准输入,然后将文件流stdin与程序参数给定的文件名关联起来。接下来,它调用execl用upper程序替换掉正在运行的进程代码。有hi那我IE已打开的文件描述符会在execl调用

    之后保留下来,所以upper程序的运行情况和他在shell提示符下运行情况完全一致。 

     ps:

    1.
    stdout(Standardoutput)标准输出
    stdin(Standardinput)标准输入
    stderr(Standarderror)标准错误

    2.int fprintf (FILE* stream, const char*format, [argument])

    FILE*stream:文件指针
    const char* format:输出格式
    argument  :附加参数列表
     
    作用:
    fprintf( )会根据参数format 字符串来转换并格式化数据, 然后将结果输出到参数stream 指定的文件中, 直到出现字符串结束('')为止。
     

    3.FILE *freopen(const char * restrict filename, const char * restrict mode, FILE * restrict stream);

    freopen是被包含于C标准库头文件<stdio.h>中的一个函数,用于重定向输入输出流。该函数可以在不改变代码原貌的情况下改变输入输出环境,但使用时应当保证流是可靠的。

    形参说明:

    filename:需要重定向到的文件名或文件路径。
    mode:代表文件访问权限的字符串。例如,"r"表示“只读访问”、"w"表示“只写访问”、"a"表示“追加写入”。
    stream:需要被重定向的文件流。
    返回值:如果成功,则返回该指向该输出流的文件指针,否则返回为NULL。

    4.perror()

    perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno(这里的说法不准确,errno是一个宏,该宏返回左值) 的值来决定要输出的字符串。
    在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用"某些"函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和现在的errno所对应的错误一起输出。

     

    以上内容来自《Linux程序设计第四版》PS部分来自百度百科

  • 相关阅读:
    OSI安全体系结构
    PHP 二维数组根据相同的值进行合并
    Java实现 LeetCode 17 电话号码的字母组合
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 14 最长公共前缀
  • 原文地址:https://www.cnblogs.com/xiaodeyao/p/6440615.html
Copyright © 2011-2022 走看看