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( "\nYou 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, '\0', sizeof(buff));
fprintf(stdout, "Going to set full buffering on\n");
setvbuf(stdout, buff, _IOFBF, 1024);
fprintf(stdout, "This is tutorialspoint.com\n");
fprintf(stdout, "This output will go into buff\n");
fflush(stdout);
fprintf(stdout, "and this will appear when programm\n");
fprintf(stdout, "will come after sleeping 5 seconds\n");
sleep(5);
return(0);
}
setvbuf的作用是当缓冲区buff满的时候才会写出到输出流.一直到fprintf(stdout, "This output will go into buff\n");这句话缓冲区还没有满,如果程序没有结束或者没有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\n", average(3, 12.2, 22.3, 4.5));
printf("%f\n", 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\n", 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", 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\n", str_tmp);
va_end(vArgList);
return i;
}
int main() {
int i=mon_log("%s,%d,%d,%d","asd",2, 3, 4);
printf("%d\n", 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\n", 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", 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\n",ret);
printf("%s\n",str);
return 0;
}
参考资料
- C - Input & Output
- C library function - fflush()
- Lesson 17: Functions with Variable Argument Lists in C using va_list
- vsnprintf
unix环境高级编程中的err_quit,err_sys用到的知识点的更多相关文章
- UNIX环境高级编程--#include "apue.h"
apue.h头文件为作者自己编写而非系统自带,故需要自行添加! 第一:打开网站 http://www.apuebook.com/第二:选择合适的版本(一共有三个版本,根据书的版本选择)下载源码sour ...
- unix环境高级编程附录 B 通用代码
0.说明: 在测试 unix 环境高级编程中的代码时,需要一些作者事先写好的代码, 如: apue.h 包含某些标准系统头文件,定义许多常量及函数原型 还有两个作者自编的函数来对错误进行处理 1.ep ...
- multiple definition of `err_sys' 《UNIX环境高级编程》
本文地址:http://www.cnblogs.com/yhLinux/p/4079930.html 问题描述: [点击此处直接看解决方案] 在练习<UNIX环境高级编程>APUE程序清单 ...
- Unix环境高级编程第三版中实例代码如何在自己的linux上运行的问题
学习Linux已经有2个月了,最近被期末考试把进度耽误了,前几天把Unix环境高级编程看了两章,感觉对Linux的整体有了一些思路,今天尝试着对第一章涉及到的一个简单的交互式shell编译运行一下,结 ...
- apue.h头文件(UNIX环境高级编程)
在看UNIX环境高级编程是,碰到一个头文件"apue.h",搜一下别人的帖子,其实apue.h是作者自己写的一个文件,包含了常用的头文件,系统不自带.其中包含了常用的头文件,以及出 ...
- UNIX环境高级编程(第三版)关于apue.h的用法
UNIX环境高级编程(第三版)中的例子用到apue.h这个头文件,但是书里面写的地址已经不能访问. 经过一番查找之后,找到如下解决方案: 1.到www.apuebook.com上下载第2版的源码,也可 ...
- 关于UNIX/Linux下安装《UNIX环境高级编程》源代码的问题
<UNIX环境高级编程(第三版)>是一本广为人知的unix系统编程书籍. 但是,书中的代码示例,要想正确的编译运行,要先做好准备工作: 1.下载源代码 传送门:http://apueboo ...
- 【UNIX环境高级编程】文件I/O
[UNIX环境高级编程]文件I/O大多数文件I/O只需要5个函数: open.read.write.lseek以及close 不带缓冲的I/O: 每个read和write都调用内核中的一个系统调用 1 ...
- 《unix环境高级编程》学习笔记【原创】
本文基于unix环境高级编程的学习的笔记,写的比较简如有不对,欢迎指点. 简单的描述下面函数的功能改变ctr+c信号原本的作用终止程序,在按下中断键的时候输出一句话. while循环主要读取用户的输入 ...
随机推荐
- Netty处理器重要概念
1.Netty的处理器可以分为两类:入站处理器和出战处理器 2.入站处理器顶层是ChannelInboundHandler,出战处理器顶层是ChannelOutboundHandler 3.数据处理时 ...
- 多线程-等待(Wait)和通知(notify)
1.为了支撑多线程之间的协作,JDK提供了两个非常重要的线程接口:等待wait()方法和通知notify()方法. 这两个方法并不是在Thread类中的,而是输出在Object类.这意味着任何对象都可 ...
- Java类/接口的API
本章节收集的类/接口API有: Object类,枚举,包装类,接口Comparable,类Arrays,异常, Object类 public String toString(): [把一个对象的信息用 ...
- pat 1041 Be Unique(20 分)
1041 Be Unique(20 分) Being unique is so important to people on Mars that even their lottery is desig ...
- nyoj 311-完全背包 (动态规划, 完全背包)
311-完全背包 内存限制:64MB 时间限制:4000ms Special Judge: No accepted:5 submit:7 题目描述: 直接说题意,完全背包定义有N种物品和一个容量为V的 ...
- Python3.7.1学习(五) 将列表中的元素转化为数字并排序
# 本文实例讲述了Python中列表元素转为数字的方法.分享给大家供大家参考,具体如下: # 有一个数字字符的列表: numbers = ['2', '4', '1', '3']print(numbe ...
- 学习记录:《C++设计模式——李建忠主讲》6.“状态变化”模式
状态变化模式:在组件构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定.状态变化模式为这一问题提供了一种解决方案. 典型模式:状态模式(State).备忘录 ...
- PHP中的服务容器与依赖注入的思想
依赖注入 当A类需要依赖于B类,也就是说需要在A类中实例化B类的对象来使用时候,如果B类中的功能发生改变,也会导致A类中使用B类的地方也要跟着修改,导致A类与B类高耦合.这个时候解决方式是,A类应该去 ...
- JS三座大山再学习(三、异步和单线程)
本文已发布在西瓜君的个人博客,原文传送门 前言 写这一篇的时候,西瓜君查阅了很多资料和文章,但是相当多的文章写的都很简单,甚至互相之间有矛盾,这让我很困扰:同时也让我坚定了要写出一篇好的关于JS异步. ...
- Solr搜索引擎【索引管理】
一.索引存储 当文档提交到索引之后,directory目录组件会将它们写入到持久化存储器.Solr的目录组件具有以下重要特点: 1.隐藏持久存储的读写细节,例如,将文档写入到磁盘或通过JDBC在数据库 ...