@[TOC]
标准库
一. 冷门的库
- 与小数精度有关的<float.h>
- 与数据的大小范围限制有关 <limits.h>
- 与国家的地域属性有关的配置<locale.h>
- 关于jmp条转的库<setjmp.h>
- 关于信号处理 <signal.h>
- 定义一些结果运算后的变量或者类型<stddef.h>
二. 实用的标准库
(一). <assert.h> 信息诊断
assert(条件判断)
函数没有返回值,可能会引起程序退出
#include <assert.h>
#include <stdio.h>
int main()
{
int a;
printf("请输入一个整数值: ");
scanf("%d", &a);
assert(a >= 10);
printf("输入的整数是: %d\n", a);
return(0);
}
如果你的输入>=10,程序正常执行
如果你的输入<10,程序中断退出
(二). <errno.h>报错反馈
1.stderr(errno) 找不到文件
extern int errno
这里只能用errno
,用其它的变量名称都不可以
#include <stdio.h>
#include <errno.h>
#include <string.h>
extern int errno;
int main ()
{
FILE *file_ptr;
file_ptr = fopen("file.txt", "r");
if( file_ptr == NULL )
{
fprintf(stderr, "错误类型编号: %d\n", errno);
fprintf(stderr, "发生了什么错误: %s\n", strerror(errno));
}
else
{
fclose(file_ptr);
}
return(0);
}
2. EDOM 超出数学定义域
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LTj41M7g-1645462567059)(C%E5%BA%93.assets/image-20220220223247653.png)]
value = sqrt(-10);
我们知道,负数是不能开方的,所以不在规定的数学定义域内
#include <stdio.h>
#include <errno.h>
#include <math.h>
int main()
{
double value;
errno = 0;
value = sqrt(-10);
if(errno == EDOM)
{
printf("错误类型编号: %d\n", errno);
printf("错误类型编号: %d\n", EDOM);
printf("发生了什么错误:超出数学函数定义的域 \n ");
}
else
{
printf("在数学函数定义的域\n");
}
return(0);
}
3. ERANGE 不在数学函数域
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3SqFjeTv-1645462567061)(C%E5%BA%93.assets/image-20220220224116147.png)]
log()的范围是[-∞,+∞]
当结果是∞的时候,就会这样报错
#include <stdio.h>
#include <errno.h>
#include <math.h>
int main()
{
double x;
double value;
x = 0.000000;
value = log(x);
if( errno == ERANGE )
{
printf("错误类型 %d\n",errno);
printf("Log(%f) is too large\n", x);
}
else
{
printf("Log(%f) = %f\n", x, value);
}
return 0;
}
(三). <stdarg.h>可变参数
#include <stdarg.h>
#include <stdio.h>
int add(int, ...);
int main()
{
printf("和 = %d\n", add(2, 20, 30) );
return 0;
}
int add(int how_many_args, ...)
//how_many_args 固定的参数,代表了参数的个数,
{
int sum = 0;
va_list book_list;
int i;
va_start(book_list, how_many_args);
for(i = 0; i < how_many_args; i++)
{
sum += va_arg(book_list, int);
//(int) va_arg(book_list, int);返回一个int的类型
//va_arg(book_list, int); 根据int的数据长度去遍历ags
}
va_end(book_list);
return sum;
}
上面中
1. va_list book_list
book_list用于了va_start()、va_arg() 和 va_end() 中
2. va_start(book_list, how_many_args);
在参数,参数个数的条件下,借va_start
初始化了book_list
用于后面参数的遍历
3. va_arg(book_list, int);
返回int型
遍历也是4字节4字节的遍历
4. va_end(book_list);
结束这个book_list
如果没有end,连start都无法开始
(四). <stdio.h>标准库
1. vfprintf() 多此一举的fprintf
#include <stdio.h>
#include <stdarg.h>
//这里用到了可变参数
//翻看网上的教程,发现他们基本上都用可变参数
void WriteFrmtd(FILE *stream, char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stream, format, args);
va_end(args);
}
int main ()
{
FILE *fp;
fp = fopen("d:/file.txt","w+");
WriteFrmtd(fp, "This is just one argument %d %s\n", 10,"dqx");
fclose(fp);
return(0);
}
2. vprintf 多此一举的printf
用vprintf实现printf,多此一举
#include<stdio.h>
//#include<stdlib.h>
#include<stdarg.h>//ANSI C可变参数的头文件
int print(char* format, ...) {
va_list ap;
int n;
va_start(ap, format);
n = vprintf(format, ap);
va_end(ap);
return 0;
}
int main() {
int ch1 = 10, ch2 = 20;
print("%d\t%d\n", ch1, ch2);
return 0;
}
3. vsprintf 多此一举的sprintf
#include <stdio.h>
#include <stdarg.h>
char buffer[80];
int func(char *format, ...)
{
va_list aptr;
int ret;
va_start(aptr, format);
ret = vsprintf(buffer, format, aptr);
va_end(aptr);
return(ret);
}
int main()
{
int i = 5;
float f = 27.0;
char str[50] = "runoob.com";
func("%d %f %s", i, f, str);
printf("%s\n", buffer);
return(0);
}
#include <stdarg.h>
#include <stdio.h>
int add(int, ...);
int main()
{
printf("和 = %d\n", add(2, 20, 30) );
return 0;
}
int add(int how_many_args, ...)
//how_many_args 固定的参数,代表了参数的个数,
{
int sum = 0;
va_list book_list;
int i;
va_start(book_list, how_many_args);
for(i = 0; i < how_many_args; i++)
{
sum += va_arg(book_list, int);
//(int) va_arg(book_list, int);返回一个int的类型
//va_arg(book_list, int); 根据int的数据长度去遍历ags
}
va_end(book_list);
return sum;
}
8. abort() 异常中断退出
C 库函数 void abort(void) 中止程序执行,直接从调用的地方跳出。
9. atexit()
函数发生问题退出的时候调用的函数
#include <stdio.h>
#include <stdlib.h>
void functionA ()
{
printf("这是函数A\n");
}
int main ()
{
atexit(functionA );
return(0);
}
(六). <time.h>时间库
协调世界时 UTC:1970-01-01 00:00:00 下面的绝大多数的时间都是与它做减法
库变量 下面是头文件 time.h 中定义的变量类型:
size_t | 是无符号整数类型,它是 sizeof 关键字的结果。 |
clock_t | 这是一个适合存储处理器时间的类型。 |
time_t is | 这是一个适合存储日历时间类型。是long的类型 |
struct tm | 这是一个用来保存时间和日期的结构。 |
- | -- |
struct tm 结构体
tm 结构的定义如下:
struct tm {
int tm_sec; /* 秒,范围从 0 到 59 */
int tm_min; /* 分,范围从 0 到 59 */
int tm_hour; /* 小时,范围从 0 到 23 */
int tm_mday; /* 一月中的第几天,范围从 1 到 31 */
int tm_mon; /* 月,范围从 0 到 11 */
int tm_year; /* 自 1900 年起的年数 */
int tm_wday; /* 一周中的第几天,范围从 0 到 6 */
int tm_yday; /* 一年中的第几天,范围从 0 到 365 */
int tm_isdst; /* 夏令时 */
};
关于那写数据转化为字符串怎么输出
说明符 | 替换为 | 实例 |
%a | 缩写的星期几名称 | Sun |
%A | 完整的星期几名称 | Sunday |
%b | 缩写的月份名称 | Mar |
%B | 完整的月份名称 | March |
%c | 日期和时间表示法 | Sun Aug 19 02:56:02 2012 |
%d | 一月中的第几天(01-31) | 19 |
%H | 24 小时格式的小时(00-23) | 14 |
%I | 12 小时格式的小时(01-12) | 05 |
%j | 一年中的第几天(001-366) | 231 |
%m | 十进制数表示的月份(01-12) | 08 |
%M | 分(00-59) | 55 |
%p | AM 或 PM 名称 | PM |
%S | 秒(00-61) | 02 |
%U | 一年中的第几周,以第一个星期日作为第一周的第一天(00-53) | 33 |
%w | 十进制数表示的星期几,星期日表示为 0(0-6) | 4 |
%W | 一年中的第几周,以第一个星期一作为第一周的第一天(00-53) | 34 |
%x | 日期表示法 | 08/19/12 |
%X | 时间表示法 | 02:50:06 |
%y | 年份,最后两个数字(00-99) | 01 |
%Y | 年份 | 2012 |
%Z | 时区的名称或缩写 | CDT |
%% | 一个 % 符号 | % |
asctime() 返回一个tm类型的字符串,,代表了tm的结构
char *asctime(const struct tm *timeptr)
参数 是
#include <stdio.h>
#include <string.h>
#include <time.h>
int main()
{
struct tm t;
t.tm_sec = 10;
t.tm_min = 12;
t.tm_hour = 3;
t.tm_mday = 23;
t.tm_mon = 2;
t.tm_year = 22;
t.tm_wday = 6;
puts(asctime(&t));
return(0);
}
输出
Sat Mar 23 03:12:10 1922
clock() 返回处理器时钟所使用的时间。
clock_t clock(void)
处理器时钟所使用的时间
CLOCKS_PER_SEC 可能是一个单位,就像
sizeof(arr)/sizeof(int)
CLOCKS_PER_SEC
好比/sizeof(int)
#include <time.h>
#include <stdio.h>
int main()
{
clock_t start, end;
double total;
int i;
start = clock();
printf("程序启动,start = %ld\n", start);
printf("开始一个大循环,start = %ld\n", start);
for(i=0; i< 10000000; i++)
{
}
end = clock();
printf("大循环结束,end_t = %ld\n", end);
total = (double)(end - start) / CLOCKS_PER_SEC;
printf("CPU 占用的总时间:%f\n", total );
printf("程序退出...\n");
return(0);
}
time()
time_t time(time_t *seconds)
以 time_t 对象返回当前时间自纪元 Epoch(1970-01-01 00:00:00 UTC)起经过的秒数
#include <stdio.h>
#include <time.h>
int main ()
{
time_t seconds;
seconds = time(NULL);
printf("自 1970-01-01 起的小时数 = %ld\n", seconds/3600);
return(0);
}
输出
自 1970-01-01 起的小时数 = 457105
ctime()
char *ctime(const time_t *timer)
返回一个表示当地时间的字符串
#include <stdio.h>
#include <time.h>
int main ()
{
time_t curtime;
time(&curtime);
printf("当前时间 = %s", ctime(&curtime));
return(0);
}
difftime() 返回2个时间的差
double difftime(time_t time1, time_t time2)
参数1,参数2是两个time_t类型的时间 用dounle返回两个时间之间相差的秒数 (time1 - time2)。
#include <stdio.h>
#include <time.h>
#include <Windows.h>
int main ()
{
time_t start_t, end_t;
double diff_t;
//把时间给start_t
time(&start_t);
Sleep(1000);
//这里是毫秒,1000毫秒=1秒
//Sleep必须大写,否者编译器不认识
//把时间给end_t
time(&end_t);
diff_t = difftime(end_t, start_t);
printf("执行时间 = %lf\n", diff_t);
return(0);
}
输出
执行时间 = 1.000000
gmtime() 将time_t转化为tm
#include <stdio.h>
#include <time.h>
//时区的初始化
#define BST (+1)
#define CCT (+8)
int main ()
{
time_t init_time;
//定义了一个结构体指针
struct tm *ptr;
//初始化rawtime
time(&init_time);
/* 获取 GMT 时间 */
//把time_t类型转化为tm类型,并返回一个结构体指针
ptr = gmtime(&init_time );
printf("当前的世界时钟:\n");
printf("伦敦:%2d:%02d\n", (ptr->tm_hour+BST)%24, ptr->tm_min);
printf("中国:%2d:%02d\n", (ptr->tm_hour+CCT)%24, ptr->tm_min);
return(0);
}
localtime
struct tm *localtime(const time_t *timer)
localtime() 将参数 timer所指的 time_t 结构中的信息转换成真实世界所使用的时间日期表示方法,然后返回结构体指针
#include <stdio.h>
#include <time.h>
int main ()
{
time_t init_time;
struct tm *output;
time( &init_time );
output = localtime( &init_time );
printf("当前的本地时间和日期:%s", asctime(output));
return(0);
}
mktime()
time_t mktime(struct tm *timeptr)
参数是一个时间结构体指针
函数返回自 1970 年 1 月 1 日以来持续时间的秒数。如果发生错误,则返回 -1 值
#include <stdio.h>
#include <time.h>
int main () {
int ret;
struct tm info;
char buffer[80];
//1970-01-01 00:00:00
info.tm_year = 2021 - 1900;
info.tm_mon = 7-1;
info.tm_mday = 4-0;
info.tm_hour = 0-0;
info.tm_min = 0-0;
info.tm_sec = 1-0;
info.tm_isdst = -1;/* 夏令时 */
ret = mktime(&info);
if( ret == -1 )
{
printf("Error: unable to make time using mktime\n");
}
else
{
strftime(buffer, sizeof(buffer), "%c", &info );
printf(buffer);
}
return(0);
}
输出
另外一个代码
/* 输入日期判断是周几 */
#include <stdio.h> /* printf, scanf */
#include <time.h> /* time_t, struct tm, time, mktime */
int main ()
{
time_t init_time;
struct tm * time_struct_ptr;
int year, month ,day;
const char * weekday_arr[] = { "周日", "周一","周二", "周三","周四", "周五", "周六"};
/* 用户输入日期 */
printf ("年: ");
//fflush(stdout);
scanf ("%d",&year);
printf ("月: ");
//fflush(stdout);
scanf ("%d",&month);
printf ("日: ");
//fflush(stdout);
scanf ("%d",&day);
/* 获取当前时间信息,并修改用户输入的输入信息 */
time ( &init_time );
time_struct_ptr = localtime ( &init_time );
time_struct_ptr->tm_year = year - 1900;
time_struct_ptr->tm_mon = month - 1;
time_struct_ptr->tm_mday = day;
/* 调用 mktime: time_struct_ptr->tm_wday */
mktime ( time_struct_ptr );
printf ("那一天是:%s\n", weekday_arr[time_struct_ptr->tm_wday]);
return 0;
}
输入2001.09.27 输出
年: 2001
月: 9
日: 27
那一天是:周四
strftime 将时间写入字符串
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)
参数1:接收时间字符串的数组 参数2: 这是被复制到 str 的最大字符数 参数3: 格式化写入 参数4:时间结构体 函数返回 如果产生的 C 字符串小于 size 个字符(包括空结束字符),则会返回复制到 str 中的字符总数(不包括空结束字符),否则返回零,没有字符串写入到数组
#include <stdio.h>
#include <time.h>
int main ()
{
time_t rawtime;
struct tm *info;
char buffer[80];
time( &rawtime );
info = localtime( &rawtime );
strftime(buffer, 50, "%Y-%m-%d %H:%M:%S", info);
printf("格式化的日期 & 时间 : |%s|\n", buffer );
return(0);
}
输出
格式化的日期 & 时间 : |2022-02-23 09:15:27|