c/cpp中如何分割字符串,类似于split的功能
来源:互联网 发布:淘宝精选安踏鞋 编辑:程序博客网 时间:2024/05/22 13:33
在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 <ioe@informatik.tu-chemnitz.de> * - 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 <jason@topic.com.au>, * Matthew Hawkins <matt@mh.dropbear.id.au> * - 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]);}
用法也差不多。
- c/cpp中如何分割字符串,类似于split的功能
- 【Python】实现字符串分割功能 类似于str.split()
- 字符串分割函数:类似于VB的split()函数
- 模拟java的split函数,分割字符串,类似于java的split方法
- C实现分割字符串(使用strtok_s函数,完成C#的Split函数功能)
- 分割字符串函数split(C#)
- 分割字符串函数split(C#)
- c 分割字符串函数 split
- C++:实现split分割字符串
- C++:实现split分割字符串
- C++:实现split分割字符串
- C++:实现split分割字符串
- C++:实现split分割字符串
- C++:实现split分割字符串
- 分割字符串(字符串的split)
- 在PL/SQL中如何分割字符串(Split String)
- JS实现Split分割字符串同时允许被分割出的字符串中存在分割符号
- c语言的split字符串分割函数strtok的使用
- 南邮ACM 1014 数据的插入与删除 JAVA解法
- poj Tiling
- 技术晋升的误区
- 实战Jquery(一)--用户名校验
- POJ 3013 Big Christmas Tree(Dijkstra)
- c/cpp中如何分割字符串,类似于split的功能
- [LeetCode] N-Queens II
- /*****************c++ STL 里的upper_bound 和 lower_bound 的用法~~*********************/
- 内核中位运算函数
- ExtJS下拉grid
- android获取string.xml的值
- Thread 的构造方法
- poj 2533/3903 Longest Ordered Subsequence(最长升序子串)
- 递归入门(二) -- 斐波那契数列