C标准库
/**
* @file ctype_note.c
* @brief ctye.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-07
*/
/****************************************************************
* <ctype.h>用于字符的识别和转换
* ctype.h中的函数已经针对运行速度经过优化,大多函数都通过宏实现
* 这些函数的可移植性好,可以再任何字符集上运行
* 当地点发生改变,ctype.h中的函数会相应地调整其行为
****************************************************************/
#include <stdio.h>
#include <ctype.h>
/****************************************************************
* 识别字符函数
*
* 当且仅当参数c与函数描述一致时返回非零(真)
*
* 标准运动控制字符:换页、换行、回车、水平制表符,垂直制表符
* ('\f', '\n', '\r', '\t', '\v')
* isdigit 所有十进制数字,[0-9]
* isxdigit 十六进制数字,[0-9a-fA-F]
* islower 小写字母,[a-z]
* isupper 大写字母,[A-Z]
* isalpha 字母,isupper或者islower
* isalnum 字母或数字,isalpha或者isdigit
* isgraph 图形字符,除空格之外的所有打印字符
* isprint 打印字符,包括空格在内的所有可打印字符
* ispunct 除空格和所有isalnum之外的所有字符
* 如:!@#$%^&*;:'"<>=+-*[]\
* iscntrl 所有控制字符:5个标准的运动控制字符、退格符BS
* 和警报符BEL
* isspace 标准空白字符,5个标准运动控制字符和空格
****************************************************************/
/* extern int isdigit(int c); */
/* extern int isxdigit(int c); */
/* extern int islower(int c); */
/* extern int isupper(int c); */
/* extern int isalpha(int c); */
/* extern int isalnum(int c); */
/* extern int isgraph(int c); */
/* extern int isprint(int c); */
/* extern int ispunct(int c); */
/* extern int iscntrl(int c); */
/* extern int isspace(int c); */
/****************************************************************
* 识别字符函数
*
* tolower把大写字母c转换为小写,如果c不是大写字母,则返回原来值
* toupper把小写字母c转换为大写,如果c不是小写字母,则返回原来值
****************************************************************/
/* extern int tolower(int c); */
/* extern int toupper(int c); */
/****************************************************************
* 主函数
****************************************************************/
extern void ctype_main(void)
{
int c = '\t';
int lower = 'l';
int upper = 'U';
printf("=================================================\n");
printf(" ctype.h\n");
printf("=================================================\n");
printf("character c = %c:\n", c);
isdigit(c) ? printf("isdigit\n") : printf("!isdigit\n");
isxdigit(c) ? printf("isxdigit\n") : printf("!isxdigit\n");
isupper(c) ? printf("isupper\n") : printf("!isupper\n");
islower(c) ? printf("islower\n") : printf("!islower\n");
isalpha(c) ? printf("isalpha\n") : printf("!isalpha\n");
isalnum(c) ? printf("isalnum\n") : printf("!isalnum\n");
isgraph(c) ? printf("isgraph\n") : printf("!isgraph\n");
isprint(c) ? printf("isprint\n") : printf("!isprint\n");
ispunct(c) ? printf("ispunct\n") : printf("!ispunct\n");
iscntrl(c) ? printf("iscntrl\n") : printf("!iscntrl\n");
isspace(c) ? printf("isspace\n") : printf("!isspace\n");
printf("%c to upper is %c\n", lower, toupper(lower));
printf("%c to lower is %c\n", upper, toupper(upper));
printf("\n");
}
/**
* @file math_note.c
* @brief math.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-07
*/
/****************************************************************
* <math.h>常用的数学函数
* math.h处理错误的方式与其他库函数不同,当错误发生时,math.h中的
* 大多数函数会将一个错误编码存到errno变量中,该变量在errno.h中。
* 常见的错误有两种:
* 定义域错误,对应的错误编码EDOM
* 取值范围错误,对应的错误编码ERANGE
****************************************************************/
#include <stdio.h>
#include <math.h>
#define PI 3.1415927
#define E 2.71828183
/****************************************************************
* 三角函数
*
* 参数x为角度(弧度为单位)
* 角度和弧度的转换:R为弧度,A为角度
* R = PI * A / 180; A = 180 * R / PI
* cos和sin函数的返回值为[-1, 1]
****************************************************************/
/* extern double cos(double x); */
/* extern double sin(double x); */
/* extern double tan(double x); */
static double ator(double a)
{
return (PI * a / 180);
}
void tri_sample(void)
{
double a; /* 角度 */
double r; /* 弧度 */
double val; /* 三角函数值 */
printf("三角函数\n");
a = 60;
r = ator(a);
val = cos(r);
printf("cos %lg = %lg,对应角度为%lg\n", r, val, a);
a = 30;
r = ator(a);
val = sin(r);
printf("sin %lg = %lg,对应角度为%lg\n", r, val, a);
a = 45;
r = ator(a);
val = tan(r);
printf("tan %lg = %lg,对应角度为%lg\n", r, val, a);
printf("\n");
}
/****************************************************************
* 反三角函数
*
* acos和asin参数x在[-1, 1]范围内,否则发生定义域错误
* acos正常返回值在[0, PI]
* asin正常返回值在[-PI/2, PI/2]
* atan正常返回值在[-PI/2, PI/2]
* atan2返回y/x的反正切,返回值在[-PI, PI]
****************************************************************/
/* extern double acos(double x); */
/* extern double asin(double x); */
/* extern double atan(double x); */
/* extern double atan2(double y, double x); */
static double rtoa(double r)
{
return (180 * r / PI);
}
void anti_tri_sample(void)
{
double x;
double a;
double r;
printf("反三角函数\n");
x = 0.5;
r = acos(x);
a = rtoa(r);
printf("arccos %lg = %lg,对应角度为%lg\n", x, r, a);
x = 0.5;
r = asin(x);
a = rtoa(r);
printf("arcsin %lg = %lg,对应角度为%lg\n", x, r, a);
x = 1;
r = atan(x);
a = rtoa(r);
printf("arctan %lg = %lg,对应角度为%lg\n", x, r, a);
printf("\n");
}
/****************************************************************
* 双曲函数
*
* cosh(x) = [e^x + e^(-x)] / 2
* sinh(x) = [e^x - e^(-x)] / 2
* tanh(x) = sinh(x) / consh(x)
* = [e^x - e^(-x)] / [e^x + e^(-x)]
* 如果参数x的值太大,会发生值域错误
****************************************************************/
/* extern double cosh(double x); */
/* extern double sinh(double x); */
/* extern double tanh(double x); */
void hyp_sample(void)
{
double x = 0.7;
printf("双曲函数\n");
printf("cosh %lg = %lg\n", x, cosh(x));
printf("sinh %lg = %lg\n", x, sinh(x));
printf("tanh %lg = %lg\n", x, tanh(x));
printf("\n");
}
/****************************************************************
* 指数函数和对数函数
*
* exp(x) = e^x
* log(x)计算x的自然对数,参数为正数
* log10(x)计算以10为底的对数,参数为正数
****************************************************************/
/* extern double exp(double x); */
/* extern double log(double x); */
/* extern double log10(double x); */
void exp_sample(void)
{
double x;
printf("指数函数和对数函数\n");
x = 1;
printf("exp %lg = %lg\n", x, exp(x));
x = E;
printf("log %lg = %lg\n", x, log(x));
x = 10000;
printf("log10 %lg = %lg\n", x, log10(x));
printf("\n");
}
/****************************************************************
* 浮点数处理函数
*
* frexp把一个浮点数规格化为一个小数和一个2的整数次幂
* value = frexp(value, exp) * (2 ^ (*exp))
* frexp的返回值为[1/2, 1)
*
* ldexp计算一个浮点数和2的整数次幂的乘积,与frexp相对
* ldexp(x, exp) = x * (2 ^ exp)
*
* modf把一个浮点数value分为整数部分*iptr和小数部分modf(value, iptr)
* value = *iptr + modf(value, iptr)
****************************************************************/
/* extern double frexp(double value, int *exp); */
/* extern double ldexp(double x, int exp); */
/* extern double modf(double value, double *iptr); */
void flo_sample(void)
{
double unnnum; /* 非规格浮点数,unnormalized number */
double nornum; /* 0.5~1的浮点数,normalized number */
int n; /* 2的次幂 */
double fval; /* 浮点数 */
double intpart; /* 整数部分,integer part */
double frapart; /* 小数部分,fractional part */
printf("浮点数函数\n");
unnnum = 5.0;
nornum = frexp(unnnum, &n);
printf("frexp %lg = %lg,n = %d\n", unnnum, nornum, n);
printf(" %lg = %lg * (2 ^ %d)\n", unnnum, nornum, n);
nornum = 0.7;
n = 4;
unnnum = ldexp(nornum, n);
printf("ldexp (%lg, %d) = %lg\n", nornum, n, unnnum);
printf(" %lg = %lg * (2 ^ %d)\n", unnnum, nornum, n);
fval = -123.456;
frapart = modf(fval, &intpart);
printf("modf %lg = %lg,intpart = %lg\n", fval, frapart, intpart);
printf(" %lg整数部分%lg,小数部分%lg\n", fval, frapart, intpart);
printf("\n");
}
/****************************************************************
* 幂函数
*
* pow(x, y) = x ^ y
* x < 0 并且y不是一个整数时,发生定义域错误
* x = 0 并且 y <= 0 时,其结果不能表示
*
* sqrt(x) = x ^ 0.5,返回x的平方根,参数x为非负数
****************************************************************/
/* extern double pow(double x, double y); */
/* extern double sqrt(double x); */
void pow_sample(void)
{
double x = 4.0;
double y = 3.0;
printf("幂函数\n");
printf("pow (%lg, %lg) = %lg\n", x, y, pow(x, y));
printf("sqrt %lg = %lg\n", x, sqrt(x));
printf("\n");
}
/****************************************************************
* 其他浮点处理函数
*
* ceil计算不小于x的最小整数
* floor计算不大于x的最小整数
* fabs计算x的绝对值
* fmod计算x/y的浮点余数
****************************************************************/
/* extern double ceil(double x); */
/* extern double floor(double x); */
/* extern double fabs(double x); */
/* extern double fmod(double x, double y); */
void oth_sample(void)
{
double x = -17.6;
double y = 6.0;
printf("其他浮点处理函数\n");
printf("ceil %lg = %lg\n", x, ceil(x));
printf("floor %lg = %lg\n", x, floor(x));
printf("fabs %lg = %lg\n", x, fabs(x));
printf("fmod (%lg, %lg) = %lg\n", x, y, fmod(x, y));
printf("\n");
}
/****************************************************************
* 主函数
****************************************************************/
void math_main(void)
{
printf("=================================================\n");
printf(" math.h\n");
printf("=================================================\n");
tri_sample();
anti_tri_sample();
hyp_sample();
exp_sample();
flo_sample();
pow_sample();
oth_sample();
}
/**
* @file time_note.c
* @brief time.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-08
*/
/****************************************************************
* <time.h>日期和时间
****************************************************************/
#include <stdio.h>
#include <time.h>
/****************************************************************
* 类型和宏
*
* CLOCKS_PER_SEC 表达式clock()/CLOCKS_PER_SEC以秒为单位计算占用
* 处理器时间
* clock_t 函数clock的返回类型,可以是整型也可以是浮点型
* size_t sizeof运算返回的类型就是size_t,它是一个无符号
* 整数类型,unsigned int 或者 unsigned long
* time_t 函数time的返回类型,不能直接进行算术运算
* struct tm 它保存了一个日历时间(细分时间)的各个组成部分
****************************************************************/
/****************************************************************
* 时间操纵函数
*
* clock 返回程序使用处理器时间的最佳近似值
* difftime time1 - time0,返回以秒为单位的double类型的值
* mktime 把timeptr指向的tm结构体中的本地时间转换为一个
* size_t类型的日历时间值
* time 参数timer = NULL时,返回当前的日历时间值
* 参数timer不为空时,返回值赋给timer指定的对象
*
* time上是返回1970年1月1日00:00:00到当前时间的秒数
* 如果要进行效率分析,用clock函数比time函数精确
****************************************************************/
/* extern clock_t clock(void); */
/* extern double difftime(time_t time1, time_t time0); */
/* extern time_t mktime(struct tm *timeptr); */
/* extern time_t time(time_t *timer); */
/****************************************************************
* 时间转换函数
*
* asctime 把timeptr指向的结构转换为固定格式的字符串
* ctime 把timer指向的日历时间值转换为串形式的本地时间
* 等价于asctime(localtime(timer))
* gmtime 把timer指向的日历时间值转换为以UTC表示的细分时间
* localtime 把timer指向的日历时间值转换为以本地时间表示的细分
* 时间
* strftime 把timeptr指向的细分时间格式化为format的形式保存到
* s数组中,maxsize为s的最大长度
* format的格式中:
* "%y" 不带世纪的年份(00~99)
* "%Y" 带世纪的年份
* "%m" 月份(01~12)
* "%b" 缩写的月份名
* "%B" 完整的月份名
* "%d" 当月的第几天(01~31)
* "%j" 当年的第几天(001~366)
* "%U" 当年的第几周,每星期从星期日开始(00~53)
* "%W" 当年的第几周,每星期从星期一开始(00~53)
* "%w" 星期(0~6),星期日表示为0
* "%a" 缩写的星期名
* "%A" 完整的星期名
* "%H" 24小时制的小时(00~23)
* "%I" 12小时制的小时(01~12)
* "%M" 分钟(00~59)
* "%S" 秒(00~59)
* "%z" 时区名字或者时区缩写
* "%x" 区域设置的适当的日期
* "%X" 区域设置的适当的时间
* "%c" 区域设置的适当的日期和时间
****************************************************************/
/* extern char *asctime(const struct tm *timeptr); */
/* extern char *ctime(const time_t *timer); */
/* extern struct tm *gmtime(const time_t *timer); */
/* extern struct tm *localtime(const time_t *timer); */
/* extern size_t strftime(char *s, size_t maxsize, */
/* const char *format, const struct tm *timeptr); */
/****************************************************************
* 主函数
****************************************************************/
void time_main(void)
{
clock_t time_start; /* 程序开始时间 */
clock_t time_end; /* 程序结束时间 */
int running_time; /* 程序运行时间 */
int running_seconds; /* 程序运行秒数 */
time_t time1, time0; /* difftime函数参数 */
time_t t; /* timer指向的值 */
time_t *timer = &t; /* ctime,gmtime, localtime的参数 */
char timestr[100]; /* strtime的参数 */
int i; /* 延时的循环变量 */
printf("=================================================\n");
printf(" time.h\n");
printf("=================================================\n");
time_start = clock(); /* 开始时间 */
time0 = time(timer);
printf("本地时间ctime: %s\n", ctime(timer));
printf("UTC时间asctime(gmtime()):%s\n",
asctime(gmtime(timer)));
strftime(timestr, 100, "%Y年%m月%d日 %H:%M:%S\n",
localtime(timer));
printf("自定义时间格式strftime: %s\n", timestr);
printf("延时...\n");
for(i = 0; i < 1000000000; i++); /* 延时 */
time1 = time(NULL);
printf("time1: %lf, time0: %lf\n",
(double)time1, (double)time0);
printf("difftime(time1, time0): %lf\n",
difftime(time1, time0));
time_end = clock(); /* 结束时间 */
running_time = (int)time_end - (int)time_start;
running_seconds = running_time / CLOCKS_PER_SEC;
printf("time_start: %d, time_end: %d, running_time: %d\n",
(int)time_start, (int)time_end, running_time);
printf("CLOCKS_PER_SEC: %d, running_seconds: %d\n",
(int)CLOCKS_PER_SEC, running_seconds);
printf("\n");
}
/**
* @file string_note.c
* @brief string.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-11
*/
/****************************************************************
* <string.h>串处理,3种形式的串
* 1.名字以mem开头的函数对任意字符序列进行操作
* 可以操作结构体等
* 2.名字以str开头的函数对字符串进行操作
* 操作遇到'\0'停止,可能发生越界错误
* 3.名字以strn开头的函数对字符串序列操作
* 参数n限制操作的最大范围,因此比以str开头的函数更安全
****************************************************************/
#include <stdio.h>
#include <string.h>
/****************************************************************
* 复制函数
* memcpy 从s2指向的对象复制n个字符到s1指向的对象中
* 如果对象之间有重叠,这种行为未定义
* memmove 从s2指向的对象中复制n个字符到s1指向的对象中
* strcpy 把s2指向的串(包括'\0')复制到s1指向的数组
* 如果对象之间有重叠,这种行为未定义,返回s1
* strncpy 从s2指向的数组中复制最多n个字符到s1指向的数组中
* 如果对象之间有重叠,这种行为未定义,返回s1
****************************************************************/
/* extern void *memcpy(void *s1, const void *s2, size_t n); */
/* extern void *memmove(void *s1, const void *s2, size_t n); */
/* extern char *strcpy(char *s1, const char *s2); */
/* extern char *strncpy(char *s1, const char *s2, size_t n); */
/****************************************************************
* 拼接函数
*
* strcat 把s2指向的串的添加到s1指向的串的末尾
* 如果对象之间有重叠,这种行为未定义,返回s1
* strncat 从s2指向的数组中将最多n个字符添加到s1的末尾
* 如果对象之间有重叠,这种行为未定义,返回s1
****************************************************************/
/* extern char *strcat(char *s1, const char *s2); */
/* extern char *strncat(char *s1, const char *s2, size_t n); */
/****************************************************************
* 比较函数
*
* memcmp 将s1指向的对象的前n个字节和s2指向的对象的前n个字节
* 进行比较,结构对象内部为对齐而填充的“空隙”内容是
* 不确定的
* strcmp 比较串s1和s2的大小,相等时返回0
* strcoll 比较串s1和s2的大小,比较时串都被解释为适合当前区域
* 设置的类别LC_COLLATE的形式
* strncmp 最多比较串s1和串s2的前n个字符
* strxfrm 将转换s2为另一种形式到s1
* 这种转换使得用strcmp比较转换后的字符串和用strcoll
* 比较转换前的字符串的返回值是一样的
****************************************************************/
/* extern int memcmp(const void *s1, const void *s2, size_t n); */
/* extern int strcmp(const char *s1, const char *s2); */
/* extern int strcoll(const char *s1, const char *s2); */
/* extern int strncmp(const char *s1, const char *s2, size_t n); */
/* extern size_t strxfrm(char *s1, const char *s2, size_t n); */
/****************************************************************
* 查找函数
*
* memchr 返回s指向的对象的前n个字符(每个字节解释为unsigned
* char)中字符c出现的位置,若没有返回空
* strchr 返回串s中字符c第一次出现的位置,若没有返回空
* strrchr 返回串s中字符c最后一次出现的位置,若没有返回空
* strpbrk 确定s2指向的串中的任意字符在s1指向的串中第一次出现
* 的位置
* strspn 计算s1指向的字符串中完全由是s2指向的串中字符组成的
* 最大初始段长度
* strcspn 计算s1指向的字符串中完全不是由s2指向的串中字符组成
* 的最大初始段长度
* strstr 确定s2指向的串的字符序列在s1指向的串中第一次出现的
* 位置
* strtok 连续调用strtok把s1指向的串分解为一系列记号,每个记
* 号都由s2指向的串的字符界定
****************************************************************/
/* extern void *memchr(const void *s, int c, size_t n); */
/* extern char *strchr(const char *s, int c); */
/* extern char *strrchr(const char *s, int c); */
/* extern char *strpbrk(const char *s1, const char *s2); */
/* extern size_t strspn(const char *s1, const char *s2); */
/* extern size_t strcspn(const char *s1, const char *s2); */
/* extern char *strstr(const char *s1, const char *s2); */
/* extern char *strtok(char *s1, const char *s2); */
/****************************************************************
* 其他函数
*
* memset 用c(转成unsigned char)的值填充s的前n个字节
* strerror 将errnum中的错误编号对应到一个错误信息串
* strlen 计算串s的长度,'\0'表示一个串的结束
****************************************************************/
/* extern void *memset(void *s, int c, size_t n); */
/* extern char *strerror(int errnum); */
/* extern size_t strlen(const char *s); */
/* 自定义结构体,在示例程序中使用 */
struct str_st
{
int i;
float f;
char c;
};
void st_print(char *name, struct str_st *s)
{
printf("%s: {c:%c, i:%i, f:%f}\n", name, s->c, s->i, s->f);
}
/****************************************************************
* 主函数
****************************************************************/
void string_main(void)
{
char s1[100];
const char *s2 = "hello world!";
const char *s3 = "hello ";
const char *s4 = "world!";
struct str_st st1 = {'a', 2, 123.456};
struct str_st st2;
printf("=================================================\n");
printf(" string.h\n");
printf("=================================================\n");
printf("s2: %s\n", s2);
printf("s3: %s\n", s3);
printf("s4: %s\n", s4);
printf("\n");
printf("memset(s1, 0, sizeof(s1))\n");
memset(s1, 0, sizeof(s1));
printf("s1: %s\n\n", s1);
printf("strncpy(s1, s2, 7)\n");
strncpy(s1, s2, 7);
printf("s1: %s\n\n", s1);
printf("strcpy(s1, s3)\n");
strcpy(s1, s3);
printf("s1: %s\n\n", s1);
printf("strcat(s1, s4)\n");
strcat(s1, s4);
printf("s1: %s\n\n", s1);
printf("strncat(s1, s4, 3)\n");
strncat(s1, s4, 3);
printf("s1: %s\n\n", s1);
printf("memcpy(s1, s4, strlen(s2) + 1)\n");
memcpy(s1, s2, strlen(s2) + 1);
printf("s1: %s\n\n", s1);
printf("strcmp(s1, s2): %d\n", strcmp(s1, s2));
printf("strcoll(s1, s4): %d\n", strcoll(s1, s4));
printf("strncmp(s1, s3, 6): %d\n", strncmp(s1, s3, 6));
printf("strncmp(s1, s3, 7): %d\n", strncmp(s1, s3, 7));
printf("memcmp(s1, s3, 6): %d\n", memcmp(s1, s3, 6));
printf("memcmp(s1, s3, 7): %d\n", memcmp(s1, s3, 7));
printf("\n");
printf("srtchr(s2, 'l'): %d\n", strchr(s2, 'l') - s2);
printf("srtrchr(s2, 'l'): %d\n", strrchr(s2, 'l') - s2);
printf("memchr(s2, 'l', 10): %d\n",
(char *)memchr(s2, 'l', 10) - s2);
printf("srtpbrk(s2, \"abcd\"): %d\n",
strpbrk(s2, "abcd") - s2);
printf("strspn(s2, \"hel\"): %d\n", strspn(s2, "hel"));
printf("strcspn(s2, \"orl\"): %d\n", strcspn(s2, "orl"));
printf("srtrchr(s2, \"llo\"): %d\n", strstr(s2, "llo") - s2);
printf("strlen(s2): %d\n", strlen(s2));
printf("strerror(0): %s\n", strerror(0));
printf("\n");
strcpy(s1, "192.168.0.1");
printf("s1: %s\n", s1);
printf("strtok(s1): ");
printf("%s ", strtok(s1, "."));
printf("%s ", strtok(NULL, "."));
printf("%s ", strtok(NULL, "."));
printf("%s\n", strtok(NULL, "."));
printf("\n");
st_print("st1", &st1);
st_print("st2", &st2);
printf("\n");
printf("memcpy(st2, st1, sizeof(struct str_st))\n");
memset(&st2, 0, sizeof(struct str_st));
st_print("st2", &st2);
printf("\n");
printf("memcpy(st2, st1, sizeof(struct str_st))\n");
memcpy(&st2, &st1, sizeof(struct str_st));
st_print("st2", &st2);
printf("\n");
printf("memcmp st1, st2: %d\n",
memcmp(&st1, &st2, sizeof(struct str_st)));
printf("\n");
}
/**
* @file stdlib_note.c
* @brief stdlib.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-12
*/
/****************************************************************
* <stdlib.h>是一个大杂烩,定义和声明了那些没有明显定义的宏和函数
****************************************************************/
#include <stdio.h>
#include <stdlib.h>
/****************************************************************
* 类型和宏
*
* size_t sizeof运算符返回的类型
* wchar_t 宽字节字符,如:L'x'的类型就是wchar_t
* div_t 函数div的返回值,包含商和余数的结构体
* 商和余数的类型都为int
* ldiv_t 函数ldiv的返回值,和div_t类似
* 商和余数的类型都为long int
* 现在的很多编译器int和long int都占4个字节
* 在这些编译器里,div_t和ldiv_t实际上是一样的
* EXIT_FAILURE exit的参数或者main函数的返回值,表示程序不成功终止
* EXIT_SUCCESS exit的参数或者main函数的返回值,表示程序成功终止
* MB_CUR_MAX 当前区域设置(类型为LC_CTYPE)指定的扩展字符集中多
* 字节字符的最大字节数目,该值小于MB_LEN_MAX
* RAND_MAX rand()函数返回的最大值,该值至少为32767
****************************************************************/
/****************************************************************
* 字符转换函数
*
* atoi 把nptr指向的字符串初始部分转换为int
* atol 把nptr指向的字符串初始部分转换为long int
* 有些编译器int和long int一样都占4个字节
* 此时,atol和atoi一样
* atof 把nptr指向的字符串初始部分转换为double
* strtod 把nptr指向的字符串初始部分转换为double
* 如果endptr != NULL,enptr存储最后串的指针
* double序列的期望形式是首先可选的正负号,然后是数字
* 序列(可能包括小数点),接着可能是可选的指数部分
* strtol 把nptr指向的字符串初始部分按base进制转换为long
* strtoul 把nptr指向的字符串初始部分转换为unsigned long
****************************************************************/
/* extern int atoi(const char *nptr); */
/* extern long int atol(const char *nptr); */
/* extern double atof(const char *nptr); */
/* extern double strtod(const char *nptr, char **endptr); */
/* extern long int strtol(const char *nptr, char **endptr, */
/* int base); */
/* extern unsigned long int strtoul(const char *nptr, */
/* char **endptr, int base); */
void to_sample(void)
{
char pc[20];
char **endptr = (char **)&pc;
char *pi = "123abc";
char *pl = "4294967296def";
char *pf = "123.456e-2ghi";
int i;
long int l;
printf("atoi(%s): %d\n", pi, atoi(pi));
printf("atol(%s): %ld\n", pl, atol(pl));
printf("atof(%s): %f\n", pf, atof(pf));
i = strtod(pi, endptr);
printf("strtod(%s, endptr): %d, endptr: %s\n", pi, i, *endptr);
l = strtol(pl, endptr, 10);
printf("strtol(%s, endptr, 10): %ld, endptr: %s\n",
pl, l, *endptr);
printf("strtol(\"0xff\", endptr, 16): %ld\n",
strtol("0xff", endptr, 16));
printf("\n");
}
/****************************************************************
* 伪随机序列产生函数
*
* rand 产生一个0~RAND_MAX之间的为随机数
* srand 设置rand()函数的种子,相同的种子产生相同的随机数
****************************************************************/
/* extern int rand(void); */
/* extern void srand(unsigned int seed); */
void rand_sample(void)
{
int i;
srand(10);
printf("rand: ");
for (i = 0; i < 10; i++)
{
printf("%d ", rand());
}
printf("\n\n");
}
/****************************************************************
* 内存管理函数
*
* 有些编译器需要include <malloc.h>
*
* calloc 为nmemb个对象的数组分配空间
* 每个元素的大小为size
* 分配空间的所有位都初始化为零
* malloc 为一个对象分配size大小的空间,初始值不确定
* realloc 重新分配空间,首先判断当前指针是否有足够的连续空间
* 如果有,扩大ptr指向的地址,返回ptr;如果空间不够,
* 按照size分配新空间,把原数据拷贝到新空间,返回重新
* 分配的地址空间
* 如果ptr为空,则realloc的行为与malloc相同
* 如果size为零,则ptr指向的空间将被释放
* free 释放ptr指向的空间
****************************************************************/
/* extern void *calloc(size_t nmemb, size_t size); */
/* extern void *malloc(size_t size); */
/* extern void *realloc(void *ptr, size_t size); */
/* extern void free(void *prt); */
void mal_sample(void)
{
int i;
int *pi = malloc(10 * sizeof(int));
printf("memory\n");
for (i = 0; i < 10; ++i)
{
pi[i] = i;
}
for (i = 0; i < 10; ++i)
{
printf("%d ", pi[i]);
}
printf("\n\n");
free(pi);
}
/****************************************************************
* 环境通信函数
*
* abort 使程序异常终止,或者捕获信号SIGABRT且信号处理程序
* 没有返回
* exit 使用程序执行正常终止
* 如果程序多次调用exit,这种行为未定义
* 首先调用atexit注册函数,按照他们注册的反序调用
* 然后清空所有打开的缓冲数据流,关闭所有打开的流,并
* 删除tmpfile函数创建的所有文件
* 最后控制权返回给宿主环境,返回status,不能返回给它
* 的调用者
* atexit 注册func函数,该函数在程序正常终止的时候被调用
* getenv 查看环境变量name的值
* system 把string指向的串传递给宿主环境
****************************************************************/
/* extern void abort(void); */
/* extern void exit(int status); */
/* extern int atexit(void (*func)(void)); */
/* extern char *getenv(const char *name); */
/* extern int system(const char *string); */
void func1(void)
{
printf("atexit function func1 is called\n");
}
void func2(void)
{
printf("atexit function func2 is called\n");
}
void env_sample(void)
{
atexit(func1);
atexit(func2);
printf("getenv(home): %s\n", getenv("home"));
printf("system()\n");
/* windows中dir表示显示当前目录,linux中对应命令为ls */
system("dir /d ");
printf("\n\n");
}
/****************************************************************
* 查找和排序函数
*
* bsearch 在数组base中查找元素key的位置
* nmemb为元素个数,size为每个元素的大小
* compar为比较函数
* qsort 对数组base排序
* nmemb为元素个数,size为每个元素的大小
* compar为比较函数
****************************************************************/
/* extern void *bsearch(const void *key, const void *base, */
/* size_t nmemb, size_t size, */
/* int (*compar)(const void *, const void *)); */
/* extern void qsort(void *base, size_t nmemb, size_t szie, */
/* int (*compar)(const void *, const void *)); */
int compar(const int *i1, const int *i2)
{
return *i1 - *i2;
}
void com_sample(void)
{
int i;
int iarray[] = {9, 3, 5, 7, 5, 8, 6, 2};
int key = 7;
int *pi;
printf("iarray: ");
for (i = 0; i < sizeof(iarray) / sizeof(int); ++i)
{
printf("%d ", iarray[i]);
}
printf("\n");
pi = bsearch(&key, iarray, sizeof(iarray) / sizeof(int),
sizeof(int), compar);
printf("key %d pos is %d\n", key, pi - iarray);
qsort(iarray, sizeof(iarray) / sizeof(int),
sizeof(int), compar);
printf("qsort iarray: ");
for (i = 0; i < sizeof(iarray) / sizeof(int); ++i)
{
printf("%d ", iarray[i]);
}
printf("\n\n");
}
/****************************************************************
* 整数算数
*
* abs 计算整数j的绝对值
* div 计算分子numer除以分母所得的商和余数
* div_t是一个包含商和余数的结构体
* labs 和abs类似,参数和返回值都是long int
* ldiv 和div相似,参数和返回值都是long int
****************************************************************/
/* extern int abs(int j); */
/* extern div_t div(int numer, int denom); */
/* extern long int labs(long int j); */
/* extern ldiv_t ldiv(long int numer, long int denom); */
void math_sample(void)
{
div_t dt = div(34, 11);
ldiv_t ldt = ldiv(34, 11);
printf("abs(-17): %d\n", abs(-17));
printf("labs(-17): %d\n", labs(-17));
printf("div(34, 11): quot %d, rem %d\n",
dt.quot, dt.rem);
printf("ldiv(34, 11): quot %ld, rem %ld\n",
ldt.quot, ldt.rem);
printf("\n");
}
/****************************************************************
* 多字节字符函数
*
* mblen 确定s指向的多字节字符中包含的字节数
* mbtowc 转换多字节字符为相应的宽字符
* 首先确定s包含的字节数,然后确定这个多字节字符对应
* 的wchar_t类型的值的编码,如果多字节字符有效且pwc不
* 为空,在pwc中存储编码,最多检测s中的n个字节
* 返回多字节字符包含的字节数
* wctomb 转换宽字符为相应的多字节字符
* 返回wchar的值对应的多字节字符包含的字节数
* mbstowcs 转换多字节序列为相应的编码序列
* wcstombs 转换多字节对应的编码序列成初始的多字节序列
****************************************************************/
/* extern int mblen(const char *s, size_t n); */
/* extern int mbtowc(wchar_t *pwc, const char *s, size_t n); */
/* extern int wctomb(char *s, wchar_t wchar); */
/* extern size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n); */
/* extern size_t wcstombs(char *s, const wchar_t *pwcs, size_t n); */
/****************************************************************
* 主函数
****************************************************************/
void stdlib_main(void)
{
printf("=================================================\n");
printf(" stdlib.h\n");
printf("=================================================\n");
to_sample();
rand_sample();
mal_sample();
env_sample();
com_sample();
math_sample();
}
/**
* @file stdio_note.c
* @brief stdio.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-13
*/
/****************************************************************
* <stdio.h>标准输入输出流
* 文本文件和二进制文件在UNIX系统中不区别对待,但是MS-DOS读取文本
* 文件时要丢弃每行后面的回车符,在UNIX系统中可以忽略fopen函数中的
* b模式,但如果要移植到其他系统,应正确编写fopen的模式
* 如果文本最后一行不是一整行,很多系统不能很好的处理他们,因为没
* 有结束符它们就不能表示行的概念。如果写入文本文件的最后一个字符
* 不是换行符,那么最后的不完整的文本行可能会丢失,或者自动补充完
* 整,再次读取文本就多了一个换行符,或者程序运行的时候会出问题,
* 因此要避免文本文件的最后一行不完整
****************************************************************/
#include <stdio.h>
#include <stdlib.h>
/****************************************************************
* 类型和宏
*
* FILE 对象类型,可以记录控制流需要的所有信息
* 包括它的文件定位符、指向相关缓冲的指针,
* 记录是否发生了读写错误的错误指示符和
* 记录文件是否结束的文件结束符
* fpos_t 对象类型,可以唯一指定文件中的每个位置所需要的信息
* _IOFBF setvbuf的mode参数,表示完全缓冲
* _IOLBF setvbuf的mode参数,表示行缓冲
* _IONBF setvbuf的mode参数,表示没有缓冲
* BUFSIZ setbuf使用缓冲的大小
* EOF 标志文件的结束,即一个流输入结束了
* FILENAME_MAX 定义存放任意文件名的字符缓冲区的长度
* FOPEN_MAX 程序至少可以同时打开的文件数
* L_tmpnam 定义了足够存放一个临时文件名的字符缓冲区的长度
* SEEK_CUR fseek的mode参数,表示当前文件定位
* SEEK_END fseek的mode参数,表示文件结束
* SEEK_SET freek的mode参数,表示文件开始
* TMP_MAX tmpnam函数可以生成单独文件名的最小数目
* stderr 标准错误数据流
* stdin 标准输入流
* stdout 标准输出流
****************************************************************/
/****************************************************************
* 文件访问和操作
*
* fopen 以mode的方式打开文件filename
* 参数mode字符串含义
* mode的值:[rwa][b][+],各个字符的含义如下:
* r 表示以只读方式打开文件,该文件必须存在
* w 表示以只写方式打开文件
* 若文件存在,截短文件长度至零
* 若文件不存在,则创建新文件
* a 表示以追加方式打开文件
* 若文件存在,写入的数据会被附加到文件尾部
* 若文件不存在,则创建新文件
* b 表示二进制文件,如果没有,表示文本文件
* + 表示可读写方式
* 例如:
* wb 表示以只写方式打开二进制文件
* 若文件存在,截短文件长度至零
* 若文件不存在,则创建新文件
* r+ 以可读写方式打开文本文件,该文件必须存在
* a+ 以追加方式打开可读写文本文件
* 若文件存在,写入的数据会被附加到文件尾部
* 若文件不存在,则创建新文件
* mode的可能只有:r, w, a, r+, w+, a+, rb, wb, ab,
* rb+, wb+, ab+, r+b, w+b, a+b
* 其中rb+和r+b,wb+和w+b,ab+和a+b含义一样
* 操作成功返回文件对象,失败返回空
* freopen 打开名filename文件,并把它和stream流关联在一起
* 首先尝试关闭和指定的流关联的任意文件,如果不能成功
* 关闭就忽略这一点
* 成功返回stream,失败返回空
* fclose stream指向的流被清空,并且和流相关联的文件也被关闭
* fflush 清除文件缓冲区,文件以写方式打开时将缓冲区内容写入
* setvbuf 设置流stream的缓冲区为buf,缓冲区的大小为size
* 缓冲的模式为mode,mode有3中取值:
* _IOFBF完全缓冲,_IOLBF行缓冲,_IONBF没有缓冲
* setbuf 设置流stream的缓冲区为buf,缓冲区的大小为BUFSIZ
* 缓冲的模式为_IOFBF,如果buf为空,模式为_IONBF
* remove 删除文件名为filename的文件
* 如果文件文件已打开,这种行为由具体实现定义
* 成功删除时返回0
* rename 给old文件重命名为new
* 如果文件new已存在,这种行为由具体实现定义
* 成功重命名时返回0
* tmpfile 以"wb+"的模式创建临时的二进制文件
* 如果不能创建返回空
* tmpnam 产生一个唯一的文件名
* 每次调用tmpnam都产生不同的文件名
* 如果参数s不为空,产生的文件名存放在s中,并返回s
* 如果s为空,产生的文件名存放在内部静态对象中,并返
* 回该对象的地址
****************************************************************/
/* extern FILE *fopen(const char *filename, const char *mode); */
/* extern FILE *freopen(const char *filename, */
/* const char *mode, FILE *stream); */
/* extern int fclose(FILE *stream); */
/* extern int setvbuf(FILE *stream, char *buf, */
/* int mode, size_t size); */
/* extern void setbuf(FILE *stream, char *buf); */
/* extern int fflush(FILE *stream); */
/* extern int remove(const char *filename); */
/* extern int rename(const char *old, const char *new); */
/* extern FILE *tmpfile(void); */
/* extern char *tmpnam(char *s); */
void ope_sample(void)
{
FILE *file;
char *old = "old_file.txt";
char *new = "new_file.txt";
printf("create file %s\n", old);
file = fopen(old, "w"); /* 创建old_file */
printf("close file %s\n", old);
fclose(file); /* 关闭old_file */
printf("remove file %s\n", new);
remove(new); /* 删除原来的new_file */
printf("rename %s to %s\n", old, new);
rename(old, new); /* 重命名old_file为new_file */
printf("create tmpfile %p\n", tmpfile());
printf("create tmpfile %p\n", tmpfile());
printf("tmpnam: %s\n", tmpnam(NULL));
printf("tmpnam: %s\n", tmpnam(NULL));
printf("tmpnam: %s\n", tmpnam(NULL));
printf("\n");
}
/****************************************************************
* 格式化输入输出
*
* fprintf 按照格式format将参数列表格式化输出到流文件stream中
* format参数为输出的格式
* 格式定义:%[flags][width][.prec][F|N|h|l]type
* 1.type 输出的类型
* d 有符号十进制整数
* i 有符号整数
* o 无符号八进制整数
* u 无符号十进制整数
* x 无符号十六进制整数,小写abcdef表示
* X 无符号十六进制整数,大写ABCDEF表示
* f 浮点数,[-]ddd.ddd
* e/E 指数形式浮点数,[-]d.ddde(+|-)dd
* g/G 用%f和%e表示中总位数最短的来表示浮点数
* c 单个字符
* s char类型字符串
* S wchar_t类型字符串
* % %本身
* p 显示一个指针
* n 相应的参数为一个整数指针,这个整数中记录了
* 存放已写字符的个数,不转换参数
* 2.flags 输出格式控制
* 无 右对齐,左边填充0和空格
* - 左对齐,右边填充空格
* + 在数字前面增加符号+或-
* 0 将输出的前面补上0,直到占满指定列宽
* 空格 输出值为正时加空格,为负时加负号
* # 当type为csdiu时没有影响
* type为oxX时,分别在数值前加"0","0x","0X"
* type为eEf时,总是使用小数点
* type为gG时,除了数值为0外,总是显示小数点
* 3.width 显示宽度控制
* n 宽度至少为n位,不够以空格填充
* 0n 宽度至少为n位,不够以0填充
* * 格式列表中,下一个参数还是width
* 4.prec 精度控制
* 无 按默认的精度显示
* 0 当type为eEf时,不显示小数点
* n 当type为eEf时,n为最大的小数位数
* type为其他时,n为显示的最大宽度
* * 格式列表中,下一个参数还是width
* 5.F|N|h|l
* F 远指针
* N 近指针
* h 短整数或单精度浮点数
* l 长整数或双精度浮点数
* 函数返回传送字符的数目,错误放回负值
* printf 格式化输出到标准输出,相当于:
* fprintf(stdout, format, ... )
* sprintf 格式化输出到字符串,和fprintf类似
* 只是输入出写入到一个字符数组中,而不是流文件中
* vfprintf 与fprintf等价,只是可变参数列表用arg代替
* vprintf 与printf等价,只是可变参数列表用arg代替
* vsprintf 与sprintf等价,只是可变参数列表用arg代替
* fscanf 按照格式format从流stream中格式化读取输入到参数列表
* format为输入的格式
* 格式说明符
* a/A 读浮点值(C99适用)
* c 读单个字符
* d 读十进制整数
* u 读无符号十进制整数
* i 读整数
* o 读八进制整数
* x 读十六进制整数
* e/f/g 有符号浮点数
* s 读字符串,即非空白字符序列
* [] 扫描字符集合
* p 读指针值
* n 不读取输入,相应的参数为一个整数指针
* 这个整数中记录了存放已写字符的个数
* % 读%
* 修饰符
* L/l 长度修饰(long)
* h 长度修饰(short)
* 数字 整型常数,指定输入数据所占宽度
* * 表示本输入项在读入后不赋值给相应变量
* 空白符
* 略去读取过程中一个或多个空白字符
* 非空白字符
* 略去与这个空白字符相同的字符
* 函数返回成功赋值的数据项数,读到文件末尾返回EOF
* scanf 从标准输入格式化读入,相当于:
* fscanf(stdin, format, ... )
* sscanf 从字符串格式化读入,和fscanf类似
* 只是输入出写入到一个字符数组中,而不是流文件中
****************************************************************/
/* extern int fprintf(FILE *stream, const char *format, ... ); */
/* extern int fscanf(FILE *stream, const char *format, ... ); */
/* extern int printf(const char *format, ... ); */
/* extern int scanf(const char *format, ... ); */
/* extern int sprintf(char *s, const char *format, ... ); */
/* extern int sscanf(const char *s, const char *format, ... ); */
/* extern int vfprintf(FILE *stream, const char *format, */
/* va_list arg); */
/* extern int vprintf(const char *format, va_list arg); */
/* extern int vsprintf(char *s, const char *format, */
/* va_list arg); */
void fmt_sample(void)
{
FILE *file;
char *filename = "new_file.txt";
int i1 = 10;
int i2 = 20;
int i3, i4;
file = fopen(filename, "w");
fprintf(file, "%d %d\n", i1, i2);
printf("fprintf %d %d to %s\n", i1, i2, filename);
fclose(file);
file = fopen(filename, "r");
fscanf(file, "%d %d", &i3, &i4);
printf("fscanf %d %d from %s\n", i3, i4, filename);
fclose(file);
}
/****************************************************************
* 字符输入输出
*
* fgetc 从流文件stream读取下一个字符
* 返回流文件中的下一个字符,文件结束或流错误返回EOF
* fgets 从流文件stream中读取最多n-1个字符到字符数组s中
* 读入换行符或者文件结束符EOF之后,不在读取其它字符
* 最后写入一个空字符
* fputc 将字符c写入流文件stream的文件定位符指定位置处
* fputs 把字符串s写入到流文件stream中,不写入结束的空字符
* getc 等价于fgetc
* getchar 从标准输入stdin读取下一个字符,相当于fgetc(stdin)
* gets 从标准输入读取一个字符串到s指向的字符数组中
* 遇到文件结束符或者换行符结束
* putc 等价于fputc
* putchar 将字符c写入到标准输出stdout,相当于fputc(c,stdout)
* puts 把s指向的串写到stdout,并在输出最后添加一个换行符
* ungetc 把指定字符c转换成unsigned char退回到stream流文件中
****************************************************************/
/* extern int fgetc(FILE *stream); */
/* extern char *fgets(char *s, int n, FILE *stream); */
/* extern int fputc(int c, FILE *stream); */
/* extern int fputs(const char *s, FILE *stream); */
/* extern int getc(FILE *stream); */
/* extern int getchar(void); */
/* extern char *gets(char *s); */
/* extern int putc(int c, FILE *stream); */
/* extern int putchar(int c); */
/* extern int puts(const char *s); */
/* extern int ungetc(int c, FILE *stream); */
void cio_sample(void)
{
int c;
fputs("get a character form stdin: ", stdout);
c = fgetc(stdin);
fputs("put a character to stdout: ", stdout);
fputc(c, stdout);
printf("\n");
getchar(); /* 读取换行符 */
printf("getchar: ");
c = getchar();
printf("putchar: ");
putchar(c);
printf("\n\n");
}
/****************************************************************
* 直接输入输出
*
* fread 从流stream中读取最多nmemb个size大小的元素到ptr中
* 返回成功读取的元素个数
* fwrite 从ptr中读取最多nmemb个size大小的元素写入到stream中
* 返回成功写入的元素个数
****************************************************************/
/* extern size_t fread(void *ptr, size_t size, */
/* size_t nmemb, FILE *stream); */
/* extern size_t fwrite(const void *ptr, size_t size, */
/* size_t nmemb, FILE *stream); */
void frw_sample(void)
{
FILE *file;
char *filename = "test_file.txt";
char str[] = "This is a test file.\n";
int i;
file = fopen(filename, "w");
printf("fwrite \"%s\" to %s\n", str, filename);
fwrite(str, sizeof(char), sizeof(str) - 1, file);
fwrite(str, sizeof(char), sizeof(str) - 1, file);
fwrite(str, sizeof(char), sizeof(str) - 1, file);
fclose(file);
printf("clear str...\n");
for (i = 0; i < sizeof(str); ++i)
{
str[i] = '\0';
}
file = fopen(filename, "r");
printf("fread from %s to str\n", filename);
fread(str, sizeof(char), sizeof(str) - 1, file);
printf("str: %s", str);
fclose(file);
printf("\n");
}
/****************************************************************
* 文件定位
*
* fgetpos 把stream的文件定位符当前值存储到pos中
* 成功返回0
* fseek 设置stream的文件定位符为whence + offset
* whence有3中取值:
* SEEK_SET文件开始,SEEK_CUR当前,SEEK_END文件结束
* 成功返回0
* fsetpos 设置stream的文件定位符为pos
* 成功返回0
* ftell 获得stream文件定位符的当前值
* rewind 设置stream的文件定位符到文件开始处
****************************************************************/
/* extern int fgetpos(FILE *stream, fpos_t *pos); */
/* extern int fseek(FILE *stream, long int offset, int whence); */
/* extern int fsetpos(FILE *stream, const fpos_t *pos); */
/* extern long int ftell(FILE *stream); */
/* extern void rewind(FILE *stream); */
void pos_sample(void)
{
FILE *file;
char *filename = "test_file.txt";
char str[] = "This is a test file.\n";
fpos_t pos;
file = fopen(filename, "r");
printf("fseek(file, 5, SEEK_SET)\n");
fseek(file, (long int)5, SEEK_SET);
printf("curpos: %ld\n", ftell(file));
printf("fgetpos to pos\n");
fgetpos(file, &pos);
fgets(str, sizeof(str), file);
printf("fgets: %s", str);
printf("curpos: %ld\n", ftell(file));
fgets(str, sizeof(str), file);
printf("fgets: %s", str);
printf("curpos: %ld\n", ftell(file));
printf("fsetpos at pos\n");
fsetpos(file, &pos);
printf("curpos: %ld\n", ftell(file));
printf("rewind\n");
rewind(file);
printf("curpos: %ld\n", ftell(file));
fclose(file);
}
/****************************************************************
* 错误处理
*
* ferror 测试stream的错误指示符
* stream流设置了错误指示符时返回非0
* perror 把errno中的错误编码转换为一条错误信息
* 把参数s所指的字符串和错误信息写到标准错误流stderr
* feof 如果文件结束返回非0,否则返回0
* clearerr 清空stream指向的流的文件结束符和错误指示符
****************************************************************/
/* extern int ferror(FILE *stream); */
/* extern void perror(const char *s); */
/* extern int feof(FILE *stream); */
/* extern void clearerr(FILE *stream); */
void err_sample(void)
{
perror("hehe");
}
void clean_all(void)
{
remove("new_file.txt");
remove("test_file.txt");
}
/****************************************************************
* 主函数
****************************************************************/
void stdio_main(void)
{
printf("=================================================\n");
printf(" stdio.h\n");
printf("=================================================\n");
ope_sample();
fmt_sample();
/* cio_sample(); */
frw_sample();
pos_sample();
err_sample();
/* clean_all(); */
}
/**
* @file signal_note.c
* @brief signal.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-14
*/
/****************************************************************
* <signal.h>信号处理
* 信号是程序执行过程发生的异常事件。同步信号的产生是因为程序自身
* 的某些动作,如:除零错误或不正当访问存储器。异步信号是由程序外
* 部的行为引起的,如:特定的组合键,或者另一个程序发送信号
* 程序不能屏蔽的信号要求立即得到处理,如果不对信号指定一种处理方
* 法,程序就会以失败的状态终止执行
* 当程序收到一个信号时,就会调用相应的信号处理程序,程序的正常执
* 行被挂起,如果信号处理程序把控制权返回给调用者,程序就会从挂起
* 的那个点继续执行
****************************************************************/
#include <stdio.h>
#include <signal.h>
/****************************************************************
* 类型和宏
*
* sig_atomic_t 整数类型,该类型对象可作为原子实体被访问
*
* SIG_DFL signal的第二个参数,对信号进行默认的处理
* SIG_IGN signal的第二个参数,忽略该信号
* SIG_ERR signal函数调用出错,返回SIG_ERR
*
* 信号类型
* SIGABRT 异常终止,比如执行了abort函数
* SIGFPE 错误的算术操作,比如除零或者导致溢出操作
* SIGILL 检测到无效的函数映像,比如一条非法指令
* SIGINT 收到一条交互式的提示信号
* SIGSEGV 对存储器的无效访问
* SIGTERM 送到程序中的终止请求
* 信号的完整集合,信号的语义和信号的默认处理方法是由实现定义的
* 所有的信号的编号都应该是正数
****************************************************************/
/****************************************************************
* 信号函数
*
* raise 把信号sig发送给正在执行的程序,成功返回0
* signal 指定程序接收到信号sig时,调用func处理信号
* 参数sig为信号类型,如SIGABRT,SIGINT等
* 参数func有3种取值:
* 1.SIG_DFL表示对信号进行默认处理
* 2.SIG_IGN表示对忽略该信号
* 3.func指向一个无返回值的函数
* 表示当这个信号发生时,就调用这个函数
* 函数signal成功返回指定的信号sig最后一次调用signal
* 的func的值;否则返回SIG_ERR
****************************************************************/
/* extern void (*signal(int sig, void (*func)(int)))(int); */
/* extern int raise(int sig); */
static int rec_sig = 0;
static void handle_int(int sig)
{
if(SIGINT == sig)
{
printf("recieve signal int\n");
rec_sig = 1;
}
signal(SIGINT, SIG_DFL);
}
/****************************************************************
* 主函数
****************************************************************/
void signal_main(void)
{
printf("=================================================\n");
printf(" signal.h\n");
printf("=================================================\n");
signal(SIGINT, handle_int); /* 按ctrl-c产生SIGINT信号 */
printf("按 CTRL-C 产生信号\n");
while(!rec_sig);
printf("按任意键退出\n");
getchar();
}
/**
* @file limits_note.c
* @brief limit.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-14
*/
/****************************************************************
* <limits.h>整型的大小
****************************************************************/
#include <stdio.h>
#include <limits.h>
/****************************************************************
* 整型常量
*
* CHAR_BIT 除位域外最小的对象的位数(字节),8
* SCHAR_MIN signed char类型最小值,-128
* SCHAR_MAX signed char类型最大值,+127
* UCHAR_MAX unsigned char类型最大值,255
* CHAR_MIN char类型最小值
* CHAR_MAX char类型最大值
* MB_LEN_MAX 任何支持区域设置的多字节字符的最大字节数,1
* SHRT_MIN short int类型最小值,-32768
* SHRT_MAX short int类型最大值,+32767
* USHRT_MAX unsigned short int类型最大值,65535
* INT_MIN int类型最小值,2个字节或4个字节,与处理器有关
* INT_MAX int类型最大值,2个字节或4个字节,与处理器有关
* UINT_MAX unsigned int类型最大值
* LONG_MIN long int类型最小值,-2147483648
* LONG_MAX long int类型最大值,+2147483647
* ULONG_MAX unsigned long int类型最大值,4294967295
****************************************************************/
/****************************************************************
* 主函数
****************************************************************/
void limits_main(void)
{
printf("=================================================\n");
printf(" limits.h\n");
printf("=================================================\n");
printf("CHAR_BIT: %d\n", CHAR_BIT);
printf("SCHAR_MIN: %d\n", SCHAR_MIN);
printf("SCHAR_MAX: %d\n", SCHAR_MAX);
printf("UCHAR_MAX: %d\n", UCHAR_MAX);
printf("CHAR_MIN: %d\n", CHAR_MIN);
printf("CHAR_MAX: %d\n", CHAR_MAX);
printf("MB_LEN_MAX: %d\n", MB_LEN_MAX);
printf("SHRT_MIN: %d\n", SHRT_MIN);
printf("SHRT_MAX: %d\n", SHRT_MAX);
printf("USHRT_MAX: %d\n", USHRT_MAX);
printf("INT_MIN: %d\n", INT_MIN);
printf("INT_MAX: %d\n", INT_MAX);
printf("UINT_MAX: %u\n", UINT_MAX);
printf("LONG_MIN: %ld\n", LONG_MIN);
printf("LONG_MAX: %ld\n", LONG_MAX);
printf("ULONG_MAX: %lu\n", ULONG_MAX);
printf("\n");
}
/**
* @file float_note.c
* @brief float.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-15
*/
/****************************************************************
* <float.h>浮点类型特征
* 浮点数x = s * b^e * sum(f(k) * b^(-k)) (k = 1, 2, ... , p)
* s 符号
* b 指数的基数(大于1的整数)
* e 指数(整数)
* p 精度(有效数字的位数)
* f(k) 小数点后第k位数字(比b小的整数)
****************************************************************/
#include <stdio.h>
#include <float.h>
/****************************************************************
* 浮点常量
*
* FLT_ROUNDS 浮点加法的舍入模式:
* -1 不能确定
* 0 向0舍入
* 1 最近舍入
* 2 向正无穷舍入
* 3 向负无穷舍入
* FLT_RADIX 指数表示的基数b
*
* FLT_MANT_DIG 有效数字位数(基数FLT_RADIX)
* DBL_MANT_DIG
* LDBL_MANT_DIG
*
* FLT_DIG 有效数字位数(十进制)
* DBL_DIG
* LDBL_DIG
*
* FLT_MIN_EXP FLT_RADIX能表示的最小负的次幂
* DBL_MIN_EXP
* LDBL_MIN_EXP
* FLT_MAX_EXP FLT_RADIX能表示的最大次幂
* DBL_MAX_EXP
* LDBL_MAX_EXP
*
* FLT_MIN_10_EXP 10能表示的最小的负的次幂
* DBL_MIN_10_EXP
* LDBL_MIN_10_EXP
* FLT_MAX_10_EXP 10能表示的最大次幂
* DBL_MAX_10_EXP
* LDBL_MAX_10_EXP
*
* FLT_MIN 最小的正的规格化浮点数
* DBL_MIN
* LDBL_MIN
* FLT_MAX 最大可表示的有限浮点数
* DBL_MAX
* LDBL_MAX
*
* FLT_EPSILO 最小的正浮点数e,满足1.0 + e != 1.0
* DBL_EPSILON
* LDBL_EPSILON
****************************************************************/
/****************************************************************
* 主函数
****************************************************************/
void float_main(void)
{
printf("=================================================\n");
printf(" float.h\n");
printf("=================================================\n");
printf("FLT_ROUNDS: %d\n", FLT_ROUNDS);
printf("FLT_RADIX: %d\n", FLT_RADIX);
printf("FLT_MANT_DIG: %d\n", FLT_MANT_DIG);
printf("DBL_MANT_DIG: %d\n", DBL_MANT_DIG);
printf("LDBL_MANT_DIG: %d\n", LDBL_MANT_DIG);
printf("FLT_DIG: %d\n", FLT_DIG);
printf("DBL_DIG: %d\n", DBL_DIG);
printf("LDBL_DIG: %d\n", LDBL_DIG);
printf("FLT_MIN_EXP: %d\n", FLT_MIN_EXP);
printf("DBL_MIN_EXP: %d\n", DBL_MIN_EXP);
printf("LDBL_MIN_EXP: %d\n", LDBL_MIN_EXP);
printf("FLT_MAX_EXP: %d\n", FLT_MAX_EXP);
printf("DBL_MAX_EXP: %d\n", DBL_MAX_EXP);
printf("LDBL_MAX_EXP: %d\n", LDBL_MAX_EXP);
printf("FLT_MIN_10_EXP: %d\n", FLT_MIN_10_EXP);
printf("DBL_MIN_10_EXP: %d\n", DBL_MIN_10_EXP);
printf("LDBL_MIN_10_EXP: %d\n", LDBL_MIN_10_EXP);
printf("FLT_MAX_10_EXP: %d\n", FLT_MAX_10_EXP);
printf("DBL_MAX_10_EXP: %d\n", DBL_MAX_10_EXP);
printf("LDBL_MAX_10_EXP: %d\n", LDBL_MAX_10_EXP);
printf("FLT_MIN: %g\n", FLT_MIN);
printf("DBL_MIN: %lg\n", DBL_MIN);
printf("LDBL_MIN: %llg\n", LDBL_MIN);
printf("FLT_MAX: %g\n", FLT_MAX);
printf("DBL_MAX: %lg\n", DBL_MAX);
printf("LDBL_MAX: %llg\n", LDBL_MAX);
printf("FLT_EPSILON: %g\n", FLT_EPSILON);
printf("DBL_EPSILON: %lg\n", DBL_EPSILON);
printf("LDBL_EPSILON: %llg\n", LDBL_EPSILON);
printf("\n");
}
/**
* @file assert_note.c
* @brief assert.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-15
*/
/****************************************************************
* <assert.h>的唯一目的是提供宏assert的定义,可以再程序的任何关键
* 地方使用这个宏进行断言,如果某处断言为假,会在标准错误流中输出
* 一条错误信息,并使程序异常终止
* 头文件assert.h,每次包含它的时候它的行为都会发生变化
* 其他头文件包含多次与包含一次的效果完全相同
* 打开断言:
* #undef NDEBUG
* #include <assert.h>
* 关闭断言
* #define NDEBUG
* #include <assert.h>
****************************************************************/
#include <stdio.h>
#include <assert.h>
/****************************************************************
* 断言
*
* NDEBUG 断言的开关
* assert 如果表达式为假,向标准错误流写入错误并调用abort
* assert的实现是一个宏
*
* 宏assert的结构
* #undef assert
* #ifdef NDEBUG
* #define assert (test) ((void)0)
* #else
* #define assert (test) ...
* #endif
****************************************************************/
/* 宏void assert(int expression); */
/****************************************************************
* 主函数
****************************************************************/
void assert_main(void)
{
printf("=================================================\n");
printf(" assert.h\n");
printf("=================================================\n");
assert(1 == 1);
/* assert(1 == 2); */
printf("\n");
}
/**
* @file errno_note.c
* @brief errno.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-15
*/
/****************************************************************
* <errno.h>定义了错误编码,错误编码与具体定义有关
* errno是一个整型变量存储了错误编码,该值会被其它库函数改变:
* <math.h>中的很多函数发生域错误或者溢出错误
* <stdlib.h>中把文本转换成算术类型发生溢出错误
* <stdio.h>中改变文件中下一次读或写的位置
* <signal.h>中signal函数
****************************************************************/
#include <stdio.h>
#include <errno.h>
/****************************************************************
* 错误
*
* EDOM 算术域错误码
* ERANGE 算术溢出错误码
* errno 一个存储错误码的整型变量
****************************************************************/
/* extern int errno; */
/****************************************************************
* 主函数
****************************************************************/
void errno_main(void)
{
int errnum;
printf("=================================================\n");
printf(" errno.h\n");
printf("=================================================\n");
printf("EDOM: %d\n", EDOM);
printf("ERANGE: %d\n", ERANGE);
printf("\n");
printf("error code: \n");
for (errnum = 0; errnum < 50; errnum++)
{
printf("errno: %2d %s\n", errnum, strerror(errnum));
}
printf("\n");
}
/**
* @file stdarg_note.c
* @brief stdarg.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-15
*/
/****************************************************************
* <stdarg.h>可变参数
* C语言允许定义接受可变参数列表的函数
* 在调用可变参数函数时,必须知道每个参数的类型,可以使用一个固定
* 的参数来确定参数的个数和类型,如printf函数
****************************************************************/
#include <stdio.h>
#include <stdarg.h>
/****************************************************************
* 可变参数
*
* va_list 它是一个保存va_start,va_arg,va_end所需信息的类型
* va_start 对ap进行初始化,以便va_arg和va_end使用
* 参数parmN是函数定义可变参数列表左边的标识符
* va_arg 修改ap的值指向下一个参数并返回该参数
* type是一种参数的类型
* va_end 使函数正常返回,可能修改ap的值
****************************************************************/
/* 宏void va_start(va_list ap, parmN); */
/* 宏type va_arg(va_list ap, type); */
/* 宏void va_end(va_list ap); */
void print_arg(const char *format, ...)
{
va_list ap;
va_start(ap, format);
for (; *format != '\0'; ++format)
{
while(*format != '%')
{
printf("%c", *format);
++format;
}
++format;
switch(*format)
{
case 'i':
printf("%d", va_arg(ap, int));
break;
case 'd':
printf("%lf", va_arg(ap, double));
break;
case 's':
printf("%s", va_arg(ap, char *));
break;
case 'c':
printf("%c", va_arg(ap, char));
break;
default:
printf("%c", *format);
break;
}
}
va_end(ap);
}
int max_int(int num, ... )
{
va_list ap;
int i;
int cur;
int max;
va_start(ap, num);
max = va_arg(ap, int);
for(i = 1; i < num; ++i)
{
cur = va_arg(ap, int);
if (max < cur)
{
max = cur;
}
}
va_end(ap);
return max;
}
/****************************************************************
* 主函数
****************************************************************/
void stdarg_main(void)
{
int i = 789;
double d = 123.456;
char *s = "this is a string";
char c = 'c';
printf("=================================================\n");
printf(" stdarg.h\n");
printf("=================================================\n");
print_arg("int: %i, double: %d, string: %s, char: %c",
i, d, s, c);
printf("\n");
printf("max_int(5, 7, 9, -6, 10, 2): %d\n",
max_int(5, 7, 9, -6, 10, 2));
printf("\n\n");
}
/**
* @file stddef_note.c
* @brief stddef.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-15
*/
/****************************************************************
* <stddef.h>定义了一些类型
****************************************************************/
#include <stdio.h>
#include <stddef.h>
/****************************************************************
* 一般定义
*
* ptrdiff_t 两个指针相减的结果,有符号整型
* size_t sizeof操作符的结果,无符号整型
* wchar_t 整型,它范围内的值可以表示最大扩展字符集中所有成员
* 的不同编码值,而该字符集是由支持它的区域设置指定的
* NULL 空指针常量
* offsetof 展开为一个size_t类型的整值常量表达式,它的值是从结
* 构体的起始位置开始(type)到结构体成员(member)的
* 偏移量,以字节为单位
* offsetof(type, member)
****************************************************************/
/* 自定义结构体,在示例程序中使用 */
struct def_st
{
char c;
int i;
double d;
};
/****************************************************************
* 主函数
****************************************************************/
void stddef_main(void)
{
printf("=================================================\n");
printf(" stddef.h\n");
printf("=================================================\n");
printf("sizeof(char): %d\n", sizeof(char));
printf("sizeof(short int): %d\n", sizeof(short int));
printf("sizeof(int): %d\n", sizeof(int));
printf("sizeof(long int): %d\n", sizeof(long int));
printf("sizeof(float): %d\n", sizeof(float));
printf("sizeof(double): %d\n", sizeof(double));
printf("sizeof(long double): %d\n", sizeof(long double));
printf("\n");
printf("offsetof(ds, c): %d\n", offsetof(struct def_st, c));
printf("offsetof(ds, i): %d\n", offsetof(struct def_st, i));
printf("offsetof(ds, d): %d\n", offsetof(struct def_st, d));
printf("\n");
}
/**
* @file setjmp_note.c
* @brief setjmp.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-15
*/
/****************************************************************
* <setjmp.h>非本地跳转
* goto语句只能跳到所在函数内部标号,而不能将控制权转移到任意地点
* setjmp和longjmp分别承担非局部标号和goto作用
* 这些函数对处理程序中的低级函数中遇到的异常情况很有用
****************************************************************/
#include <stdio.h>
#include <setjmp.h>
/****************************************************************
* 类型
*
* jmp_buf 数组类型,适合存储恢复一个调用环境所需的信息
* 程序存放位置,栈和框架指针,重要寄存器和内部数据
****************************************************************/
/****************************************************************
* 保存和恢复环境
*
* setjmp 将它的调用环境存在它的jmp_buf参数中
* 以供后面的longjmp函数使用
* 如果setjmp来自一个直接调用返回0,来自函数longjmp的
* 调用,setjmp返回一个非0值
* longjmp 使用相应的jmp_buf恢复程序的调用环境
* val不为0时,函数返回val,否则返回1
****************************************************************/
/* 宏int setjmp(jmp_buf env); */
/* extern void longjmp(jmp_buf env, int val); */
/****************************************************************
* 主函数
****************************************************************/
void setjmp_main(void)
{
jmp_buf jmpbuf;
printf("=================================================\n");
printf(" setjmp.h\n");
printf("=================================================\n");
switch(setjmp(jmpbuf))
{
case 0:
printf("in case 0\n");
longjmp(jmpbuf, 0); /* 这里返回1 */
break;
case 1:
printf("in case 1\n");
longjmp(jmpbuf, 2); /* 这里返回2 */
break;
case 2:
printf("in case 2\n");
longjmp(jmpbuf, 3); /* 这里返回3 */
break;
default:
break;
}
printf("\n");
}
/**
* @file locale_note.c
* @brief locale.h笔记
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-15
*/
/****************************************************************
* <locale.h>区域设置
* 这些区域设置影响标准库的输入输出函数
****************************************************************/
#include <stdio.h>
#include <locale.h>
/****************************************************************
* 类型和宏
*
* struct lconv 它包含的成员和数字值的格式有关
* NULL 空指针
* LC_ALL setlocale函数的第一个参数,对整个区域进行设置
* LC_COLLATE 影响<string.h>中strcoll和strxfrm的比较方式
* LC_CTYPE 影响<ctype.h>中的函数、<stdio.h>中打印和扫描函数
* 和<stdlib.h>中多字节函数
* LC_MONETARY 影响<locale.h>中localeconv的返回值
* LC_NUMERIC 影响<stdio.h>中打印和扫描函数、<stdlib.h>中atof和
* strtod函数对十进制小数点字符的使用方式,也会影响
* <locale.h>中localeconv的返回值
* LC_TIME 影响<time.h>中的时间转换函数
****************************************************************/
/****************************************************************
* 区域设置与查询
*
* setlocale 区域设置函数,参数category为要设置的类别,locale为
* 要设置的值,locale的值"C"为编译器指定最小的环境值
* local的值""指定实现定义的本地环境
* localeconv 获得当前的区域设置
****************************************************************/
/* extern char *setlocale(int category, const char *locale); */
/* extern struct lconv *localeconv(void); */
/****************************************************************
* 主函数
****************************************************************/
void locale_main(void)
{
struct lconv *lc;
printf("=================================================\n");
printf(" locale.h\n");
printf("=================================================\n");
/* setlocale(LC_ALL, ""); */
/* setlocale(LC_ALL, "C"); */
setlocale(LC_ALL, "Chinese");
/* setlocale(LC_ALL, "English"); */
lc = localeconv();
printf("int_curr_symbol: \"%s\"\n", lc->int_curr_symbol);
printf("currency_symbol: \"%s\"\n", lc->currency_symbol);
printf("mon_decimal_point: \"%s\"\n", lc->mon_decimal_point);
printf("mon_thousands_sep: \"%s\"\n", lc->mon_thousands_sep);
printf("mon_grouping: \"%s\"\n", lc->mon_grouping);
printf("positive_sign: \"%s\"\n", lc->positive_sign);
printf("negative_sign: \"%s\"\n", lc->negative_sign);
printf("int_frac_digits: %d\n", lc->int_frac_digits);
printf("frac_digits: %d\n", lc->frac_digits);
printf("n_sep_by_space: %d\n", lc->n_sep_by_space);
printf("p_sep_by_space: %d\n", lc->p_sep_by_space);
printf("n_cs_precedes: %d\n", lc->n_cs_precedes);
printf("p_cs_precedes: %d\n", lc->p_cs_precedes);
printf("n_sign_posn: %d\n", lc->n_sign_posn);
printf("p_sign_posn: %d\n", lc->p_sign_posn);
}
/**
* @file main.c
* @brief 主函数
* @author hatlonely
* @e-mail hatlonely@foxmail.com
* @date 2013-01-07
*/
extern void math_main(void);
extern void ctype_main(void);
extern void time_main(void);
extern void string_main(void);
extern void stdlib_main(void);
extern void stdio_main(void);
extern void signal_main(void);
extern void limits_main(void);
extern void float_main(void);
extern void assert_main(void);
extern void errno_main(void);
extern void setjmp_main(void);
extern void stdarg_main(void);
extern void stddef_main(void);
extern void locale_main(void);
int main()
{
math_main();
ctype_main();
time_main();
string_main();
stdlib_main();
stdio_main();
limits_main();
float_main();
assert_main();
errno_main();
setjmp_main();
stdarg_main();
stddef_main();
locale_main();
signal_main();
return 0;
}
objects= main.o \
math_note.o \
ctype_note.o \
time_note.o \
string_note.o \
stdlib_note.o \
stdio_note.o \
signal_note.o \
limits_note.o \
float_note.o \
assert_note.o \
errno_note.o \
setjmp_note.o \
stdarg_note.o \
stddef_note.o \
locale_note.o
CSTDL: $(objects)
gcc -o CSTDL $(objects) -lm
%.o: %.c
gcc -c $< -o $@
clean:
rm *.o CSTDL
run:
./CSTDL