標籤: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]);}
用法也差不多。