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 <[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: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]);
}

使用方法也差点儿相同。

时间: 2024-10-24 08:33:57

c/cpp中怎样切割字符串,相似于split的功能的相关文章

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()的实现,可以一

实现SQL Server中的切割字符串SplitString函数

有时我们要用到批量操作时都会对字符串进行拆分,可是SQL Server中却没有自带Split函数,所以要自己来实现了.没什么好说的,需要的朋友直接拿去用吧 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /* by kudychen 2011-9-28 */ CREATE function [dbo].[SplitString] ( @Input nvarchar(max), --input string to be separated @Sep

实现SQL Server中的切割字符串SplitString函数,返回Table

有时我们要用到批量操作时都会对字符串进行拆分,可是SQL Server中却没有自带Split函数,所以要自己来实现了. -- ============================================= -- Author: chenlong -- Create date: 2015-02-02 -- Description: 根据逗号分隔拆分字符串,返回table -- ============================================= ALTER FUN

JavaScript和php常用语法——切割字符串

在面向Web的应用中,前台和后台通信非常常用的一种格式就是字符串,所以,在通信中,我们不可避免的就需要进行字符串的拼切. 在js代码中,当我们传递一个字符串到后台代码时,我们在后台需要对字符串进行切割用以获取我们所需要的数据.同样的,在后台代码(我常用的是php)中我们传递一个字符串到前台js代码中,我们同样需要对字符串进行切割以获取我们所需的数据. 那么,接下里就看看在JavaScript和php中如何进行字符串的切割吧! JavaScript中: 在js中,切割字符串的常用方法有:subst

以字符串str2中的内容为规范切割字符串

. char*strstrchar*str1,回来该方位的针.char*str2;求str2str1中初次呈现的方位.> 假如找不到则回来NULL; 则第一个参数要用NULL 8. char*strtokchar*str1,str1中只需遇到str2中存在字符就会切割.回来被切割出来的左面的那一部分.履行一次只切割一次. 假如要继续切割现已被切割过的字符串.char*str2;以字符串str2中的内容为规范切割字符串str1str2中可所以单个字符也可所以字符串.> 下面的比如中str2中有逗

loadrunner中切割字符串

下面函数的作用: http://blog.csdn.net/hgj125073/article/details/8447605 通过-与: 字符切割字符串,即-与:字符已经被\0 字符取代 char s[] = "ab-cd : ef;gh :i-jkl;mnop;qrs-tu: vwx-y;z"; char *delim = "-: ";  char *p;  lr_output_message("%s ", strtok(s, delim))

HTML中JS对于字符串的切割截取实现

在网站编程制作中,对于字符串的切割截取平时所用可能不是特别多,而且分的比较细,所以自备自查.有备无患.由于之前所有均在一个demo测试,下面就来跟大家分享一下成果. 1.函数:split() 功能:使用一个指定的分隔符把一个字符串分割存储到数组 例子: str="jpg|bmp|gif|ico|png"; arr=str.split("|"); //arr是一个包含字符值"jpg"."bmp"."gif".

【整理】C语言中常见的字符串操作函数

需求开发中经常会用到很字符串操作的函数,现整理常用函数如下: 函数名: strcpy 功  能: 拷贝一个字符串到另一个 用  法: char *strcpy(char *destin, char *source); 示例如下: <span style="font-size:24px;">#include <stdio.h> #include <string.h> int main() { char desstr[10]; char *srcstr

切割字符串

首先吹一下意图:切割字符串是因为在数据库中存图片地址时,可能一件商品对应有多张图片.那么我们可以建一个商品表(goods)和一个图片表(goods_image),然后让图片表的id作为商品表的外键,实现一对多的关联. 但是想到建表一个路径一个路径的存,数据也蛮多的,然后既然可以在商品表中添加一个字段(goods_image_url);那为什么不用呢? 然后讲一下思路:图片地址拼接在一起,然后要将其分割成单独的一张一张图片的地址,那么之前拼接的时候就要用到分隔符来分割每一条地址.分割出来的地址可以