日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

strtok拆分字符串

發布時間:2024/3/26 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 strtok拆分字符串 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

大家好,我是驚覺,今天聊聊字符串。字符串的使用場景非常之多,人機交互和雙機通信都會用到。比如:

  • 通過串口向單片機發送指令,以執行操作或配置參數。
  • 單片機讀取傳感器數據,數據格式是字符串。一般GPS數據就是字符格式。
  • 有些場景需要使用多個處理器協同工作,比如單片機+openmv,它們之間需要通信,可以采用字符格式的編碼方式。

操作字符串,無非是兩件事兒:生成字符串與解析字符串,后者往往更復雜一些。Java,Python之類的高級編程語言自帶了強大的字符串處理庫,提供非常豐富的操作。下圖是Java的String類函數,密密麻麻有木有,這還只是一部分。

相對而言,標準C庫提供的功能有限。大家熟知的功能可能有:

  • 字符串復制追加(strcpy,strcat)
  • 字符串查找比較(strstr,strcmp)
  • 字符串轉數字(atoi,strtol)

有兩個非常有用但是可能被大家忽略的函數,介紹給大家。

任務:解析經緯度

讓我們以解析GPS中的RMC消息為例,數據如下:

$GNRMC,122921.000,A,3204.862246,N,11845.911047,E,0.099,191.76,280521,,E,A*00

GPS的各字段以逗號分隔。我們需要提取經緯度信息,集中在:A,3204.862246,N,11845.911047,E。A表示經緯度有效,3204.862246是緯度,11845.911047是緯度,具體的解釋參見下圖:

拆分字符串strtok_r

由于GPS中各字段以逗號分隔,大家最先想到的可能是用strstr或strchr去查找逗號的位置,再一一處理。如果有一個函數可以幫我們完成拆分,效果如下圖,那將會很方便后續處理。

這個函數是有的,而且就在C標準庫中,那就是strtok。

char *strtok(char *source, const char *delimiters);

其根據提供的分隔符集delimiters,對source進行拆分。

  • source 待拆分的字符串。
  • delimiters 分隔符集,可以包含多個字符。比如"\r\n\t "表示以換行,tab等字符進行拆分。
  • return 返回指向子字符串的指針。

在拆分一個字符串時,需要多次調用該方法:

  • 初次調用時,source為待拆分字符串,delimiters為分隔符。函數返回第一個子字符串地址。
  • 之后的調用,source為NULL,delimiters為分隔符,分隔符的內容并不需要與之前的一致。函數返回下一個子字符串地址。
  • 當某次調用后返回NULL時,整個拆分就結束了。

其實過程并不復雜,請看拆分GPS的代碼:

#define GPS_RMC "$GNRMC,122921.000,A,3204.862246,N,11845.911047,E,0.099,191.76,280521,,E,A*00"void split_string_example(void) {char buf[128];int buf_len;char *token = NULL;char *saveptr = NULL;const char *delim = ",*";LOG_I("test split string");buf_len = snprintf(buf, sizeof(buf), "%s", GPS_RMC);token = strtok_r(buf, delim, &saveptr);while (token){LOG_D("%s", token);token = strtok_r(NULL, delim, &saveptr);}LOG_HEX_V(buf, buf_len, "finally, buf:"); }

結果剛才已經放過了,這次放一個更完整的。

示例中用宏GPS_RMC來定義GPS的內容,再用snprintf把它打印到buf之中?

buf_len = snprintf(buf, sizeof(buf), "%s", GPS_RMC);

這可不是筆者多此一舉,而是因為strtok在拆分字符串時會修改其內容。以下兩點需要牢記:

  • strtok并不是重新分配內存以存放子字符串,其返回的子字符串直接指向待拆分字符串中的相應位置。沒有任何的內存分配。
  • 所謂的拆分,是將字符串中的分隔符替換為’\0’,也只有這樣,你才能進行后續操作。上圖的結尾展示了拆分后的buf的內容,紅框都是’\0’。因此,待拆分字符串必須是可被修改的,必須是變量,而不能是常量。

筆者用的不是strtok,而是strtok_r。C語言中很多函數有兩種版本,一種不帶_r,一種帶_r,_r表示可重入。可重入的概念可以單獨寫一篇文章,這里就不多說了。strtok_r比strtok多了一個參數,其為char *指針,用于保存拆分的狀態。其實用法很簡單,定義一個指針變量并傳入就行,不需要關注它的值。

優化一下

我們再看下GPS的數據,如果想提取其中的A,3204.862246和11845.911047,直接使用strtok并不方便。

$GNRMC,122921.000,A,3204.862246,N,11845.911047,E,0.099,191.76,280521,,E,A*00

如果使用Java的話,如下幾行代碼即可完成提取。

String gps = "$GNRMC,122921.000,A,3204.862246,N,11845.911047,E,0.099,191.76,280521,,E,A*00"; String[] sub = gps.split(","); if (sub.length < 6) {System.out.println("parse fail"); } else {System.out.println(String.format("parse succeed, valid:%s, longitude:%s, latitude:%s", sub[2], sub[3], sub[5])); }

輸出結果:

parse succeed, valid:A, longitude:3204.862246, latitude:11845.911047

Java之所以方便,關鍵在于split函數返回了拆分后的字符串數組,可直接通過下標提取相關字段。

C語言沒有這樣的函數,那我們就自己寫一個。

static int split_string(char *str, const char *delim, char *sub_ptr[], int size) {char *token = NULL;char *saveptr = NULL;int idx = 0;token = strtok_r(str, delim, &saveptr);while (token && idx < size){sub_ptr[idx++] = token;token = strtok_r(NULL, delim, &saveptr);}return idx; }

split_string將拆分的結果寫入sub_ptr之中,并返回子字符串個數。有了這個函數,提取就如Java一樣方便了。

void split_string_example2(void) {char buf[128];char *sub_buf[20];int num;LOG_I("test split string 2");snprintf(buf, sizeof(buf), "%s", GPS_RMC);num = split_string(buf, ",", sub_buf, ARRAY_SIZE(sub_buf));if (num < 7){LOG_E("fail");return;}LOG_D("succeed, valid:%s, latitude:%s, longitude:%s", sub_buf[2], sub_buf[3], sub_buf[5]);}

使用strtok或者是split_string僅僅是提取出目標字符串,想得到經緯度數值的話,還需要轉換成浮點數,可使用atof函數。其實還有一種更為簡單的方法,咱明天繼續。

文中完整的示例代碼,參見筆者基于stm32f407創建的demo工程:

地址:git@gitee.com:wenbodong/mcu_demo.git 示例:examples/05_string/example.c 使用時需要打開examples/examples.h中的EXAMPLE_SHOW_STRING。

總結

以上是生活随笔為你收集整理的strtok拆分字符串的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产经典三级在线 | 亚洲一二三不卡 | 懂色av蜜臀av粉嫩av喷吹 | 日本少妇裸体做爰 | 日本一区二区欧美 | 亚洲激情视频 | 亚洲成熟女性毛茸茸 | 在线播放无码后入内射少妇 | 男人视频网站 | 精品国产一区二区三区在线观看 | 51精品国自产在线 | 欧美一区二区三区免费 | 日本美女交配 | 亚欧美日韩 | 蜜桃网站 | 国产在线三区 | 波多野结衣视频在线播放 | 久久日精品 | 福利一区二区视频 | 久久久久99精品成人片 | 国产黑丝在线播放 | 特淫毛片 | 久久91av| 精品一区二区三区在线播放 | 99精品国产一区 | 老师用丝袜脚帮我脚交 | 欧美一区二区网站 | 日韩视频一区在线 | 欧美午夜久久 | 手机av网站 | 婷婷丁香视频 | 日韩精品人妻中文字幕有码 | 日韩中文字幕在线免费观看 | 日韩在线视频在线 | 亚洲精品一二三 | 久草福利 | 国产后入清纯学生妹 | 欧美美女性视频 | 97se在线视频 | av高清在线免费观看 | 超碰一级片 | 成人福利一区二区 | 国产理论片| 久久精品一区二区 | 国产精品亲子伦对白 | 欧美三p| 成人在线黄色 | 99视频免费在线观看 | 男女午夜视频在线观看 | 中文字幕无码乱码人妻日韩精品 | 97久久人国产精品婷婷 | 成人在线电影网站 | 国产毛片一区 | 免费av一级 | 精品久久久久久无码人妻 | 日欧美女人 | www.色在线观看 | 亚洲av无码乱码在线观看富二代 | 国产中文欧美日韩在线 | 成年女人18级毛片毛片免费 | 欧洲精品码一区二区三区免费看 | 色亚洲成人 | 中文字幕一区二区三区四区免费看 | 国产三级av在线播放 | 男女洗澡互摸私密部位视频 | 91av久久 | 韩国中文字幕在线观看 | 国产一区二区三区免费在线观看 | 织田真子作品 | va在线观看| 日本特级黄色录像 | 日本亚洲视频 | 国产免费无遮挡 | 超碰在线网 | 怡红院院av | 亚州av片| 美日韩丰满少妇在线观看 | 青娱乐超碰在线 | 18禁裸男晨勃露j毛免费观看 | 午夜xx| 成人免费一区二区三区在线观看 | 成人午夜免费在线 | 亚洲制服一区二区 | 伊人影视久久 | 一炮成瘾1v1高h | 波多野吉衣视频在线观看 | 色蜜桃av| 国产福利合集 | 欧美噜噜噜 | h视频在线观看网站 | 中文写幕一区二区三区免费观成熟 | 亚洲资源在线观看 | 茄子视频A | 都市激情 亚洲 | 台湾色综合 | 色婷婷综合久久久久中文 | 黑料视频在线 | 午夜精品久久久久久久久久蜜桃 | 综合亚洲色图 |