首页
前端面试题
前端报错总结
电子书
更多
插件下载
Search
1
JavaScript基础(二)操作符 流程控制
42 阅读
2
HTML基础
20 阅读
3
Vue基础
17 阅读
4
wctype.h
14 阅读
5
Vue2(知识点)
13 阅读
默认分类
HTML CSS
HTML基础
CSS
HTML5 CSS3
javaScript
javaScript基础
javaScript高级
Web APIs
jQuery
js小总结
WEB开发布局
Vue
PS切图
数据可视化
Git使用
Uniapp
c语言入门
标准库
嵌入式
登录
Search
liuxiaobai
累计撰写
108
篇文章
累计收到
12
条评论
首页
栏目
默认分类
HTML CSS
HTML基础
CSS
HTML5 CSS3
javaScript
javaScript基础
javaScript高级
Web APIs
jQuery
js小总结
WEB开发布局
Vue
PS切图
数据可视化
Git使用
Uniapp
c语言入门
标准库
嵌入式
页面
前端面试题
前端报错总结
电子书
插件下载
搜索到
104
篇与
的结果
2023-09-20
time.h
time.htime_ttime_t 是一个表示时间的类型别名,可以视为国际标准时 UTC。它可能是浮点数,也可能是整数,Unix 系统一般是整数。许多系统上,time_t 表示自时间纪元(time epoch)以来的秒数。Unix 的时间纪元是国际标准时 UTC 的1970年1月1日的零分零秒。time_t 如果为负数,则表示时间纪元之前的时间。time_t 一般是32位或64位整数类型的别名,具体类型取决于当前系统。如果是32位带符号整数,time_t 可以表示的时间到 2038年1月19日03:14:07 UTC 为止;如果是32位无符号整数,则表示到2106年。如果是64位带符号整数,可以表示-2930亿年到+2930亿年的时间范围。struct tmstruct tm 是一个数据结构,用来保存时间的各个组成部分,比如小时、分钟、秒、日、月、年等。下面是它的结构。struct tm { int tm_sec; // 秒数 [0, 60] int tm_min; // 分钟 [0, 59] int tm_hour; // 小时 [0, 23] int tm_mday; // 月份的天数 [1, 31] int tm_mon; // 月份 [0, 11],一月用 0 表示 int tm_year; // 距离 1900 的年数 int tm_wday; // 星期几 [0, 6],星期天用 0 表示 int tm_yday; // 距离1月1日的天数 [0, 365] int tm_isdst; // 是否采用夏令时,1 表示采用,0 表示未采用 };time()time()函数返回从时间纪元到现在经过的秒数。time_t time(time_t* returned_value);time()接受一个 time_t 指针作为参数,返回值会写入指针地址。参数可以是空指针 NULL。time()的返回值是 time_t 类型的当前时间。 如果计算机无法提供当前的秒数,或者返回值太大,无法用time_t类型表示,time()函数就返回-1。time_t now; // 写法一 now = time(NULL); // 写法二 time(&now);上面示例展示了将当前时间存入变量now的两种写法。如果要知道某个操作耗费的精确时间,需要调用两次time(),再将两次的返回值相减。time_t begin = time(NULL); // ... 执行某些操作 time_t end = time(NULL); printf("%d\n", end - begin);注意,上面的方法只能精确到秒。ctime()ctime()用来将 time_t 类型的值直接输出为人类可读的格式。char* ctime( time_t const * time_value );ctime()的参数是一个 time_t 指针,返回一个字符串指针。该字符串的格式类似“Sun Jul 4 04:02:48 1976\n\0”,尾部包含换行符和字符串终止标志。下面是一个例子。time_t now; now = time(NULL); // 输出 Sun Feb 28 18:47:25 2021 printf("%s", ctime(&now));注意,ctime()会在字符串尾部自动添加换行符。localtime(),gmtime()localtime()函数用来将 time_t 类型的时间,转换为当前时区的 struct tm 结构。gmtime()函数用来将 time_t 类型的时间,转换为 UTC 时间的 struct tm 结构。它们的区别就是返回值,前者是本地时间,后者是 UTC 时间。struct tm* localtime(const time_t* timer); struct tm* gmtime(const time_t* timer);下面是一个例子。time_t now = time(NULL); // 输出 Local: Sun Feb 28 20:15:27 2021 printf("Local: %s", asctime(localtime(&now))); // 输出 UTC : Mon Mar 1 04:15:27 2021 printf("UTC : %s", asctime(gmtime(&now)));asctime()asctime()函数用来将 struct tm 结构,直接输出为人类可读的格式。该函数会自动在输出的尾部添加换行符。用法示例参考上一小节。mktime()mktime()函数用于把一个 struct tm 结构转换为 time_t 值。time_t mktime(struct tm* tm_ptr);mktime()的参数是一个 struct tm 指针。mktime()会自动设置 struct tm 结构里面的tm_wday属性和tm_yday属性,开发者自己不必填写这两个属性。所以,这个函数常用来获得指定时间是星期几(tm_wday)。struct tm 结构的tm_isdst属性也可以设为-1,让mktime()决定是否应该采用夏令时。下面是一个例子。struct tm some_time = { .tm_year=82, // 距离 1900 的年数 .tm_mon=3, // 月份 [0, 11] .tm_mday=12, // 天数 [1, 31] .tm_hour=12, // 小时 [0, 23] .tm_min=00, // 分钟 [0, 59] .tm_sec=04, // 秒数 [0, 60] .tm_isdst=-1, // 夏令时 }; time_t some_time_epoch; some_time_epoch = mktime(&some_time); // 输出 Mon Apr 12 12:00:04 1982 printf("%s", ctime(&some_time_epoch)); // 输出 Is DST: 0 printf("Is DST: %d\n", some_time.tm_isdst);difftime()difftime()用来计算两个时间之间的差异。Unix 系统上,直接相减两个 time_t 值,就可以得到相差的秒数,但是为了程序的可移植性,最好还是使用这个函数。double difftime( time_t time1, time_t time2 );difftime()函数接受两个 time_t 类型的时间作为参数,计算 time1 - time2 的差,并把结果转换为秒。注意它的返回值是 double 类型。#include <stdio.h> #include <time.h> int main(void) { struct tm time_a = { .tm_year=82, .tm_mon=3, .tm_mday=12, .tm_hour=4, .tm_min=00, .tm_sec=04, .tm_isdst=-1, }; struct tm time_b = { .tm_year=120, .tm_mon=10, .tm_mday=15, .tm_hour=16, .tm_min=27, .tm_sec=00, .tm_isdst=-1, }; time_t cal_a = mktime(&time_a); time_t cal_b = mktime(&time_b); double diff = difftime(cal_b, cal_a); double years = diff / 60 / 60 / 24 / 365.2425; // 输出 1217996816.000000 seconds (38.596783 years) between events printf("%f seconds (%f years) between events\n", diff, years); }上面示例中,折算年份时,为了尽量准确,使用了一年的准确长度 365.2425 天,这样可以抵消闰年的影响。strftime()strftime()函数用来将 struct tm 结构转换为一个指定格式的字符串,并复制到指定地址。size_t strftime( char* str, size_t maxsize, const char* format, const struct tm* timeptr )strftime()接受四个参数。第一个参数:目标字符串的指针。第二个参数:目标字符串可以接受的最大长度。第三个参数:格式字符串。第四个参数:struct tm 结构。如果执行成功(转换并复制),strftime()函数返回复制的字符串长度;如果执行失败,返回-1。下面是一个例子。#include <stdio.h> #include <time.h> int main(void) { char s[128]; time_t now = time(NULL); // %c: 本地时间 strftime(s, sizeof s, "%c", localtime(&now)); puts(s); // Sun Feb 28 22:29:00 2021 // %A: 完整的星期日期的名称 // %B: 完整的月份名称 // %d: 月份的天数 strftime(s, sizeof s, "%A, %B %d", localtime(&now)); puts(s); // Sunday, February 28 // %I: 小时(12小时制) // %M: 分钟 // %S: 秒数 // %p: AM 或 PM strftime(s, sizeof s, "It's %I:%M:%S %p", localtime(&now)); puts(s); // It's 10:29:00 PM // %F: ISO 8601 yyyy-mm-dd 格式 // %T: ISO 8601 hh:mm:ss 格式 // %z: ISO 8601 时区 strftime(s, sizeof s, "ISO 8601: %FT%T%z", localtime(&now)); puts(s); // ISO 8601: 2021-02-28T22:29:00-0800 }下面是常用的格式占位符。%%:输出 % 字符。%a:星期几的简写形式,以当地时间计算。%A:星期几的完整形式,以当地时间计算。%b:月份的简写形式,以当地时间计算。%B:月份的完整形式,以当地时间计算。%c:日期和时间,使用“%x %X”。%d:月份的天数(01-31)。%H:小时,采用24小时制(00-23)。%I:小时,采用12小时制(00-12)。%J:一年的第几天(001-366)。%m:月数(01-12)。%M:分钟(00~59)。%P:AM 或 PM。%R:相当于"%H:%M"。%S:秒(00-61)。%U:一年的第几星期(00-53),以星期日为第1天。%w:一星期的第几天,星期日为第0天。%W:一年的第几星期(00-53),以星期一为第1天。%x:完整的年月日的日期,以当地时间计算。%X:完整的时分秒的时间,以当地时间计算。%y:两位数年份(00-99)。%Y:四位数年份(例如 1984)。%Z:时区的简写。timespec_get()timespec_get()用来将当前时间转成距离时间纪元的纳秒数(十亿分之一秒)。int timespec_get ( struct timespec* ts, int base ) ;timespec_get()接受两个参数。第一个参数是 struct timespec 结构指针,用来保存转换后的时间信息。struct timespec 的结构如下。struct timespec { time_t tv_sec; // 秒数 long tv_nsec; // 纳秒 };第二个参数是一个整数,表示时间计算的起点。标准只给出了宏 TIME_UTC 这一个可能的值,表示返回距离时间纪元的秒数。下面是一个例子。struct timespec ts; timespec_get(&ts, TIME_UTC); // 1614581530 s, 806325800 ns printf("%ld s, %ld ns\n", ts.tv_sec, ts.tv_nsec); double float_time = ts.tv_sec + ts.tv_nsec/1000000000.0; // 1614581530.806326 seconds since epoch printf("%f seconds since epoch\n", float_time);clock()clock()函数返回从程序开始执行到当前的 CPU 时钟周期。一个时钟周期等于 CPU 频率的倒数,比如 CPU 的频率如果是 1G Hz,表示1秒内时钟信号可以变化 10^9 次,那么每个时钟周期就是 10^-9 秒。clock_t clock(void);clock()函数返回一个数字,表示从程序开始到现在的 CPU 时钟周期的次数。这个值的类型是 clock_t,一般是 long int 类型。 为了把这个值转换为秒,应该把它除以常量CLOCKS_PER_SEC(每秒的时钟周期),这个常量也由time.h定义。printf("CPU time: %f\n", clock() / (double)CLOCKS_PER_SEC);上面示例可以输出程序从开始到运行到这一行所花费的秒数。如果计算机无法提供 CPU 时间,或者返回值太大,无法用clock_t类型表示,clock()函数就返回-1。为了知道某个操作所耗费的精确时间,需要调用两次clock(),然后将两次的返回值相减。clock_t start = clock(); // ... 执行某些操作 clock_t end = clock(); long double seconds = (float)(end - start) / CLOCKS_PER_SEC;参考链接How to Measure Execution Time of a Program
2023年09月20日
5 阅读
0 评论
0 点赞
2023-09-20
string.h
string.hstring.h主要定义了字符串处理函数和内存操作函数。字符串处理函数以下字符串处理函数,详见《字符串》一章。strcpy():复制字符串。strncpy():复制字符串,有长度限制。strcat():连接两个字符串。strncat():连接两个字符串,有长度限制。strcmp():比较两个字符串。strncmp():比较两个字符串,有长度限制。strlen():返回字符串的字节数。strchr(),strrchr()strchr()和strrchr()都用于在字符串中查找指定字符。不同之处是,strchr()从字符串开头开始查找,strrchr()从字符串结尾开始查找,函数名里面多出来的那个r表示 reverse(反向)。char* strchr(char* str, int c); char* strrchr(char *str, int c);它们都接受两个参数,第一个参数是字符串指针,第二个参数是所要查找的字符。一旦找到该字符,它们就会停止查找,并返回指向该字符的指针。如果没有找到,则返回 NULL。下面是一个例子。char *str = "Hello, world!"; char *p; p = strchr(str, ','); // p 指向逗号的位置 p = strrchr(str, 'o'); // p 指向 world 里面 o 的位置strspn(),strcspn()strspn()用来查找属于指定字符集的字符串长度,strcspn()正好相反,用来查找不属于指定字符集的字符串长度。size_t strspn(char* str, const char* accept); size_t strcspn(char *str, const char *reject);这两个函数接受两个参数,第一个参数是源字符串,第二个参数是由指定字符组成的字符串。strspn()从第一个参数的开头开始查找,一旦发现第一个不属于指定字符集范围的字符,就停止查找,返回到目前为止的字符串长度。如果始终没有不在指定字符集的字符,则返回第一个参数字符串的长度。strcspn()则是一旦发现第一个属于指定字符集范围的字符,就停止查找,返回到目前为止的字符串长度。如果始终没有发现指定字符集的字符,则返回第一个参数字符串的长度。char str[] = "hello world"; int n; n = strspn(str1, "aeiou"); printf("%d\n", n); // n == 0 n = strcspn(str1, "aeiou"); printf("%d\n", n); // n == 1上面示例中,第一个n等于0,因为0号位置的字符h就不属于指定字符集aeiou,可以理解为开头有0个字符属于指定字符集。第二个n等于1,因为1号位置的字符e属于指定字符集aeiou,可以理解为开头有1个字符不属于指定字符集。strpbrk()strpbrk()在字符串中搜索指定字符集的任一个字符。char* strpbrk(const char* s1, const char* s2);它接受两个参数,第一个参数是源字符串,第二个参数是由指定字符组成的字符串。它返回一个指向第一个匹配字符的指针,如果未找到匹配字符,则返回 NULL。char* s1 = "Hello, world!"; char* s2 = "dow!"; char* p = strpbrk(s1, s2); printf("%s\n", p); // "o, world!"上面示例中,指定字符集是“dow!”,那么s1里面第一个匹配字符是“Hello”的“o”,所以指针p指向这个字符。输出的话,就会输出从这个字符直到字符串末尾的“o, world!”。strstr()strstr()在一个字符串里面,查找另一个字符串。char *strstr( const char* str, const char* substr );它接受两个参数,第一个参数是源字符串,第二个参数是所要查找的子字符串。如果匹配成功,就返回一个指针,指向源字符串里面的子字符串。如果匹配失败,就返回 NULL,表示无法找到子字符串。char* str = "The quick brown fox jumped over the lazy dogs."; char* p = strstr(str, "lazy"); printf("%s\n", p == NULL ? "null": p); // "lazy dogs."上面示例中,strstr()用来在源字符串str里面,查找子字符串lazy。从返回的指针到字符串结尾,就是“lazy dogs.”。strtok()strtok()用来将一个字符串按照指定的分隔符(delimiter),分解成一系列词元(tokens)。char* strtok(char* str, const char* delim);它接受两个参数,第一个参数是待拆分的字符串,第二个参数是指定的分隔符。它返回一个指针,指向分解出来的第一个词元,并将词元结束之处的分隔符替换成字符串结尾标志\0。如果没有待分解的词元,它返回 NULL。如果要遍历所有词元,就必须循环调用,参考下面的例子。strtok()的第一个参数如果是 NULL,则表示从上一次strtok()分解结束的位置,继续往下分解。#include <stdio.h> #include <string.h> int main(void) { char string[] = "This is a sentence with 7 tokens"; char* tokenPtr = strtok(string, " "); while (tokenPtr != NULL) { printf("%s\n", tokenPtr); tokenPtr = strtok(NULL, " "); } }上面示例将源字符串按照空格,分解词元。它的输出结果如下。This is a sentence with 7 tokens注意,strtok()会修改原始字符串,将所有分隔符都替换成字符串结尾符号\0。因此,最好生成一个原始字符串的拷贝,然后再对这个拷贝执行strtok()。strcoll()strcoll()用于比较两个启用了本地化设置的字符串,用法基本与strcmp()相同。int strcoll(const char *s1, const char *s2);请看下面的示例。setlocale(LC_ALL, ""); // 报告 é > f printf("%d\n", strcmp("é", "f")); // 报告 é < f printf("%d\n", strcoll("é", "f"));上面示例比较带重音符号的é与f,strcmp()会返回é大于f,而strcoll()就会正确识别é排在f前面,所以小于f。注意,在比较之前,需要使用setlocale(LC_ALL, ""),启用本地化设置。strxfrm()strxfrm()将一个本地化字符串转成可以使用strcmp()进行比较的形式,相当于strcoll()内部的第一部分操作。size_t strxfrm( char * restrict s1, const char * restrict s2, size_t n );它接受三个参数,将第二个参数s2转为可以使用strcmp()比较的形式,并将结果存入第一个参数s1。第三个参数n用来限定写入的字符数,防止超出s1的边界。它返回转换后的字符串长度,不包括结尾的终止符。如果第一个参数是 NULL,第三个参数是0,则不进行实际的转换,只返回转换后所需的字符串长度。下面的示例是用这个函数自己实现一个strcoll()。int my_strcoll(char* s1, char* s2) { int len1 = strxfrm(NULL, s1, 0) + 1; int len2 = strxfrm(NULL, s2, 0) + 1; char *d1 = malloc(len1); char *d2 = malloc(len2); strxfrm(d1, s1, len1); strxfrm(d2, s2, len2); int result = strcmp(d1, d2); free(d2); free(d1); return result; }上面示例中,先为两个进行比较的本地化字符串,分配转换后的存储空间,使用strxfrm()将它们转为可比较的形式,再用strcmp()进行比较。strerror()strerror()函数返回特定错误的说明字符串。char *strerror(int errornum);它的参数是错误的编号,由errno.h定义。返回值是一个指向说明字符串的指针。// 输出 No such file or directory printf("%s\n", strerror(2));上面示例输出2号错误的说明字符“No such file or directory“。下面的例子是自定义报错信息。#include <stdio.h> #include <string.h> #include <errno.h> int main(void) { FILE* fp = fopen("NONEXISTENT_FILE.TXT", "r"); if (fp == NULL) { char* errmsg = strerror(errno); printf("Error %d opening file: %s\n", errno, errmsg); } }上面示例中,通过strerror(errno)拿到当前的默认报错信息,其中errno是errno.h定义的宏,表示当前的报错编号。然后,再输出一条自定义的报错信息。内存操作函数以下内存操作函数,详见《内存管理》一章。memcpy():内存复制函数。memmove():内存复制函数(允许重叠)。memcmp():比较两个内存区域。memchr()memchr()用于在内存区域中查找指定字符。void* memchr(const void* s, int c, size_t n);它接受三个参数,第一个参数是内存区域的指针,第二个参数是所要查找的字符,第三个参数是内存区域的字节长度。一旦找到,它就会停止查找,并返回指向该位置的指针。如果直到检查完指定的字节数,依然没有发现指定字符,则返回 NULL。下面是一个例子。char *str = "Hello, world!"; char *p; p = memchr(str, '!', 13); // p 指向感叹号的位置memset()memset()将一段内存全部格式化为指定值。void* memset(void* s, int c, size_t n);它的第一个参数是一个指针,指向内存区域的开始位置,第二个参数是待写入的字符值,第三个参数是一个整数,表示需要格式化的字节数。它返回第一个参数(指针)。memset(p, ' ', N);上面示例中,p 是一个指针,指向一个长度为 N 个字节的内存区域。memset()将该块内存区域的每个字节,都改写为空格字符。下面是另一个例子。char string1[15] = "BBBBBBBBBBBBBB"; // 输出 bbbbbbbBBBBBBB printf("%s\n", (char*) memset(string1, 'b', 7));memset()的一个重要用途,就是将数组成员全部初始化为0。memset(arr, 0, sizeof(arr));下面是将 Struct 结构都初始化为0的例子。struct banana { float ripeness; char *peel_color; int grams; }; struct banana b; memset(&b, 0, sizeof b); b.ripeness == 0.0; // True b.peel_color == NULL; // True b.grams == 0; // True上面示例,将 Struct banana 的实例 b 的所有属性都初始化为0。其他函数void* memset(void* a, int c, size_t n); size_t strlen(const char* s);
2023年09月20日
1 阅读
0 评论
0 点赞
2023-09-20
stdlib.h
stdlib.h类型别名和宏stdlib.h 定义了下面的类型别名。size_t:sizeof 的返回类型。wchar_t:宽字符类型。stdlib.h 定义了下面的宏。NULL:空指针。EXIT_SUCCESS:函数运行成功时的退出状态。EXIT_FAILURE:函数运行错误时的退出状态。RAND_MAX:rand() 函数可以返回的最大值。MB_CUR_MAX:当前语言环境中,多字节字符占用的最大字节数。abs(),labs(),llabs()这三个函数用于计算整数的绝对值。abs()用于 int 类型,labs()用于 long int 类型,llabs()用于 long long int 类型。int abs(int j); long int labs(long int j); long long int llabs(long long int j);下面是用法示例。// 输出 |-2| = 2 printf("|-2| = %d\n", abs(-2)); // 输出 |4| = 4 printf("|4| = %d\n", abs(4));div(),ldiv(),lldiv()这三个函数用来计算两个参数的商和余数。div()用于 int 类型的相除,ldiv()用于 long int 类型的相除,lldiv()用于 long long int 类型的相除。div_t div(int numer, int denom); ldiv_t ldiv(long int numer, long int denom); lldiv_t lldiv(long long int numer, long long int denom);这些函数把第2个参数(分母)除以第1个参数(分子),产生商和余数。这两个值通过一个数据结构返回,div()返回 div_t 结构,ldiv()返回 ldiv_t 结构,lldiv()返回 lldiv_t 结构。这些结构都包含下面两个字段,int quot; // 商 int rem; // 余数它们完整的定义如下。typedef struct { int quot, rem; } div_t; typedef struct { long int quot, rem; } ldiv_t; typedef struct { long long int quot, rem; } lldiv_t;下面是一个例子。div_t d = div(64, -7); // 输出 64 / -7 = -9 printf("64 / -7 = %d\n", d.quot); // 输出 64 % -7 = 1 printf("64 %% -7 = %d\n", d.rem);字符串转成数值a 系列函数stdlib.h定义了一系列函数,可以将字符串转为数字。atoi():字符串转成 int 类型。atof():字符串转成 double 类型。atol():字符串转成 long int 类型。atoll():字符串转成 long long int 类型。它们的原型如下。int atoi(const char* nptr); double atof(const char* nptr); long int atol(const char* nptr); long long int atoll(const char* nptr);上面函数的参数都是一个字符串指针,字符串开头的空格会被忽略,转换到第一个无效字符处停止。函数名称里面的a代表 ASCII,所以atoi()的意思是“ASCII to int”。它们返回转换后的数值,如果字符串无法转换,则返回0。下面是用法示例。atoi("3490") // 3490 atof("3.141593") // 3.141593如果参数是数字开头的字符串,atoi()会只转换数字部分,比如atoi("42regular")会返回整数42。如果首字符不是数字,比如“hello world”,则会返回0。str 系列函数(浮点数转换)stdlib.h还定义了一些更强功能的浮点数转换函数。strtof():字符串转成 float 类型。strtod():字符串转成 double 类型。strtold():字符串转成 long double 类型。它们的原型如下。float strtof( const char* restrict nptr, char** restrict endptr ); double strtod( const char* restrict nptr, char** restrict endptr ); long double strtold( const char* restrict nptr, char** restrict endptr );它们都接受两个参数,第一个参数是需要转换的字符串,第二个参数是一个指针,指向原始字符串里面无法转换的部分。nptr:待转换的字符串(起首的空白字符会被忽略)。endprt:一个指针,指向不能转换部分的第一个字符。如果字符串可以完全转成数值,该指针指向字符串末尾的终止符\0。这个参数如果设为 NULL,就表示不需要处理字符串剩余部分。它们的返回值是已经转换后的数值。如果字符串无法转换,则返回0。如果转换结果发生溢出,errno 会被设置为 ERANGE。如果值太大(无论是正数还是负数),函数返回HUGE_VAL;如果值太小,函数返回零。char *inp = " 123.4567abdc"; char *badchar; double val = strtod(inp, &badchar); printf("%f\n", val); // 123.456700 printf("%s\n", badchar); // abdc字符串可以完全转换的情况下,第二个参数指向\0,因此可以用下面的写法判断是否完全转换。if (*endptr == '\0') { // 完全转换 } else { // 存在无法转换的字符 }如果不关心没有转换的部分,则可以将 endptr 设置为 NULL。这些函数还可以将字符串转换为特殊值 Infinity 和 NaN。如果字符串包含 INF 或 INFINITY(大写或小写皆可),则将转换为 Infinity;如果字符串包含 NAN,则将返回 NaN。str 系列函数(整数转换)str 系列函数也有整数转换的对应函数。strtol():字符串转成 long int 类型。strtoll():字符串转成 long long int 类型。strtoul():字符串转成 unsigned long int 类型。strtoull():字符串转成 unsigned long long int 类型。它们的原型如下。long int strtol( const char* restrict nptr, char** restrict endptr, int base ); long long int strtoll( const char* restrict nptr, char** restrict endptr, int base ); unsigned long int strtoul( const char* restrict nptr, char** restrict endptr, int base ); unsigned long long int strtoull( const char* restrict nptr, char** restrict endptr, int base );它们接受三个参数。(1)nPtr:待转换的字符串(起首的空白字符会被忽略)。(2)endPrt:一个指针,指向不能转换部分的第一个字符。如果字符串可以完全转成数值,该指针指向字符串末尾的终止符\0。这个参数如果设为 NULL,就表示不需要处理字符串剩余部分。(3)base:待转换整数的进制。这个值应该是2到36之间的整数,代表相应的进制,如果是特殊值0,表示让函数根据数值的前缀,自己确定进制,即如果数字有前缀0,则为八进制,如果数字有前缀0x或0X,则为十六进制。它们的返回值是转换后的数值,如果转换不成功,返回0。下面是转换十进制整数的例子。char* s = "3490"; unsigned long int x = strtoul(u, NULL, 10); printf("%lu\n", x); // 3490下面是转换十六进制整数的例子。char* end; long value = strtol("0xff", &end, 16); printf("%ld\n", value); // 255 printf("%s\n", end); // 无内容 value = strtol("0xffxx", &end, 16); printf("%ld\n", value); // 255 printf("%s\n", end); // xx上面示例中,strtol()可以指定字符串包含的是16进制整数。不能转换的部分,可以使用指针end进行访问。下面是转换二进制整数的例子。char* s = "101010"; unsigned long int x = strtoul(s, NULL, 2); printf("%lu\n", x); // 42下面是让函数自行判断整数进制的例子。#include <stdio.h> #include <stdlib.h> int main(void) { const char* string = "-1234567abc"; char* remainderPtr; long x = strtol(string, &remainderPtr, 0); printf("%s\"%s\"\n%s%ld\n%s\"%s\"\n", "The original string is ", string, "The converted value is ", x, "The remainder of the original string is ", remainderPtr ); }上面代码的输出结果如下。The original string is "-1234567abc" The converted value is -1234567 The remainder of the original string is "abc"如果被转换的值太大,strtol()函数在errno中存储ERANGE这个值,并返回LONG_MIN(原值为负数)或LONG_MAX(原值为正数),strtoul()则返回ULONG_MAX。rand()rand()函数用来生成 0~RAND_MAX 之间的随机整数。RAND_MAX是一个定义在stdlib.h里面的宏,通常等于 INT_MAX。// 原型 int rand(void); // 示例 int x = rand();如果希望获得整数 N 到 M 之间的随机数(包括 N 和 M 两个端点值),可以使用下面的写法。int x = rand() % (M - N + 1) + N;比如,1 到 6 之间的随机数,写法如下。int x = rand() % 6 + 1;获得浮点数的随机值,可以使用下面的写法。// 0 到 0.999999 之间的随机数 printf("0 to 0.99999: %f\n", rand() / ((float)RAND_MAX + 1)); // n 到 m 之间的随机数: // n + m * (rand() / (float)RAND_MAX) printf("10.5 to 15.7: %f\n", 10.5 + 5.2 * rand() / (float)RAND_MAX);上面示例中,由于rand()和RAND_MAX都是 int 类型,要用显示的类型转换转为浮点数。srand()rand()是伪随机数函数,为了增加随机性,必须在调用它之前,使用srand()函数重置一下种子值。srand()函数接受一个无符号整数(unsigned int)作为种子值,没有返回值。void srand(unsigned int seed);通常使用time(NULL)函数返回当前距离时间纪元的秒数,作为srand()的参数。#include <time.h> srand((unsigned int) time(NULL));上面代码中,time()的原型定义在头文件time.h里面,返回值的类型是类型别名time_t,具体的类型与系统有关,所以要强制转换一下类型。time()的参数是一个指针,指向一个具体的 time_t 类型的时间值,这里传入空指针NULL作为参数,由于 NULL 一般是0,所以也可以写成time(0)。abort()abort()用于不正常地终止一个正在执行的程序。使用这个函数的目的,主要是它会触发 SIGABRT 信号,开发者可以在程序中为这个信号设置一个处理函数。void abort(void);该函数没有参数。exit(),quick_exit(),_Exit()这三个函数都用来退出当前正在执行的程序。void exit(int status); void quick_exit(int status); void _Exit(int status);它们都接受一个整数,表示程序的退出状态,0是正常退出,非零值表示发生错误,可以使用宏EXIT_SUCCESS和EXIT_FAILURE当作参数。它们本身没有返回值。它们的区别是,退出时所做的清理工作不同。exit()是正常退出,系统会做完整的清理,比如更新所有文件流,并且删除临时文件。quick_exit()是快速退出,系统的清理工作稍微少一点。_Exit()是立即退出,不做任何清理工作。下面是一些用法示例。exit(EXIT_SUCCESS); quick_exit(EXIT_FAILURE); _Exit(2);atexit(),at_quick_exit()atexit()用来登记当前程序退出时(调用exit()或main()正常退出),所要执行的其他函数。at_quick_exit()则是登记使用quick_exit()方法退出当前程序时,所要执行的其他函数。exit()只能触发atexit()登记的函数,quick_exit()只能触发at_quick_exit()登记的函数。int atexit(void (*func)(void)); int at_quick_exit(void (*func)(void));它们的参数是要执行的函数地址,即函数名。它们的返回值都是调用成功时返回0,调用失败时返回非零值。下面是一个例子。void sign_off(void); void too_bad(void); int main(void) { int n; atexit(sign_off); /* 注册 sign_off()函数 */ puts("Enter an integer:"); if (scanf("%d", &n) != 1) { puts("That's no integer!"); atexit(too_bad); /* 注册 too_bad()函数 */ exit(EXIT_FAILURE); } printf("%d is %s.\n", n, (n % 2 == 0) ? "even" : "odd"); return 0; } void sign_off(void) { puts("sign_off"); } void too_bad(void) { puts("too bad"); }上面示例中,用户输入失败时,会调用sign_off()和too_bad()函数;但是输入成功时只会调用sign_off()。因为只有输入失败时,才会进入if语句登记too_bad()。另外,如果有多条atexit()语句,函数退出时最先调用的,是最后一个登记的函数。atexit()登记的函数(如上例的sign_off和too_bad)应该不带任何参数且返回类型为void。通常,这些函数会执行一些清理任务,例如删除临时文件或重置环境变量。at_quick_exit()也是同样的规则,下面是一个例子。void exit_handler_1(void) { printf("1\n"); } void exit_handler_2(void) { printf("2\n"); } int main(void) { at_quick_exit(exit_handler_1); at_quick_exit(exit_handler_2); quick_exit(0); }执行上面的示例,命令行会先输出2,再输出1。getenv()getenv()用于获取环境变量的值。环境变量是操作系统提供的程序之外的一些环境参数。char* getenv(const char* name);它的参数是一个字符串,表示环境变量名。返回值也是一个字符串,表示环境变量的值。如果指定的环境变量不存在,则返回 NULL。下面是输出环境变量$PATH的值的例子。printf("PATH is %s\n", getenv("PATH"));system()system()函数用于执行外部程序。它会把它的参数字符串传递给操作系统,让操作系统的命令处理器来执行。void system( char const * command );这个函数的返回值因编译器而异。但是标准规定,如果 NULL 作为参数,表示询问操作系统,是否有可用的命令处理器,如果有的话,返回一个非零值,否则返回零。下面是执行ls命令的例子。system("ls -l"); 内存管理函数stdlib.h 提供了一些内存操作函数,下面几个函数详见《内存管理》一章,其余在本节介绍。malloc():分配内存区域calloc():分配内存区域。realloc():调节内存区域大小。free():释放内存区域。aligned_alloc()很多系统有内存对齐的要求,即内存块的大小必须是某个值(比如64字节)的倍数,这样有利于提高处理速度。aligned_alloc()就用于分配满足内存对齐要求的内存块,它的原型如下。void* aligned_alloc(size_t alignment, size_t size);它接受两个参数。alignment:整数,表示内存对齐的单位大小,一般是2的整数次幂(2、4、8、16……)。size:整数,表示内存块的大小。分配成功时,它返回一个无类型指针,指向新分配的内存块。分配失败时,返回 NULL。char* p = aligned_alloc(64, 256);上面示例中,aligned_alloc()分配的内存块,单位大小是64字节,要分配的字节数是256字节。qsort()qsort()用来快速排序一个数组。它对数组成员的类型没有要求,任何类型数组都可以用这个函数排序。void qsort( void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *) );该函数接受四个参数。base:指向要排序的数组开始位置的指针。nmemb:数组成员的数量。size:数组每个成员占用的字节长度。compar:一个函数指针,指向一个比较两个成员的函数。比较函数compar将指向数组两个成员的指针作为参数,并比较两个成员。如果第一个参数小于第二个参数,该函数应该返回一个负值;如果两个函数相等,返回0;如果第一个参数大于第二个参数,应该返回一个正数。下面是一个用法示例。#include <stdio.h> #include <stdlib.h> int compar(const void* elem0, const void* elem1) { const int* x = elem0; const int* y = elem1; return *x - *y; } int main(void) { int a[9] = {14, 2, 3, 17, 10, 8, 6, 1, 13}; qsort(a, 9, sizeof(int), compar); for (int i = 0; i < 9; i++) printf("%d ", a[i]); putchar('\n'); }执行上面示例,会输出排序好的数组“1 2 3 6 8 10 13 14 17”。bsearch()bsearch()使用二分法搜索,在数组中搜索一个值。它对数组成员的类型没有要求,任何类型数组都可以用这个函数搜索值。注意,该方法只对已经排序好的数组有效。void *bsearch( const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void *, const void *) );这个函数接受5个参数。key:指向要查找的值的指针。base:指向数组开始位置的指针,数组必须已经排序。nmemb:数组成员的数量。size:数组每个成员占用的字节长度。compar:指向一个将待查找值与其他值进行比较的函数的指针。比较函数compar将待查找的值作为第一个参数,将要比较的值作为第二个参数。如果第一个参数小于第二个参数,该函数应该返回一个负值;如果两个参数相等,返回0;如果第一个参数大于第二个参数,返回一个正值。如果找到待查找的值,bsearch()返回指向该值的指针,如果找不到,返回 NULL。下面是一个用法示例。#include <stdio.h> #include <stdlib.h> int compar(const void *key, const void *value) { const int* k = key; const int* v = value; return *k - *v; } int main(void) { int a[9] = {2, 6, 9, 12, 13, 18, 20, 32, 47}; int* r; int key; key = 12; // 包括在数组中 r = bsearch(&key, a, 9, sizeof(int), compar); printf("Found %d\n", *r); key = 30; // 不包括在数组中 r = bsearch(&key, a, 9, sizeof(int), compar); if (r == NULL) printf("Didn't find 30\n"); return 0; }执行上面的示例,会输出下面的结果。Found 12 Didn't find 30多字节字符函数stdlib.h 提供了下面的函数,用来操作多字节字符,详见《多字节字符》一章。mblen():多字节字符的字节长度。mbtowc():将多字节字符转换为宽字符。wctomb():将宽字符转换为多字节字符。mbstowcs():将多字节字符串转换为宽字符串。wcstombs():将宽字符串转换为多字节字符串。
2023年09月20日
6 阅读
0 评论
0 点赞
1
...
5
6
7
...
35