c/cpp中如何分割字串,類似於split的功能

來源:互聯網
上載者:User

標籤:style   blog   http   java   color   使用   



在python中,如果要求目前時間的unix時間戳記,我特別喜歡這麼用:

import timetimestr = time.time()timestamp = int(timestr.split('.')[0])

這裡的split函數,我非常喜歡,在java、c#和python中都有,很方便,不用擔心踩地雷,但是C/CPP中,就沒有了,這點比較遺憾。

如果要處理一個字串型的“192.168.1.254”,想把每個欄位都分開,怎麼辦呢,C標準庫中有函數strtok()的實現,可以一用。

#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){char ip_str[] = "192.168.1.250";char *ip_arr[4] ;char * s = strtok(ip_str, ".");int i=0;while(s){ip_arr[i] = s;s = strtok(NULL, ".");i++;//printf("%s\n",s);}for(i=0; i<4; i++)printf("%s\n",ip_arr[i]);}

在這裡,strtok是非安全執行緒的,這點也可以在程式的第二次strtok調用中看到,因此linux用strsep來替換strtok了,我在linux2.6.22的源碼/lib/string.c和linux-3.3中同檔案中,c檔案開頭就是這樣一段話:

/* *  linux/lib/string.c * *  Copyright (C) 1991, 1992  Linus Torvalds *//* * stupid library routines.. The optimized versions should generally be found * as inline code in <asm-xx/string.h> * * These are buggy as well.. * * * Fri Jun 25 1999, Ingo Oeser <[email protected]> * -  Added strsep() which will replace strtok() soon (because strsep() is *    reentrant and should be faster). Use only strsep() in new code, please. * * * Sat Feb 09 2002, Jason Thomas <[email protected]>, *                    Matthew Hawkins <[email protected]> * -  Kissed strtok() goodbye */


因為strsep是安全執行緒的,並且速度上更快一些,所以採用strsep來替換strtok,接下來我會試一試strsep。在這裡感慨下,沒事的時候或者寫程式的時候,用man和查看源碼的方式,能學到很多基本的知識,比如核心源碼的lib檔案夾下,linux核心使用的rbtree結構,還有lib檔案夾的string.c,include下的string.h裡的各種strcpy,strcat等基本函數的實現,都是非常經典而且久經考驗的。

在strtok使用的代碼裡,有兩處很有意思。

其中一個,修改第7行,如下所示:

#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){char *ip_str = "192.168.1.250";char *ip_arr[4] ;char * s = strtok(ip_str, ".");int i=0;while(s){ip_arr[i] = s;s = strtok(NULL, ".");i++;//printf("%s\n",s);}for(i=0; i<4; i++)printf("%s\n",ip_arr[i]);}

將char ip_str[] = "192.168.1.250";改為char *ip_str = "192.168.1.250";就會core dump,通過gdb和core檔案來看,程式崩潰在了

Program terminated with signal 11, Segmentation fault.#0  strtok () at ../sysdeps/i386/i686/strtok.S:245245  movb $0, (%edx) /* Terminate string.  */(gdb) where#0  strtok () at ../sysdeps/i386/i686/strtok.S:245#1  0x0804841e in main () at test.c:9

而這段代碼在VS下是沒有問題的,所以這個原因需要找一下。

這個原因找到了,在連結http://www.cnblogs.com/longzhao1234/archive/2012/05/31/2528317.html

通過閱讀原始碼,因為函數內部會修改原字串變數,所以傳入的參數不能是不可變字串(即文字常量區)。
如 char *tokenremain ="abcdefghij"//編譯時間為文字常量,不可修改。
strtok(tokenremain,"cde");
strsep(&tokenremain,"cde");
編譯通過,運行時會報段錯誤。

VS在很多情況下要比GCC優秀很多,VS的CPP支援是最全面的,可以這麼說。好多CPP的作者啦,大牛啦,都是M$的VC組的,好牛逼的地方。

另外在改一處,這次只改第16行,將printf語句注釋掉,代碼如下:

#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){char ip_str[] = "192.168.1.250";char *ip_arr[4] ;char * s = strtok(ip_str, ".");int i=0;while(s){ip_arr[i] = s;s = strtok(NULL, ".");i++;printf("%s\n",s);}for(i=0; i<4; i++)printf("%s\n",ip_arr[i]);}

又崩潰了,我也整個人都不好了。

分析core檔案,出錯如下:

Program terminated with signal 11, Segmentation fault.#0  __strlen_ia32 () at ../sysdeps/i386/i586/strlen.S:9999  movl (%eax), %ecx /* get word (= 4 bytes) in question */(gdb) where#0  __strlen_ia32 () at ../sysdeps/i386/i586/strlen.S:99#1  0x00b9ddd5 in _IO_puts (str=0x0) at ioputs.c:37#2  0x0804846b in main () at test.c:16

令人欣慰的是,VS在這句也崩了。

根據core檔案的提示,在#0處,在strlen函數這裡崩潰了,我判斷,是strtok階段字元數組到最後,要在printf("%s\n",s);處列印時,由於沒有‘\0‘符號,所以緩衝區無法截斷,最後溢出導致printf崩潰,所以我重新聲明一個長度為sizeof(ip_str)+1的字元數組,將ip_str複製進去,並將最後一個字元置為‘\0‘,代表字元結束,結果依然崩潰。

如果我把printf("%s\n",s);改為printf("%s\t",s);,因為printf是列印到標準輸出中,而標準輸出是行緩衝的,對於‘\n‘,代表行緩衝結束,需要輸出,如果我不讓他輸出,會怎樣?

列印結果為:

1681250(null)
好吧我也不知道是什麼了,而且這個結果與是否有‘\0‘符號無關。


這兩個地方一定要找出來問題,嗯。


接下來我們看看strsep的用法吧

#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){char ip_str[] = "192.168.1.250";char *p = ip_str;char *ip_arr[4] ;char * s = strsep(&p, ".");int i=0;while(s){ip_arr[i] = s;s = strsep(&p, ".");i++;//printf("%s\n",s);}for(i=0; i<4; i++)printf("%s\n",ip_arr[i]);}

用法也差不多。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.