c/cpp中怎样切割字符串,相似于split的功能
在python中,假设要求当前时间的unix时间戳,我特别喜欢这么用:
import time
timestr = 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:245
245 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:99
99 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',代表行缓冲结束,须要输出,假设我不让他输出,会如何?
打印结果为:
168 1 250 (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的功能的更多相关文章
- 实现SQL Server中的切割字符串SplitString函数,返回Table
有时我们要用到批量操作时都会对字符串进行拆分,可是SQL Server中却没有自带Split函数,所以要自己来实现了. -- ===================================== ...
- 实现SQL Server中的切割字符串SplitString函数
有时我们要用到批量操作时都会对字符串进行拆分,可是SQL Server中却没有自带Split函数,所以要自己来实现了.没什么好说的,需要的朋友直接拿去用吧 SET ANSI_NULLS ON GO S ...
- JavaScript和php常用语法——切割字符串
在面向Web的应用中,前台和后台通信非常常用的一种格式就是字符串,所以,在通信中,我们不可避免的就需要进行字符串的拼切. 在js代码中,当我们传递一个字符串到后台代码时,我们在后台需要对字符串进行切割 ...
- golang学习笔记15 golang用strings.Split切割字符串
golang用strings.Split切割字符串 kv := strings.Split(authString, " ") if len(kv) != 2 || kv[0] != ...
- loadrunner中切割字符串
下面函数的作用: http://blog.csdn.net/hgj125073/article/details/8447605 通过-与: 字符切割字符串,即-与:字符已经被\0 字符取代 char ...
- shell 从变量中切割字符串
1. 在shell变量中切割字符串 shell中截取字符串的方法有很多中,${expression}一共有9种使用方法.${parameter:-word}${parameter:=word}${pa ...
- PHP 中使用explode()函数切割字符串为数组
explode()函数的作用:使用一个字符串分割另一个字符串,打散为数组. 例如: 字符串 $pizza = "第1 第2 第3 第4 第5 第6"; 根据空格分割后:$piece ...
- JavaScript中常见的字符串操作函数及用法
JavaScript中常见的字符串操作函数及用法 最近几次参加前端实习生招聘的笔试,发现很多笔试题都会考到字符串的处理,比方说去哪儿网笔试题.淘宝的笔试题等.如果你经常参加笔试或者也是一个过来人,相信 ...
- loadrunner通过字符串左右边界切割字符串
void web_reg_save_param_custom(char *sourceStr, char* outpuStr, char *leftBdry, char *rightBdry){ ...
随机推荐
- php+sqlite 最佳web服务器
1 wampserver 支持mysql.每次都启动mysql,可以手动停止.但是运行时有时会很慢. 放弃 2 APS绿色版(Apache+PHP+SQLite) 组件环境:Apache2.2. ...
- 开源Math.NET基础数学类库使用(02)矩阵向量计算
原文:[原创]开源Math.NET基础数学类库使用(02)矩阵向量计算 开源Math.NET基础数学类库使用系列文章总目录: 1.开源.NET基础数学计算组件Math.NET(一)综合介绍 ...
- 部署Redis主-从
Redis主-从部署实践 0. 前言 这篇文章简要介绍Redis的主从部署,实现了一主二从,使用两个哨兵监控,以实现简单的HA,其中从库作为备机. 1. 部署 这里有三台服务器,其中239主机上的Re ...
- IOS开发——手动设置屏幕旋转
在移动开发过程.您可能需要跨越看看你的手机.有可能是所有的接口必须跨越,有可能是一个交叉通过电话,当用户当,你的接口也希望他能跨越.还有可能的是,界面的一部分需要被侧向显示.视情况而定,有不同的方法来 ...
- ZOJ 3820 2014ACM/ICPC牡丹江司B称号
3797714 2014 - 10 - 12 21:58 : 19 Accepted 3820 C++ 1350 70240 zz_1215 比較麻烦的一道题吧,開始的时候不停的段异常,后面知道是爆栈 ...
- Linux IO工具 iotop备择方案iopp
iotop毫无疑问linux IO检测上是一个很好的工具,但苦于要求和内核版本Python版本号.我的很多朋友放弃了.我也是.无意中发现iopp,使用c书面,与此iotop它是一个作用.nice! 一 ...
- SplashScreenDemo
对Java应用最常见的抱怨就是启动时间太长.这是因为Java虚拟机花费一段时间去加载所有必需的类,特别是对Swing应用,它们需要从Swing和AWT类库代码中去抽取大量的内容. 用户并不喜欢应用程序 ...
- C++中的class (2)
class Father { protected void methodA(){ //do something } private void methodB(){//do something } } ...
- 达到HTTP合约Get、Post和文件上传功能——采用WinHttp介面
于<采用WinHttp实现HTTP协议Get.Post和文件上传功能>一文中,我已经比較具体地解说了怎样使用WinHttp接口实现各种协议. 在近期的代码梳理中,我认为Post和文件上传模 ...
- HTML5 3D翻书效果(双面效应)
最后使用HTML5翻书效果达到测试,比较简单,它的升级版是 最后一个问题: 1)后,原来的页面连环画将成为一面镜子 2)无法实现双面翻书. 3)明显感觉页面似有近遮挡标志. 这次的升级版本号实现过程比 ...