C标准库

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

英文版:The Standard C Library 内容简介 《C标准库》集中讨论了C标准库,全面介绍了ANSI/ISOC语言标准的所有库函数。书中通过引用ISOC标准的相关部分,详细讲解了每一个库函数的使用方法,并通过示例描述了其实现细节,且给出了实现和测试这些函数的完整代码。此外,每章结尾附有不同难度的习题,帮助读者巩固和提高。通过此书,读者将会更好地使用C标准库,并学会如何设计和实现库。 《C标准库》结构清晰,内容权威,阐述精辟,对于各层次C程序员和相关专业高校师生都是一本优秀的参考书。 编辑推荐 C标准库“圣经”,提供完整源代码,全面深入阐述库函数的实现与运用。C程序员必备参考书。《C标准库》是由世界级C语言专家编写的C标准库经典著作。英文版已经重印十多次,影响了几代程序员。《C标准库》结合C标准的相关部分,精辟地讲述了每一个库函数的使用方法和实现细节,这正是一个真正的C程序员所必须掌握的。更重要的是,书中给出了实现和测试这些函数的完整源代码。可以让你更深入地学习C语言。不仅如此,《C标准库》还讨论了一些即使是最有经验的C程序员通常也不熟悉的知识,比如国际化和独立于区域设置的程序的编写、与构建库相关的概念和设计思想。 作者简介 作者:(美国)P.J.Plauger 译者:卢红星 徐明亮 霍建同 P.J.Plauger,世界著名的软件技术专家,曾任ISO C标准委员会主席,C/C++User's Journal主编,现任ISO C++标准委员会主席。他是C/C++标准库开发领域的大师。所开发的Dinkumware标准库应用广泛。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值