一、函数功能
C 库函数 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。
二、函数解析
1.函数原型
char *strtok(char *str, const char *delim)
2.参数
char *str 要被分割的目标字符串
char *delim 要分割目标字符串的分隔符,必须被包含于目标字符串中
3.返回值
函数返回被分解的第一个子字符串,如果没有可检索的字符串(分隔符),则返回一个空指针。
三、实例
用C库字符串处理函数,解析GSM模块通过串口回传的字符串年、月、日、时、分、秒、经度、纬度,并通过库函数将字符串转换为int、double的数据类型。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
unsigned int year;
unsigned int mon;
unsigned int day;
unsigned int hour;
unsigned int min;
unsigned int sec;
double latitude;
double longitude;
}DATA;
int main(void)
{
#if 1
DATA data;
char str_src_1[] = "+CGNSINF:1,1,20200623084942.000,22.537237,113.939234,13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
char *BUFF=str_src_1;
char data_temp[20] = {0};
char *BUFF_data=data_temp;
char * pp ;
BUFF+=strlen("+CGNSINF:1,1,");//"20200623084942.000,22.537237,113.939234,13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
strncpy(BUFF_data,BUFF,4);data.year = atoi(BUFF_data);//2020
BUFF+=4;strncpy(BUFF_data,BUFF,2);data.mon = atoi(BUFF_data);//6
//"0623084942.000,22.537237,113.939234,13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
BUFF+=2;strncpy(BUFF_data,BUFF,2);data.day = atoi(BUFF_data);//23
//"23084942.000,22.537237,113.939234,13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
BUFF+=2;strncpy(BUFF_data,BUFF,2);data.hour = atoi(BUFF_data);//8
//"084942.000,22.537237,113.939234,13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
BUFF+=2;strncpy(BUFF_data,BUFF,2);data.min = atoi(BUFF_data);//49
//"4942.000,22.537237,113.939234,13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
BUFF+=2;strncpy(BUFF_data,BUFF,2);data.sec = atoi(BUFF_data);//42
//"42.000,22.537237,113.939234,13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
strtok(BUFF,",");
//"22.537237,113.939234,13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
pp=strtok(NULL,",");//*pp=22.537237
//"113.939234,13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
data.latitude = atof(pp);//double 类型 22.537237
pp=strtok(NULL,",");//*pp=113.939234
//"13.423,0.07,0.0,1,,1.0,1.4,0.9,,10,7,,,37,,";
data.longitude = atof(pp);//double 类型 113.939234
return 0;
#endif
}
四、注意事项
数据缓冲区的指针必须绑定可用的左值(内存单元)
比如在上述实列中,用到了库函数 char *strncpy(char *dest, const char *src, size_t n),其中的参数char * dest ,传入的实参必须绑定一个已经定义好的左值(内存单元),因为此函数是将src中的前面n个字节保存到dest中,所以dest不能是一个空指针。
看到这里有兄弟可能会问,那你定义char *pp 的时候为啥就没有初始化绑定一个可用的左值(内存单元)。
那是因为char *strtok(char *str, const char *delim) 这个函数执行完成后,返回的是str中分隔符前面的左值(内存单元),而我们传入的str参数肯定是一个具体的地址,所以通过pp=strtok(NULL,",");其实是将pp绑定、指向函数返回的左值(内存单元)
void lcd_show_ram_image(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,const unsigned char *data)
{
oled_set_pos_1(LCD_W_Start + x0, y0, LCD_W_Start + x1-1, y1-1); //坐标设置
LCD_DC_DATA;
LCD_CS_CLR_1;
if(!((x1-x0)*(y1-y0)*2/4095))
{
spi_write((void *)data,((x1-x0)*(y1-y0)*2%4095));
LCD_CS_SET_1;
return ;
}
else
{
for(uint8_t line =0;line<((x1-x0)*(y1-y0)*2/4095);line++)
{
spi_write((void *)(data+line*4095),4095);
}
spi_write((void *)(data+((x1-x0)*(y1-y0)*2/4095)*4095),((x1-x0)*(y1-y0)*2%4095));
LCD_CS_SET_1;
}
}