C语言中的一些函数
文章目录
1. 退出处理函数之exit() 与 _exit() 函数
正常情况下,进程终止,文件关闭,缓冲区的内容会被写到内核。
exit 会先执行一些清除处理,然后进入内核,清除操作包括执行各种终止处理程序,关闭所有标准 I/O 流,_exit会直接进入内核
。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("hello");
exit(0);
return 0;
}
打印出hello
lh@ubuntu:~/1231$ ./a.out
hellolh@ubuntu:~/1231$
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("hello");
_exit(0);
return 0;
}
什么都不打印
lh@ubuntu:~/1231$ ./a.out
lh@ubuntu:~/1231$
2. alarm 定时函数
alarm 定时,产生一个中断终止程序。
alarm 也称为闹钟函数,它可以再进程中设置一个定时器,当到达定时器指定的时间,它向进程发送 SIGALARM 信号。要注意的是,一个进程只能有一个闹钟时间
,如果在调用alarm之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。
当在调用 alarm() 前已经设置了一个闹钟,那么我们可以调用**alarm(0)**来取消此闹钟,并返回剩余时间.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ret;
ret = alarm(3);
while(1)
{
//延时1s
sleep(1);
//usleep() 微秒延时
printf("one second passed\n");
}
}
运行
one second passed
one second passed
闹钟
3. system 函数
system函数执行一个系统命令,这里是清屏操作。
#include <stdio.h>
#include <unistd.h>
int main()
{
system("clear");
printf("helloworld\n");
return 0;
}
运行
helloworld
lh@ubuntu:~/1231$
#include <stdio.h>
#include <unistd.h>
int main()
{
char cmd [] = {"/bin/ls -l"};
system(cmd);
return 0;
}
运行
效果相当于在shell中输入ls -l命令
4. 退出处理函数与登记函数 atexit
一个进程可以登记多至 32 个函数,这些函数将 由exit自动调用,atexit 的参数是一个函数地址,调用此函数时无需向它传送任何参数,也不期望它返回一个值,exit以登记这些函数的 相反顺序 调用它们,类似栈,先登记的后处理。
#include <stdlib.h>
#include <stdio.h>
static void my_exit1(void)
{
printf("first exit handler \n");
}
static void my_exit2(void)
{
printf("second exit handler \n");
}
int main(void)
{
//进行函数登记
if(atexit(my_exit2)!=0)
printf("can't register myexit2\n");
if(atexit(my_exit1)!=0)
printf("can't register myexit1");
printf("main is done \n");
return 0;
}
main is done
first exit handler
second exit handler
5. sprintf 函数
sprintf 与 printf 函数的区别:二者功能相似,但是输出的位置不同,sprintf 函数打印到 字符串 (字符数组),而 printf 函数打印输出到 屏幕 上。
sprintf 函数在我们完成其他数据类型转换成字符串类型
的操作中应用广泛。只要在 printf 中可以使用的格式化字符串,在 sprintf 都可以使用。其中的格式化字符串是此函数的精华。
#include <stdio.h>
int main()
{
char buf[50];
sprintf(buf,"%d",500);
printf("%s\n",buf);
}
lh@ubuntu:~/1230$ ./a.out
500
#include <stdio.h>
int main()
{
char buf[50];
sprintf(buf,"0x%x",500);
printf("%s\n",buf);
}
lh@ubuntu:~/1230$ ./a.out
0x1f4
#include <stdio.h>
int main()
{
char buf[50];
sprintf(buf,"%s love %s","I","YOU");
printf("%s\n",buf);
}
lh@ubuntu:~/1230$ ./a.out
I love YOU
6. printf 函数与 \n
系统有一个缓冲区的机制,printf 函数只有当 buffer 缓冲区满或者有 \n 时才会输出内容。当然程序结束的时候也会输出。
#include <stdio.h>
int main()
{
printf("hello");
while(1)
{
;
}
}
没有输出
#include <stdio.h>
int main()
{
printf("hello");
while(1)
{
;
}
}
lh@ubuntu:~/1230$ ./a.out
hello
//光标在此行闪烁
7. fgets 函数
char *fgets(char *buf, int bufsize, FILE *stream);
fgets 函数,从文件结构体指针 stream 中读取数据,每次读取一行。读取的数据保存在 buf 指向的字符数组中,每次最多读取 bufsize-1 个字符(第 bufsize 个字符赋'\0'
)。
- 如果文件中的该行,不足 bufsize 个字符,则读完该行就结束。
- 如若该行(包括最后一个换行符)的字符数超过 bufsize-1 ,则 fgets 只返回一个 不完整 的行,但是,缓冲区 buf 总是以 NULL 字符结尾,对 fgets 的下一次调用会继续读该行。函数成功将返回 buf ,失败或读到文件结尾返回 NULL 。
因此我们不能直接通过 fgets 的返回值来判断函数是否是出错而终止的,应该借助 feof 函数或者 ferror 函数来判断。
下面是验证程序:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#define BUFSIZE 1024
int main()
{
FILE *fp;
char *cmd = "printenv"; //printenv可以打印所有的环境变量,在这里只打印包含PATH的变量
char buf[BUFSIZE];
buf[BUFSIZE-1] = '\0';
if((fp=popen(cmd,"r")) == NULL)
{
//管道中数据流的方向是由第二个参数控制的,可以是r或w,这里是r,
perror("popen"); //管道会以读的方式打开
}
while((fgets(buf,BUFSIZE,fp)) != NULL)
{
if(strstr(buf,"PATH")) //strstr函数是检查buf中是否有“PATH”
{
printf("%s",buf);
}
}
pclose(fp);
exit(0);
}
lh@ubuntu:~/0102$ ./a.out //红色PATH是为了观看方便加的,实际结果是灰色
MANDATORY_PATH
=/usr/share/gconf/gnome.mandatory.path
DEFAULTS_PATH
=/usr/share/gconf/gnome.default.path
PATH
=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
将 BUFSIZE 的值修改为 10
_PATH=/usPATH=/usrPATH=/usrlh@ubuntu:~/libingxuan$ //长度都是9
在 BUFSIZE 修改为 10 的基础上将 strstr 函数注释掉
LESSOPEN=| /usr/bin/lesspipe %s
GDM_KEYBOARD_LAYOUT=us
USER=lh
SSH_AGENT_PID=1580
SHLVL=1
ORBIT_SOCKETDIR=/tmp/orbit-lh
OLDPWD=/home/lh
HOME=/home/lh
DESKTOP_SESSION=gnome
XDG_SESSION_COOKIE=bc16201ab626f343740e28ba509d143a-1533265571.786839-1264316423
GTK_MODULES=canberra-gtk-module
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-kcQlVyD6nD,guid=f6f94cf8927fa974e0019d835b63c6a4
COLORTERM=gnome-terminal
GNOME_KEYRING_CONTROL=/tmp/keyring-yTUgGP
MANDATORY_PATH=/usr/share/gconf/gnome.mandatory.path
GTK_IM_MODULE=ibus
LOGNAME=lh
_=./a.out
WINDOWID=67108867
DEFAULTS_PATH=/usr/share/gconf/gnome.default.path
USERNAME=lh
TERM=xterm
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
GDM_LANG=zh_CN.utf8
SESSION_MANAGER=local/ubuntu:@/tmp/.ICE-unix/1268,unix/ubuntu:/tmp/.ICE-unix/1268
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
DISPLAY=:0.0
LANG=zh_CN.utf8
可以得出结论 fgets 当待读取一行的长度大于缓冲区时,会读取 BUFSIZE-1 的长度,之后如果还进行 fgets 操作会从上次读取的位置继续读,直到遇到 ‘\n’。