C 常用库
时间: <time.h>
------------------------------------------------------------------------------------------------
时间戳
time_t t = time( NULL );//时间戳
得到时间戳结构体:
struct tm* tm1 =gmtime(&t);//根据时间戳得到一个标准时间结构体
struct tm* tm1 = localtime(&t);//根据时间戳得到一个tm本地时间结构体
固定格式日期:
ctime (const time_t*);
指定格式日期:
strftime (char*, size_t, const char*, const struct tm*);//返回写入char的字节数
根据结构体tm得到时间戳:
time_t mktime (struct tm*);
得到连个时间戳的差值:
difftime (time_t, time_t);
设置时区:
tzset();
时区变量:
timezone
=============================================================
不定参数:<stdarg.h>
------------------------------------------------------------------------------------------------
va_list //存储临时变量的堆
辅助获取参数的宏:
//va_stars的第二个参数:1.参数数量,标准C.2.最后一个确定参数
va_start(va_list,args_number);//初始化堆,把函数调用时候的内存拷贝到va_list
va_arg(va_list,var_type);//根据先进先出原则,重复调用来获取参数
va_end(va_list);//结束调用时清理va_list所占的内存
使用过程:
先定义一个va_list 变量,调用va_start 填充va_list变量,
循环调用va_arg得到变量,结束清理va_list所占内存
1.标准C,因为参数数量知道,所以可以使用for();
2.参数数量不清楚,使用while(1){ para = va_arg( argp, char); if ( strcmp( para, "") == 0 ) break; }
或者: vsprintf( printbuf, fmt, va_list ); fmt 为最后一个确定参数
=============================================================
信号 <signal.h>
------------------------------------------------------------------------------------------------
信号处理回调函数定义:void (*fun)(int);
signal(int, __p_sig_fn_t); //参数 信号,处理回调函数
函数signal定义:void (* signal (int signo, void (*func) (int) )) (int );
raise (int);//参数 信号
=============================================================
常用函数 <stdlib.h>
------------------------------------------------------------------------------------------------
int *a=calloc(3,sizeof(int));//分配连续内存空间
int *a=malloc(sizeof(int));//分配指定大小内存空间
int *a=realloc(a,sizeof(int)*3);//调整内存空间,一般大调小使用,小调大会先释放原内存重新申请
free(a);//释放内存;
exit;//正常停止
abort();//异常停止
int a=rand();//返回一个随机整数
char *a=getenv("PATH");//得到一个环境变量
putenv("VAR=VALUE");//增加环境变量
//数字字符操作 start
int a=labs(-10);//绝对值
//以下3个非标准C函数
float a=atof("10.1");//字符串转浮点
int a=atoi("10");//字符串转整形
long int a=atol("10");//字符串转整形
//浮点转字符
double value= 86.789e5;
int dec, sign;
int ndig = 5;
char *p = ecvt(value,ndig,&dec,&sign);
//参数:浮点数,要转换的位数,小数点的位置(返回),正或负数(返回)
//返回:连续的字符串,无小数点
char *p = fcvt(value,ndig,&dec,&sign);//跟上面一样,但结果会四舍五入
//整形转字符
string[10];
itoa(int, string*, 10);//整数,存储的字符串,整数进制(2,10等) 后面没有\0结束
//数字字符操作 end
//简便方法 兼容ANSI C
int a;
sscanf("2006", "%d", &a);//字符转数值
char m[10];
sprintf(m,"%d",a);//数值转字符
printf("%s",m);
sprintf(m,"%0x",a);//数值转十六进制字符
=============================================================
标准IO操作 <stdio.h>
------------------------------------------------------------------------------------------------
sprintf(str*,const *str,...);//其他类型转为字符串,或字符串格式化,第一个参数为转后保存指针
snprintf (char *, size_t, const char *, ...);//安全的版本,介绍见上一行
fprintf(FILE *file,const *str,...);//格式化输出到文件
printf(const *str,...);//格式化输出控制台
变量参数列表vs_list 配套的上面三函数,va_list为strarg中,见上面的strarg.
vsprintf(str*,const *str,va_list);//其他类型转为字符串,或字符串格式化,第一个参数为转后保存指针
vasprintf(str**, fmt, *fmt,va_list);//将va_list的字符串为一个字符串,并返回该字符串的指针,onlylinux
vsnprintf (char *, size_t, const char *,va_list);//安全的版本,介绍见上一行
vfprintf(FILE *file,const *str,va_list);//格式化输出到文件
vprintf(const *str,va_list);//格式化输出控制台
sscanf (const char*, const char*, ...);//字符串转化为其他类型,参数:字符串,格式化字符,输出值指针
fscanf (FILE*, const char*, ...);//格式化文件读取
scanf (const char*, ...);//控制台输入
FILE* 结构体,为文件打开指针,标准输入输出等均为该类型.(大部分平台为整形值)
FILE* f=fopen("filename","a");//打开文件
FILE* f=freopen("filename","a",stdin);//重新向打开流
//文件内操作
fseek (FILE*, long, int);//定向文件流的指针到指定位置 参数 :文件指针,偏移位置(long),位置:SEEK_SET,SEEK_CUR,SEEK_END
ftell (FILE*);//得到文件流指针的位置,long返回值
rewind (FILE*)//定向文件流指针到文件头部 = fseek(FILE*, 0, SEEK_SET);
fgetpos (FILE*, fpos_t*);//取得文件流指针的位置
fsetpos (FILE*, fpos_t*);//设置文件流指针的位置
feof (FILE*);//文件流是否到了文件底部
//文件内操作
fflush(FILE* f);//缓冲区的内容强制刷入文件
fclose (FILE*)//关闭流
ferror (FILE*);//操作文件发生错误时候使用
clearerr (FILE*);//清理操作文件时候发生的错误
rename(const char *,const char*);//改文件名
remove(const char *);//删除一个文件
FILE* f=tmpfile();//得到一个临时文件
tmpnam(char *tempname);//得到一个唯一的文件名
setbuf(FILE *f,char *);//设置缓存区,进行FILE IO的时候缓存文件数据保存地方
//前两参数跟上面一样,mode 为缓存模式(_IOFBF,_IOLBF,_IONBF),size 为缓存大小
int setvbuf(FILE *stream, char *buf, int mode, unsigned size);
//以下两函数二进制安全,如直接写数组等
fread(void *,size_t 数据块大小,size_t 数据块数量,FILE* f);//读文件
fwrite(const void*, size_t 数据块大小, size_t 数据块数量, FILE*);//写文件
=============================================================
进程信号处理<sys/wait.h>
------------------------------------------------------------------------------------------------
pid_t wait(int *status);
//参数:监听的子进程或-1(最后一个发出信号的子进程,信号处理得到子进程用),状态指针(返回检查用),选项:如WNOHANG
//返回:监听的子进程ID,或出错时候返回-1
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
介绍:http://lobert.iteye.com/blog/1705164
=============================================================
POSIX操作(only *unix) <unistd.h> <sys/types.h>
------------------------------------------------------------------------------------------------
//管道,管道适用IO操作,用于父子,或邻居进程间的通信,单通道.
int pipe_fd[2]; //存储管道指针 :0表示读管道,1表示写管道
if(pipe(pipe_fd)<0)//返回值小于0说明管道创建失败
//单独管道创建没有意义,必须配合fock等进程创建函数
pid_t pid;
if((pid=fork())==0){//派生的时,会产生内存拷贝,而管道,网络连接等会拷贝一个指针副本,系统管理计数.
//此处表示子进程
close(pipe_fd[1]);//关闭写管道
sleep(3);//确保父进程管道内信息
r_num=read(pipe_fd[0],r_buf,100);
printf( "read num is %d the data read from the pipe is %d ",r_num,atoi(r_buf));
close(pipe_fd[0]);//关闭读管道
}else if(pid>0){
//此处表示父进程,父进程可以得到子进程ID
close(pipe_fd[0]);//关闭父端的读管道
strcpy(w_buf,"111");
if(write(pipe_fd[1],w_buf,4)!=-1)//写管道信息,等待子进程去读取
printf("parent write over ");
close(pipe_fd[1]);//关闭写管道
sleep(10);//等待子进程读完数据并写出来
}
pread (int __fd, void *__buf, size_t __nbytes,__off_t __offset);//
pwrite (int __fd, __const void *__buf, size_t __n,__off_t __offset);
pipe (int __pipedes[2]);//通道
lseek (int __fd, __off_t __offset, int __whence) ;//偏移
alarm (unsigned int __seconds);//闹钟函数,它可以在进程中设置一个定时器,当定时器指定的时间到时,它向进程发送SIGALRM信号
sleep (unsigned int __seconds);//秒暂停
usleep (__useconds_t __useconds);//毫秒暂停
pause (void);//暂停
chown (__const char *__file, __uid_t __owner, __gid_t __group);//更改文件权限
chdir (__const char *__path);//改根目录
dup (int __fd); or dup2 (int __fd, int __fd2);//复制文件描述符
exe*系列:execve fexecve execv execle execl execvp execlp
第5个字符 l 表示参数列表 v 表示参数数组
第6个字符 e 表示指定文件 p 表示从环境中找
execve 内核级调用
execlp execvp 从环境变量找执行文件
execl execle 指定执行文件 此!!!新的环境变量数组即成为新执行进程的环境变量!!!
sysconf (int __name);//得到系统信息
getpid (void);//进程ID
getppid (void);//父进程ID
fork (void);//创建进程
isatty (int __fd);
link (__const char *__from, __const char *__to);
unlink (__const char *__name); //删文件
rmdir (__const char *__path);//删目录
gethostname (char *__name, size_t __len);
chroot (__const char *__path);
daemon (int __nochdir, int __noclose);
getpagesize (void);//页大小
getdtablesize (void);
sync (void);//缓存写入系统
dome:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/wait.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #define LEN 100 void str_to(int cs,struct sockaddr * addr,int addr_len){ char a[LEN]="aaaaa\n"; //read(cs,a,LEN); printf("%s",a); int i=1000; for(;i>0;i--){ write(cs,a,strlen(a)); sleep(1); } } void sigpro(int *sig){ pid_t t; while((t=waitpid(-1,NULL,WNOHANG))>0){ printf("c:%d\n",t); } } int main() { signal(SIGCHLD,&sigpro); int s,cs; s=socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in add,cadd; memset(&add,0,sizeof(add)); memset(&add,0,sizeof(cadd)); add.sin_family=AF_INET; add.sin_port=htons(8012); inet_pton(AF_INET ,"127.0.0.1", &add.sin_addr);//sockaddr_in.sin_addr 是结构体 ,不是结构体指针 bind(s,(struct sockaddr*)&add,sizeof(add)); listen(s,5); while(1){ int clen; cs=accept(s,(struct sockaddr*)&cadd,&clen); pid_t t; t=fork(); if(t==0){ str_to(cs,(struct sockaddr *)&cadd,clen);
close(cs); exit(1); }else{
close(cs);
} } return 1; }
取得域名的IP:
#include <netdb.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> int main(int arg,char *args[]) { struct addrinfo k,*pk; memset(&k,0,sizeof(struct addrinfo)); k.ai_family=AF_UNSPEC; k.ai_socktype=SOCK_STREAM; k.ai_flags=AI_PASSIVE; char o[100]; int gai; char *r; if(arg<=1){ exit(0); } /*第4个参数是指向addrinfo结构指针的指针 原理:getaddrinfo函数会根据传入的条件申请内存并创建addrinfo结构体 在根据第4个参数传入的指针的指针,得到指向指向addrinfo的指针,并修改该值指向创建好的结构体 因为在函数内部申请的内存,所以不需要addrinfo的时候需要调用freeaddrinfo()释放内存;*/; gai=getaddrinfo(args[1],"80",&k,&pk); if(gai!=0){ printf("error:%s",gai_strerror(gai)); exit(0); } printf("domain:%s\n",args[1]); void * sockaddr=NULL; while(pk){ switch(pk->ai_family){ case AF_INET: sockaddr=&((struct sockaddr_in *)pk->ai_addr)->sin_addr;//sockaddr_in.sin_addr 是结构体 ,不是结构体指针 break; case AF_INET6: sockaddr=&((struct sockaddr_in6*)pk->ai_addr)->sin6_addr;//sockaddr_in.sin6_addr 是结构体 ,不是结构体指针 break; } if(sockaddr){ inet_ntop(pk->ai_family,sockaddr,o,100);//第2个参数需要的是sockaddr指针,不是结构体 if(r!=NULL){ printf("ip address:%s & ip type:%d\n",o,(pk->ai_family==AF_INET)?4:6); } } sockaddr=NULL; pk=pk->ai_next; } freeaddrinfo(pk); }