C语言常用库函数

 

    常用string库函数、printf打印文件名行号、sprintf拼接、时间字符串和时间戳互相转换

 

一、字符串的复制比较用strcpy或strncpy,strcmp(如果用如下函数比较(memcmp)则会出错)

    

代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 #define debug_msg(fmt,...) printf("%s[%d]:"fmt,__FILE__,__LINE__,##__VA_ARGS__)
 5 
 6 #define printf_my(fmt, ...) printf("%s %s %s %s %d:"fmt, __FILE__, __FUNCTION__, __DATE__, __TIME__, __LINE__, ##__VA_ARGS__)
 7 
 8 int main(void)
 9 {
10     char str1[10]={"ABCD"};
11     char str2[100]={"ABCD"};
12     
13     char str3[10]={"ABCD"};
14     char str4[100]={"ABCD"};
15     
16     int i=0;
17     int ret =0; 
18     
19     ret=memcmp(str2,str1,sizeof(str2));
20 
21     i = strcmp(str4,str3);
22     
23     debug_msg("ret:%d,i:%d\n",ret,i);
24     printf_my("ret:%d,i:%d\n",ret,i);
25 }

 

 三者区别:1、strcpy,strncpy复制字符串时遇到\0会结束,比如abc0def,只能复制到abc。

      2、strcpy复制的是整个字符串,而strncpy复制的是字符串的count长度。同理,strcmp比较的是整个字符串,而strncmp比较的是字符串的count长度。

      3、memcpy是count个内存地址的复制,包含0,运用于不确定是否是字符串的场合。

      同理:memcpy是count个内存地址的比较,因此两个数组大小相差较大时,函数行为不确定。如一所示图片。因此字符串的比较一定要用strcpy函数。

     

注意:在使用strncpy时,如果to的内存空间小于count长度,则会内存溢出,会导致程序崩溃,设备重启。因此一般需要自己封装一个函数。如下:

 1 u8 memcpysafe(char *_dest,const char *_src,size_t _n, size_t _destSizeof)
 2 {
 3     _destSizeof--;
 4     if(_n > _destSizeof)
 5         _n = _destSizeof;
 6 
 7     memcpy(_dest,_src,_n);
 8     _dest[_n]=0x0;//增加结束符
 9     
10     debug_msg("数据格式异常");//会将文件名和行号打印出来 
11     return 1;
12 }

二、memset

      

  char *buff = NULL;

  buff = malloc(In_len+20);

  如下:memset在清空malloc申请的内存时,不能使用sizeof(buff)的形式,而是要用申请时的In_len+20,如:memset(buff,0,sizeof(In_len+20));

      

      

       

三、sprintf

       

      如下:可以拼接字符串{"ic_sercret":"adkddke"},如果后面还有数据,就会在数据中间拼接逗号{"ic_sercret":"adkddke","ic_secret_fm":"kalkdajeakal"}

      如果没有数据,字符串里就只有一个'{',有符号多余不影响,只要满足需求就行了。

 1                savecfg[0]='{';
 2                     ret = getKeyValueString(jsonmap2,"secret",tmp_buff,sizeof(tmp_buff));
 3                     if(ret>0){
 4                         if(strcmp(usrcfg->ic_secret,tmp_buff)!=0){//memcmp函数的第一个数组总是要比第二个数组小,否则字符串相同也会返回负数  
 5                             sprintf(savecfg,"%s\"ic_secret\":\"%s\"",savecfg,tmp_buff);
 6                             edit++;
 7                         }
 8                     }
 9                     ret = getKeyValueString(jsonmap2,"secret_fm",tmp_buff,sizeof(tmp_buff));
10                     if(ret>0){
11                         if(strcmp(usrcfg->ic_secret_fm,tmp_buff)!=0){
12                             if(edit>0)
13                                 sprintf(savecfg,"%s,\"ic_secret_fm\":\"%s\"",savecfg,tmp_buff);
14                             else
15                                 sprintf(savecfg,"%s\"ic_secret_fm\":\"%s\"",savecfg,tmp_buff);
16                             edit++;
17                         }   
18                     }            
19                     ret = getKeyValueString(jsonmap2,"m1_secret_fm",tmp_buff,sizeof(tmp_buff));
20                     if(ret>0){
21                         if(strcmp(usrcfg->ic_m1_secret_fm,tmp_buff)!=0){
22                             if(edit>0)
23                                 sprintf(savecfg,"%s,\"ic_m1_secret_fm\":\"%s\"",savecfg,tmp_buff);
24                             else
25                                 sprintf(savecfg,"%s\"ic_m1_secret_fm\":\"%s\"",savecfg,tmp_buff);
26                             edit++;
27                         }   
28                     }                
29                     if(edit!=0){
30                         sprintf(savecfg,"%s}",savecfg);
31                         cJSON *roottmp = cJSON_Parse(savecfg);
32                         if(roottmp){
33                             jsonConfigToConffile(roottmp,&code,0);//保存配置
34                             cJSON_Delete(roottmp);
35                         }
36                     }  
37                     printf("ICSecret --- edit:%d,savecfg:%s\n",edit,savecfg);

上述方式也可以调用json库函数实现(更优,代码少)

cJSON* rootedit = cJSON_CreateObject();
if (rootedit == NULL) {
    return 0;
}

cJSON *jsonmap2 = cJSON_GetObjectItem(jsonmap1,"tass");
if(jsonmap2){
  ret = getKeyValueString(jsonmap2,"secret",tmp_buff,sizeof(tmp_buff));
  if(ret > 0 && strcmp(usrcfg->ic_secret,tmp_buff)!=0){//
    cJSON_AddStringToObject(rootedit,"ic_secret",tmp_buff);
    edit++;
  }

   ret = getKeyValueString(jsonmap2,"secret_fm",tmp_buff,sizeof(tmp_buff));
   if(ret > 0 && strcmp(usrcfg->ic_secret_fm,tmp_buff)!=0){
       cJSON_AddStringToObject(rootedit,"ic_secret_fm",tmp_buff);
       edit++;
   }   

   ret = getKeyValueString(jsonmap2,"m1_secret_fm",tmp_buff,sizeof(tmp_buff));
   if(ret > 0 && strcmp(usrcfg->ic_m1_secret_fm,tmp_buff)!=0){
       cJSON_AddStringToObject(rootedit,"ic_m1_secret_fm",tmp_buff);
       edit++;
    }                   
}

 char *tmp = cJSON_PrintUnformatted(rootedit);//CJSON的打印格式
 log_info("edit secret:%s\n",tmp);
 if(tmp && strlen(tmp)>2){
    jsonConfigToConffile(rootedit,&code,0);//保存配置
    cJSON_Delete(rootedit);
 }
 if(tmp){
    cJSON_free(tmp);
    tmp=NULL;
 }

 

四、strtok

  

  什么时候使用?如要获取weixiao-config|wecard.qq.com|1652667671_A702F4BC233D712BFB1B38B28AA797E71676364978里的1652667671

result = strtok(indata,"|");
while(result != NULL ) {    
result = strtok(NULL,"|");
i++;
    if(i==2){//第三次就会获取到主体代码部分的字符串
          break;
    }
}
//结束获取到:1652667671_A702F4BC233D712BFB1B38B28AA797E71676364978 result
= strtok(result,"_");//这里发现主体代码后还有一个'_',那再使用一次就可以获取到主体代码,,,也可以用截取的方式,指针位移到'_'截取的长度部分。

 五、atoi

  

六、时间字符串和时间戳互相转换(在stm32上发现时间多了8小时,是时区的原因)

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <time.h>
 4 #include <stdlib.h>
 5 
 6 /*标准时间转换为时间戳*/
 7 unsigned int standard_to_stamp(char *str_time)//"2023-03-02 15:13:40"; 
 8 {
 9     struct tm stm;
10     int iY,iM,iD,iH,iMin,iS;
11     memset(&stm,0,sizeof(stm));
12     iY = atoi(str_time);
13     iM = atoi(str_time+5);     //和实际输入的格式 有关系
14     iD = atoi(str_time+8);
15     iH = atoi(str_time+11);
16     iMin = atoi(str_time+14);
17     iS = atoi(str_time+17);
18     
19     stm.tm_year=iY-1900;
20     stm.tm_mon=iM-1;
21     stm.tm_mday=iD;
22     stm.tm_hour=iH;
23     stm.tm_min=iMin;
24     stm.tm_sec=iS;
25 
26     printf("解析后的时间是%d-%02d-%02d %02d:%02d:%02d\n", iY, iM, iD, iH, iMin, iS);
27 
28     return (unsigned int)mktime(&stm);
29 }
30 
31 /*时间戳转换为标准时间*/
32 typedef struct times
33 {
34     int Year;
35     int Mon;
36     int Day;
37     int Hour;
38     int Min;
39     int Second;
40 }Times;
41 
42 Times stamp_to_standard(unsigned int stampTime)
43 {
44     time_t tick = (time_t)stampTime;//强制转换  如果传入的是毫秒级时间戳,   注意有的格式较严时应这样写:(time_t)(stamptime/1000)
45     struct tm tm;
46     char s[100];
47     Times standard;
48     tm = *localtime(&tick);                          //tm.tm_hour 有的系统下要 +8,东八区,如果+8要判断 if(tm.tm_hour+8)>=24   tm.tm_hour -= 8;  
49     strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", &tm);
50     printf("时间戳为:%d 转换成标准时间为(字符串): %s\n", (int)tick, s);//如果要转换为字符串,这里就可以return字符串了,不过注意返回的字符串要是全局或静态变量。 
51 
52     standard.Year = atoi(s);
53     standard.Mon = atoi(s+5);
54     standard.Day = atoi(s+8);
55     standard.Hour = atoi(s+11);
56     standard.Min = atoi(s+14);
57     standard.Second = atoi(s+17);
58     
59     return standard;//再转换为结构体类型 
60 }
61 
62 int main(void)
63 {
64     /*int 范围:2147483648~2147483647,表示时间:2038-01-19 11:14:07
65     unsigned int范围:0~4294967295,表示时间:2106-02-07 14:28:15
66     linux下就是用unsigned long存时间,所以只能到2038年,原因是当时那个年代就认为32位字宽已经很大了 */ 
67     
68     Times standard;
69     unsigned int a =0;
70     char argv[]= "2023-03-02 15:13:40"; 
71     printf("输入的标准时间是: %s \n",argv);
72     
73     a=standard_to_stamp(argv);
74     printf("标准时间转换为时间戳: %d\n",a);
75 
76     standard = stamp_to_standard(a);
77     printf("standard.year:%d\n",standard.Year);    
78 
79     return  0;
80 }

时间字符串和时间戳互相转换共用到三个库函数,包含在<time.h>下,分别为:

  1、时间结构体转换为时间戳(传入时间结构体,返回时间戳)

  

  2、时间戳转换为时间结构体(传入时间戳,返回时间结构体)

  

   如下:localtime 运用实例:

  struct tm *time;
    unsigned long long curSystime = XunLocGetUtc();//系统实时时间,毫秒级    

    /*C语言库函数操作time_t和结构体tm来自time.h*/
    time_t tick = (time_t)(curSystime/1000);
    time = localtime(&tick);//S级时间戳转换为时间结构体
    unsigned short tmp_hour = time->tm_hour+8; //东八区+8 世界标准时间即格林威治时间 北京时间与UTC的时差为 +8
    if((tmp_hour == 24 && time->tm_min >= 1)||tmp_hour > 24){//>=00:01:00 -= 24    23+8 = 31-24  23:59:00=1439  00:00:00=1440  00:01:00=1  
        tmp_hour -= 24;
    }
    unsigned short currentMin = (tmp_hour*60)+time->tm_min; //获取每天的实时分钟 

  

时间戳网页:时间戳(Unix timestamp)转换工具 - 在线工具 (tool.lu)

    

 

 

 

 

 

 

 

 

 

posted @ 2023-03-06 16:25  耿通宇  阅读(261)  评论(0编辑  收藏  举报