C语言:常用函数
这是很基础的教程,我只是写给自己看,作为一个学习笔记记录一下,如果正在阅读的你觉得简单,请不要批评,可以关掉选择离开
如何学好一门编程语言
- 掌握基础知识,为将来进一步学习打下良好的基础。
- 上机实践,通过大量的例题学习怎么设计算法,培养解题思路。
- 养成良好的编码习惯,注释一定要写,要不然保你一周后自己写的代码都不认识了
像 stdio.h 这样经常使用的标准库就不介绍了
随机数
#include <stdlib.h> int rand (void);
rand() 会随机生成一个位于 0 ~ RAND_MAX 之间的整数。RAND_MAX 是 <stdlib.h> 头文件中的一个宏,它用来指明 rand() 所能返回的随机数的最大值 32767。
#include <stdio.h> #include <stdlib.h> int main(){ int a = rand(); printf("%d\n",a); // 193 return 0; }
设置随机数种子
但是,我们每次运行上面的代码生成的随机数都一样,虽然随机数种子在每次启动计算机时是随机的,但是一旦计算机启动以后它就不再变化了;也就是说,每次启动计算机以后,种子就是定值了,所以生成的随机数就是固定的。通过 srand() 函数来重新“播种”,这样种子就会发生改变。
void srand (unsigned int seed);
它需要一个 unsigned int 类型的参数。在实际开发中,我们可以用时间作为参数,只要每次播种的时间不同,那么生成的种子就不同,最终的随机数也就不同。
使用 <time.h> 头文件中的 time() 函数即可得到当前的时间(精确到秒),就像下面这样:
srand((unsigned)time(NULL));
对上面的代码进行修改,生成随机数之前先进行播种:
#include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int a; srand((unsigned)time(NULL)); a = rand(); printf("%d\n", a); return 0; }
生成一定范围内的随机数
利用取模的方法产生一定范围的随机数
int a = rand() % 10; //产生0~9的随机数,注意10会被整除
如果要规定上下限:
int a = rand() % 51 + 13; //产生13~63的随机数
分析:取模即取余, rand()%51+13 我们可以看成两部分, rand()%51 是产生0~50之间的随机数,后面+13保证 a 最小只能是 13,最大就是 50+13=63。
连续生成随机数
有时候我们需要一组随机数(多个随机数),该怎么生成呢?很容易想到的一种解决方案是使用循环,每次循环都重新播种,请看下面的代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int a, i;
//使用for循环生成10个随机数
for (i = 0; i < 10; i++) {
srand((unsigned)time(NULL));
a = rand();
printf("%d ", a); // 8 8 8 8 8 8 8 8 8 8
}
return 0;
}
运行结果非常奇怪,每次循环我们都重新播种了呀,为什么生成的随机数都一样呢?
这是因为,for 循环运行速度非常快,在一秒之内就运行完成了,而 time() 函数得到的时间只能精确到秒,所以每次循环得到的时间都是一样的,这样一来,种子也就是一样的,随机数也就一样了。
那么,该如何解决呢?
计时功能
在 Linux/Unix 环境下,计算 C 程序运行时间可以通过time.h头文件中以下三个函数来实现: clock() 、 time() 、 gettimeofday() 。
clock()函数
clock() 函数返回的是时钟计时单元数(俗称硬件滴答数),要换算成秒或者毫秒,需要用到 CLOCKS_PER_SEC 常量(或者CLK_TCK
常量,两者其实一样),该常量表示一秒钟会有多少个时钟计时单元。
#include <time.h> #include <stdio.h> int main(){ clock_t start, finish; double duration; long i = 100000000; start = clock(); // 开始计数 while (i--); // 处理函数 finish = clock(); // 结束计数 duration = (double)(finish-start)/CLOCKS_PER_SEC; printf("%f seconds\n", duration); // 0.125000 seconds return 0; }
注意事项:
- 它返回的是 CPU 耗费在本程序上的时间。也就是说,途中 sleep 的话,由于 CPU 资源被释放,那段时间将不被计算在内。因此,若函数中存在
sleep()
函数,则sleep()
函数消耗的时间将不包含在内; - 这个函数的精度不适很高,大约10ms,低精度的程序全部输出 0ms。像计算
printf()
之类的调用时间是不可能实现的,因为printf()
的速度太快了,基本上和clock()
的速度一样。所以,此函数适合用于计算一些大型程序,或循环程序。 - 如果超过一个小时,将要导致溢出
- 函数clock没有考虑CPU被子进程使用的情况
- 也不能区分用户空间和内核空间
- 所以clock函数在linux系统上变得没有意义
time()函数
time()
函数返回当前日历时间。就是用“从一个标准时间点(一般是1970年1月1日0时0分0秒)到当今时间经过的秒数”来表示的时间。其原型为:
time_t time(time_t * timer);
如果参数为空(NULL),函数将返回现在的日历时间,比如下面这个例子用来显示当前的日历时间:
#include <time.h> #include <stdio.h> int main(){ time_t t; t=time(NULL); printf("1970年1月1日以来的秒数: %ld",t); // 1634915031 return 0; }
也可以利用time()
函数计算某段程序的运行时间:
#include <time.h> #include <stdio.h> #include <unistd.h> int main(){ time_t t1,t2; time(&t1); //此处放置要测试的代码 sleep(1);//延时 1 秒 time(&t2); printf("本程序运行时间: %d",t2-t1); // 1 return 0; }
gettimeofday() 函数
gettimeofday()
的函数原型为:
#include <sys/time.h>
int gettimeofday(struct timeval*tv, struct timezone *tz )
gettimeofday()
会把目前的时间用 tv 结构体返回,当地时区的信息则放到 tz 所指的结构中。其结构体定义为:
struct timeval { long tv_sec;/*秒*/ long tv_usec;/*微妙*/ }; struct timezone { int tz_minuteswest;/*和greenwich 时间差了多少分钟*/ int tz_dsttime;/*type of DST correction*/ };
在gettimeofday()
函数中 tv 或者 tz 都可以为空。如果为空则就不返回其对应的结构体。函数执行成功后返回 0,失败后返回 -1,错误代码存于 errno 中。
#include <sys/time.h> #include <stdio.h> int main() { struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); printf("tv_sec:%ld\n",tv.tv_sec); // 1634915650 printf("tv_usec:%ld\n",tv.tv_usec); // 848136 printf("tz_minuteswest:%d\n",tz.tz_minuteswest); printf("tz_dsttime:%d\n",tz.tz_dsttime); return 0; }
在使用gettimeofday()
函数时,第二个参数一般都为空,因为我们一般都只是为了获得当前时间,而不用获得 timezone 的数值。
也可利用此函数计算某段程序的运行时间:
#include <sys/time.h> #include <stdio.h> int main() { struct timeval start; struct timeval end; unsigned long timer; gettimeofday(&start, NULL); printf("hello world!\n"); gettimeofday(&end, NULL); timer = 1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec; printf("timer = %ld us\n", timer); // timer = 328 us return 0; }
gettimeofday()
函数的计算精度为微秒,精度已经很高了。
综上所述,gettimeofday()
函数的精度最高,为微秒级别;clock()
函数的精度次之,为 10ms 级别;time()
函数的精度最低,为 1s 级别。
其他
整数转字符串
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> char *Int2String(int num, char *str) { //指示填充str int i = 0; //如果num为负数,将num变正 if (num < 0) { num = -num; str[i++] = '-'; } //转换 do { str[i++] = num % 10 + 48;//取num最低位 字符0~9的ASCII码是48~57;简单来说数字0+48=48,ASCII码对应字符'0' num /= 10;//去掉最低位 } while (num);//num不为0继续循环 str[i] = '\0'; //确定开始调整的位置 int j = 0; //如果有负号,负号不用调整 if (str[0] == '-') { j = 1;//从第二位开始调整 ++i;//由于有负号,所以交换的对称轴也要后移1位 } //对称交换 for (; j < i / 2; j++) { //对称交换两端的值 其实就是省下中间变量交换a+b的值:a=a+b;b=a-b;a=a-b; str[j] = str[j] + str[i - 1 - j]; str[i - 1 - j] = str[j] - str[i - 1 - j]; str[j] = str[j] - str[i - 1 - j]; } return str; } int main() { int number1 = 0xac2031; int number2 = -123456; char string[16] = {0}; Int2String(number1, string); printf("数字:%d 转换后的字符串为:%s\n", number1, string); // 数字:11280433 转换后的字符串为:11280433 Int2String(number2, string); printf("数字:%d 转换后的字符串为:%s\n", number2, string); // 数字:-123456 转换后的字符串为:-123456 return 0; }
pcm拼接
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <string.h> int main(int arvc, char *argv[]) { FILE *wavtxt; FILE *pcmfile; FILE *wavfile; unsigned long read_len; char base[1000]={0}; char *buf[1024]; wavtxt = fopen("../wavlist.txt", "r"); if (wavtxt == NULL) { printf("!Error: Can't open wavlist.txt.\n"); return 1; } pcmfile = fopen("../clear.pcm", "wb"); if (pcmfile == NULL) { printf("!Error: Can't open clear.pcm.\n"); return 1; } // feof() 判断指针是否已经到达文件尾部的 while (!feof(wavtxt)) { fscanf(wavtxt,"%s\n",base); printf("%s\n", base); wavfile = fopen(base, "rb"); if (wavfile == NULL) { printf("!Error: Can't open %s.\n", base); return 1; } fseek(wavfile, 44, SEEK_SET); // 将文件指针移动到文件开头,后移44字节 while ((read_len = fread(buf, 1, sizeof(buf), wavfile)) != 0) { fwrite(buf, 1, read_len, pcmfile); } fclose(wavfile); } fclose(wavtxt); fclose(pcmfile); }
参考
相关文章
- 实践案例丨基于ModelArts AI市场算法MobileNet_v2实现花卉分类
- 美女面试官问我Python如何优雅的创建临时文件,我的回答....
- 绝了,华为云服务器“The 3”出道,每款都很能打
- Volcano火山:容器与批量计算的碰撞
- 【华为云技术分享】LiteOS无法直接烧录或者烧录失败解决方法--ST-Link
- 快速了解云原生中的微服务应用(内含福利)
- 从软件开发到 AI 领域工程师:模型训练篇
- 【福利活动】华为云“上云之路”征文大赛开启,FreeBuds3无线耳机等重磅好礼送不停
- 【儿童节特辑】风格迁移——让你的照片秒变手绘日漫风
- 【极客思考】计算机网络:Wireshark抓包分析TCP中的三次握手与四次挥手
- 低代码开发平台发展趋势:低代码——炒作还是趋势?
- 我们谈自动驾驶网络到底在谈什么?
- 【昇腾】ModelArts与Atlas 200 DK云端协同开发——行人检测Demo(完整版)
- 疫情数据背后,聊聊数据分析平台变迁史
- 华为五大专家亲述:如何转型搞 AI?
- 【华为云技术分享】LwM2M协议的学习与分享
- Serverless架构的前世今生
- 【华为云技术分享】STM32L476移植华为LiteOS系列教程(二)---开发前准备
- 8分钟为你详解React、Angular、Vue三大前端技术
- 【华为云技术分享】云容器引擎 CCE权限管理实践