zoukankan      html  css  js  c++  java
  • unix环境高级编程中的err_quit,err_sys用到的知识点

    unix环境高级编程中的err_quit,err_sys

    环境

    os CentOS release 6.7 (Final)
    gcc 4.4.7

    c语言预备知识

    标准输入输出文件

    在linux系统中一切设备皆文件.文件在C语言中用指针来标识.C语言定义的3个标准文件如下所示

    标准文件 文件指针 对应设备
    标准输入 stdin 键盘
    标准输出 stdout 显示器
    标准错误 stderr 显示器

    下面看2个与标准输入输出有关的函数

    • char *gets(char *s) 从标准输入stdin中读取一行到s指向的缓冲区,当遇到行结束符或者EOF时读取结束.
    • int puts(const char *s) 把s和换行符写入stdout
      看下面的代码
    #include <stdio.h>
    #include <string.h>
    int main( ) {
        char str[100];
        printf( "Enter a value :");
        gets(str);
        printf("%zu", strlen(str)); // %zu用于输出size_t,str不包括最后的回车,所以输入abc回车,这里输出为3
        printf( "
    You entered: ");
        puts(str); //当输入为abc时,这里不但输出abc还多输入一个回车.
        printf("aaa");
        return 0;
    }
    

    再看另外一组与标准输入输出有关的函数:

    • int scanf(const char *format, ...) 从标准输入stdin中按读取内容,
    • int printf(const char *format, ...) 把内容按format指定的格式写入准备输出

    flush

    看下面的代码

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    
    int main() {
        char buff[1024];
        memset(buff, '', sizeof(buff));
    
        fprintf(stdout, "Going to set full buffering on
    ");
        setvbuf(stdout, buff, _IOFBF, 1024);
    
        fprintf(stdout, "This is tutorialspoint.com
    ");
        fprintf(stdout, "This output will go into buff
    ");
        fflush(stdout);
    
        fprintf(stdout, "and this will appear when programm
    ");
        fprintf(stdout, "will come after sleeping 5 seconds
    ");
    
        sleep(5);
    
        return(0);
    }
    

    setvbuf的作用是当缓冲区buff满的时候才会写出到输出流.一直到fprintf(stdout, "This output will go into buff ");这句话缓冲区还没有满,如果程序没有结束或者没有fflush,在显示器上可能看不到前3句的输了(或者输出不完整).调用fflush则一定能看到前3句完整的输出.最后2句话后面没有fflush函数,则不会立刻看到输出.当sleep(5)结束的时候,就能看到最后2句话输出了.

    函数变长参数问题

    当传入参数个数不确定时可以用变长参数.不确定的参数用...表示.最常用的变长参数函数应该就是scanf和printf了.获取变长参数的参要用到C语言定义的宏,va_start,va_arg,and va_end.这些宏在头文件stdarg.h中定义.va_start初始化变长参数的列表,va_arg在变长参数的列表中区获取下一个参数,va_end清空变长参数的列表.看下面的代码如何求和

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #define END -1
    int va_sum (int first_num, ...) {
        va_list ap;
        va_start(ap, first_num); //first_num后面的参数是变长参数
        int result = first_num;
        int temp = 0;
        while ((temp = va_arg(ap, int)) != END) {
            result += temp;
        }
        va_end(ap);
        return result;
    }
    int main () {
        int sum_val = va_sum(1, 2, 3, 4, 5, END);
        printf ("%d", sum_val);
        return 0;
    }
    

    再看一个求平均值的代码:

    #include <stdarg.h>
    #include <stdio.h>
    
    double average (int num, ...) {
        va_list arguments;
        double sum = 0;
        va_start(arguments, num); //num后面的参数是变长参数
        for (int x = 0; x < num; x++ ) {
            sum += va_arg(arguments, double);
        }
        va_end(arguments);
        return sum / num;
    }
    
    int main() {
        printf("%f
    ", average(3, 12.2, 22.3, 4.5));
        printf("%f
    ", average(5, 3.3, 2.2, 1.1, 5.5, 3.3));
    }
    

    vsnprintf

    int vsnprintf (char * s, size_t n, const char * format, va_list arg )
    把va_list以格式format写到s中,前n位是有效的.

    • s 至少要n个字符,否则会有不可遇知的错误.
    • n 指定s的前n位置是有效的,后面的会被忽略.注意指定n时只能看到n-1个字符.最后一位是null
    • format 格式
    • 变长的参数列表
      看下面的例子:
    #include <stdarg.h>
    #include <stdio.h>
    void vout(char *string, char *fmt, ...);
    char fmt1 [] = "%s %s %s %s";
    int main() {
        char buf[100];
        vout(buf, fmt1, "Sat", "Sun", "Mon", "aaa");
        printf("The string is:%s
    ", buf);
        return 0;
    }
    void vout(char *buf, char *fmt, ...) {
        va_list arg_ptr;
        va_start(arg_ptr, fmt); //让arg_ptr指向变长参数
        int n = vsnprintf(buf, 16, fmt, arg_ptr); //变长参数以fmt格式放到buf中,返回写入buf的字节数,但是只有前12个字节会输出.
        printf("n=%d
    ", n);
        va_end(arg_ptr);
    }
    

    再看一个例子

    #include <stdio.h>
    #include <stdarg.h>
    int mon_log(char* format, ...) {
        char str_tmp[50];
        int i=0;
        va_list vArgList;
        va_start(vArgList, format);
        i = vsnprintf(str_tmp, 50, format, vArgList);
        printf("%s
    ", str_tmp);
        va_end(vArgList);
        return i;
    }
    int main() {
        int i=mon_log("%s,%d,%d,%d","asd",2, 3, 4);
        printf("%d
    ", i);
        return 0;
    }
    

    再看一个例子

    #include <stdarg.h>
    #include <stdio.h>
    void vout(char *string, char *fmt, ...);
    char fmt1 [] = "%s %s %s %s";
    int main() {
        char buf[100];
        vout(buf, fmt1, "Sat", "Sun", "Mon", "aaa");
        printf("The string is:%s
    ", buf);
        return 0;
    }
    void vout(char *buf, char *fmt, ...) {
        va_list arg_ptr;
        va_start(arg_ptr, fmt); //让arg_ptr指向变长参数
        int n = vsnprintf(buf, 16, fmt, arg_ptr); //变长参数以fmt格式放到buf中,返回写入buf的字节数,但是只有前12个字节会输出.
        printf("n=%d
    ", n);
        va_end(arg_ptr);
    }
    

    snprintf

    int snprintf(char * s, size_t n, const char * format, ... );
    和vsnprintf的作用差不多.不同是vsnprintf最后一个参数类型是va_list,这里是不定长参数.
    看下面代码

    #include <stdio.h>
    int main() {
        char str[10];
        int ret = snprintf(str, 5, "%s", "12345678");
        printf("%d
    ",ret);
        printf("%s
    ",str);
        return 0;
    }
    

    参考资料

  • 相关阅读:
    react 全局监听报错,监听白屏
    【Python】(八)Python中的set集合(每个人都是唯一的个体)
    【Python】(六)Python数据类型-列表和元组,九浅一深,用得到
    mybatis-spring多数据源配置
    自己动手实现springboot运行时新增/更新外部接口
    自己动手实现springboot运行时执行java源码(运行时编译、加载、注册bean、调用)
    自己动手实现java断点/单步调试(一)
    自己动手实现java断点/单步调试(二)
    Swift 模式下面LLDB 输出对象
    Understanding Swift’s value type thread safety
  • 原文地址:https://www.cnblogs.com/zhouyang209117/p/7476736.html
Copyright © 2011-2022 走看看