请问,c语言分隔符中,对带分隔符的字符串如何分割?

9173人阅读
C&C++(17)
& & & & 之前遇到字符串分割的需求时,都是自己去实现,最近发现其实c标准库已经提供了这个功能。对标准库还是不熟悉啊,导致重复造车轮了,有必要把标准库看一下。。。
& & & & 先看一下之前自己实现的字符串分割函数:
void strsplit(const char *str, char *delim, void (*visitor)(const char *, int, int)){
int i, k_s, k_e, s_len, d_
s_len = strlen(str);
d_len = strlen(delim);
assert(str!=NULL && delim!=NULL && visitor!=NULL);
k_s = k_e = 0;
while(k_e & s_len){
if( (k_e + d_len &= s_len) && strncmp(str+k_e, delim, d_len) == 0 ){
if(k_e & k_s)
visitor(str, k_s, k_e);
k_s = k_e = k_e + d_
if(k_e & k_s){
visitor(str, k_s, k_e);
& & & & str:要分割的字符串的字符串。
& & & & delim:分隔符,可以是多个字符的字符串。
& & & & visitor:函数指针,在识别出子串时调用。
& & & & 对于字符串&abc##123###a##&,分隔符是&##&,会将其分割为&abc&,&123&,“#a”。也就是说,要分割的字符串中的子串必须与分割字符串相等,才算做分隔符,而不是只要包含在分割字符串就算做分隔符,这个与标准库的有点不同。但是对于分隔符只有一个字符的情况与标准库的执行结果是相同的,比如:如果上面的字符串的分割符是&#&,那么最后结果就是&abc&,“123”,&a&。
& & & & 出现这个不一致,是因为如果某个子串与分割字符串相等,那么直接跳过strlen(分割字符串)个字符,然后继续检查。如果这里改成跳到下一个字符然后继续检查,那么就会和标准库的函数得到一样的结果。就是把第13行替换为:
k_s = k_e + (d_len - 1);& & & & 上面介绍了分割字符串的实现,下面看一下标准库提供的函数strtok。
char *strtok(char *str, const char *delim);& & & & str:要分割的字符串。
& & & & delim:分割字符串,包含在分割字符串中的字符都会被当做是分割字符而丢弃掉。
& & & & 看个例子:
#include &string.h&
#include &stdio.h&
#include &stdlib.h&
main(int argc, char **argv){
char *s, *d, *t;
if(argc & 3){
printf(&%s\n&, &wrong args. usage: str delim&);
s = argv[1];
d = argv[2];
t = strtok(s, d);
while(t != NULL){
printf(&%s\n&, t);
t = strtok(NULL, d);
& & & & 第一次调用strtok需要传入要分割的字符串str进行初始化,随后对同一个字符串继续分割传入NULL即可。这个地方需要注意,如果不传入NULL,那么就会出现死循环,一直返回str第一个被分割出的子串。
& & & & 分割字符串delim每次都可以传入不同的字符串,也就是说可以根据不同的分隔符分割字符串,不过这样的需求还是比较不常用的。
& & & & 通过这个函数以后完成配置文件的解析就比较方便了,不用再被各种各样的bug打扰。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:515251次
积分:6058
积分:6058
排名:第2287名
原创:114篇
评论:115条1. &memset & 初始化字串
2. &strlen & & & 字串长度
3. &strcpy / strncpy &拷贝字串
4. &strcat / strncat & 连接字串
5. &strcmp / strncmp 比较字串(区分大小写)
6. &strcasecmp / strncasecmp 比较字串(不区分大小写) &注: PICC中用的是 stricmp / strnicmp&
7. &strchr / strstr &搜索字串
8. &strtok / strtok_r &分割字串
1.&字符串操作函数
程序按功能划分可分为数值运算、符号处理和I/O操作三类,符号处理程序占相当大的比例,符号处理程序无处不在,编译器、浏览器、Office套件等程序的主要功能都是符号处理。无论多复杂的符号处理都是由各种基本的字符串操作组成的,本节介绍如何用C语言的库函数做字符串初始化、取长度、拷贝、连接、比较、搜索等基本操作。
1.1.&初始化字符串
#include &string.h&void *memset(void *s, int c, size_t n);返回值:s指向哪,返回的指针就指向哪
memset函数把s所指的内存地址开始的n个字节都填充为c的值。通常c的值为0,把一块内存区清零。例如定义char buf[10];,如果它是全局变量或静态变量,则自动初始化为0(位于.bss段),如果它是函数的局部变量,则初值不确定,可以用memset(buf, 0, 10)清零,由malloc分配的内存初值也是不确定的,也可以用memset清零。
1.2.&取字符串的长度
#include &string.h&size_t strlen(const char *s);返回值:字符串的长度
strlen函数返回s所指的字符串的长度。该函数从s所指的第一个字符开始找'\0'字符,一旦找到就返回,返回的长度不包括'\0'字符在内。例如定义char buf[] = "hello";,则strlen(buf)的值是5,但要注意,如果定义char buf[5] = "hello";,则调用strlen(buf)是危险的,会造成数组访问越界。
1.3.&拷贝字符串
在中介绍了strcpy和strncpy函数,拷贝以'\0'结尾的字符串,strncpy还带一个参数指定最多拷贝多少个字节,此外,strncpy并不保证缓冲区以'\0'结尾。现在介绍memcpy和memmove函数。
#include &string.h&void *memcpy(void *dest, const void *src, size_t n);void *memmove(void *dest, const void *src, size_t n);返回值:dest指向哪,返回的指针就指向哪
memcpy函数从src所指的内存地址拷贝n个字节到dest所指的内存地址,和strncpy不同,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。这里的命名规律是,以str开头的函数处理以'\0'结尾的字符串,而以mem开头的函数则不关心'\0'字符,或者说这些函数并不把参数当字符串看待,因此参数的指针类型是void *而非char *。
memmove也是从src所指的内存地址拷贝n个字节到dest所指的内存地址,虽然叫move但其实也是拷贝而非移动。但是和memcpy有一点不同,memcpy的两个参数src和dest所指的内存区间如果重叠则无法保证正确拷贝,而memmove却可以正确拷贝。假设定义了一个数组char buf[20] = "hello world\n";,如果想把其中的字符串往后移动一个字节(变成"hhello world\n"),调用memcpy(buf + 1, buf, 13)是无法保证正确拷贝的:
例&25.1.&错误的memcpy调用
#include &stdio.h&#include &string.h&int main(void){
char buf[20] = "hello world\n";
memcpy(buf + 1, buf, 13);
printf(buf);
return 0;}
在我的机器上运行的结果是hhhllooworrd。如果把代码中的memcpy改成memmove则可以保证正确拷贝。memmove可以这样实现:
void *memmove(void *dest, const void *src, size_t n){
char temp[n];
const char *s =
for (i = 0; i & i++)
temp[i] = s[i];
for (i = 0; i & i++)
d[i] = temp[i];}
借助于一个临时缓冲区temp,即使src和dest所指的内存区间有重叠也能正确拷贝。思考一下,如果不借助于临时缓冲区能不能正确处理重叠内存区间的拷贝?
用memcpy如果得到的结果是hhhhhhhhhhhhhh倒不奇怪,可为什么会得到hhhllooworrd这个奇怪的结果呢?根据这个结果猜测的一种可能的实现是:
void *memcpy(void *dest, const void *src, size_t n){
const char *s =
const int *
int r = n % 4;
while (r--)
*d++ = *s++;
di = (int *)d;
si = (const int *)s;
while (n--)
*di++ = *si++;}
在32位的x86平台上,每次拷贝1个字节需要一条指令,每次拷贝4个字节也只需要一条指令,memcpy函数的实现尽可能4个字节4个字节地拷贝,因而得到上述结果。
C99的restrict关键字
我们来看一个跟memcpy/memmove类似的问题。下面的函数将两个数组中对应的元素相加,结果保存在第三个数组中。
void vector_add(const double *x, const double *y, double *result){
for (i = 0; i & 64; ++i)
result[i] = x[i] + y[i];}
如果这个函数要在多处理器的计算机上执行,编译器可以做这样的优化:把这一个循环拆成两个循环,一个处理器计算i值从0到31的循环,另一个处理器计算i值从32到63的循环,这样两个处理器可以同时工作,使计算时间缩短一半。但是这样的编译优化能保证得出正确结果吗?假如result和x所指的内存区间是重叠的,result[0]其实是x[1],result[i]其实是x[i+1],这两个处理器就不能各干各的事情了,因为第二个处理器的工作依赖于第一个处理器的最终计算结果,这种情况下编译优化的结果是错的。这样看来编译器是不敢随便做优化了,那么多处理器提供的并行性就无法利用,岂不可惜?为此,C99引入restrict关键字,如果程序员把上面的函数声明为void vector_add(const double *restrict x, const double *restrict y, double *restrict result),就是告诉编译器可以放心地对这个函数做优化,程序员自己会保证这些指针所指的内存区间互不重叠。
由于restrict是C99引入的新关键字,目前Linux的Man Page还没有更新,所以都没有restrict关键字,本书的函数原型都取自Man Page,所以也都没有restrict关键字。但在C99标准中库函数的原型都在必要的地方加了restrict关键字,在C99中memcpy的原型是void *memcpy(void * restrict s1, const void * restrict s2, size_t n);,就是告诉调用者,这个函数的实现可能会做些优化,编译器也可能会做些优化,传进来的指针不允许指向重叠的内存区间,否则结果可能是错的,而memmove的原型是void *memmove(void *s1, const void *s2, size_t n);,没有restrict关键字,说明传给这个函数的指针允许指向重叠的内存区间。在restrict关键字出现之前都是用自然语言描述哪些函数的参数不允许指向重叠的内存区间,例如在C89标准的库函数一章开头提到,本章描述的所有函数,除非特别说明,都不应该接收两个指针参数指向重叠的内存区间,例如调用sprintf时传进来的格式化字符串和结果字符串的首地址相同,诸如此类的调用都是非法的。本书也遵循这一惯例,除非像memmove这样特别说明之外,都表示&不允许&。
关于restrict关键字更详细的解释可以参考。
字符串的拷贝也可以用strdup(3)函数,这个函数不属于C标准库,是POSIX标准中定义的,POSIX标准定义了UNIX系统的各种接口,包含C标准库的所有函数和很多其它的系统函数,在将详细介绍POSIX标准。
#include &string.h&char *strdup(const char *s);返回值:指向新分配的字符串
这个函数调用malloc动态分配内存,把字符串s拷贝到新分配的内存中然后返回。用这个函数省去了事先为新字符串分配内存的麻烦,但是用完之后要记得调用free释放新字符串的内存。
1.4.&连接字符串
#include &string.h&char *strcat(char *dest, const char *src);char *strncat(char *dest, const char *src, size_t n);返回值:dest指向哪,返回的指针就指向哪
strcat把src所指的字符串连接到dest所指的字符串后面,例如:
char d[10] = "foo";char s[10] = "bar";strcat(d, s);printf("%s %s\n", d, s);
调用strcat函数后,缓冲区s的内容没变,缓冲区d中保存着字符串"foobar",注意原来"foo"后面的'\0'被连接上来的字符串"bar"覆盖掉了,"bar"后面的'\0'仍保留。
strcat和strcpy有同样的问题,调用者必须确保dest缓冲区足够大,否则会导致缓冲区溢出错误。strncat函数通过参数n指定一个长度,就可以避免缓冲区溢出错误。注意这个参数n的含义和strncpy的参数n不同,它并不是缓冲区dest的长度,而是表示最多从src缓冲区中取n个字符(不包括结尾的'\0')连接到dest后面。如果src中前n个字符没有出现'\0',则取前n个字符再加一个'\0'连接到dest后面,所以strncat总是保证dest缓冲区以'\0'结尾,这一点又和strncpy不同,strncpy并不保证dest缓冲区以'\0'结尾。所以,提供给strncat函数的dest缓冲区的大小至少应该是strlen(dest)+n+1个字节,才能保证不溢出。
1.5.&比较字符串
#include &string.h&int memcmp(const void *s1, const void *s2, size_t n);int strcmp(const char *s1, const char *s2);int strncmp(const char *s1, const char *s2, size_t n);返回值:负值表示s1小于s2,0表示s1等于s2,正值表示s1大于s2
memcmp从前到后逐个比较缓冲区s1和s2的前n个字节(不管里面有没有'\0'),如果s1和s2的前n个字节全都一样就返回0,如果遇到不一样的字节,s1的字节比s2小就返回负值,s1的字节比s2大就返回正值。
strcmp把s1和s2当字符串比较,在其中一个字符串中遇到'\0'时结束,按照上面的比较准则,"ABC"比"abc"小,"ABCD"比"ABC"大,"123A9"比"123B2"小。
strncmp的比较结束条件是:要么在其中一个字符串中遇到'\0'结束(类似于strcmp),要么比较完n个字符结束(类似于memcmp)。例如,strncmp("ABCD", "ABC", 3)的返回值是0,strncmp("ABCD", "ABC", 4)的返回值是正值。
#include &strings.h&int strcasecmp(const char *s1, const char *s2);int strncasecmp(const char *s1, const char *s2, size_t n);返回值:负值表示s1小于s2,0表示s1等于s2,正值表示s1大于s2
这两个函数和strcmp/strncmp类似,但在比较过程中忽略大小写,大写字母A和小写字母a认为是相等的。这两个函数不属于C标准库,是POSIX标准中定义的。
1.6.&搜索字符串
#include &string.h&char *strchr(const char *s, int c);char *strrchr(const char *s, int c);返回值:如果找到字符c,返回字符串s中指向字符c的指针,如果找不到就返回NULL
strchr在字符串s中从前到后查找字符c,找到字符c第一次出现的位置时就返回,返回值指向这个位置,如果找不到字符c就返回NULL。strrchr和strchr类似,但是从右向左找字符c,找到字符c第一次出现的位置就返回,函数名中间多了一个字母r可以理解为Right-to-left。
#include &string.h&char *strstr(const char *haystack, const char *needle);返回值:如果找到子串,返回值指向子串的开头,如果找不到就返回NULL
strstr在一个长字符串中从前到后找一个子串(Substring)&,找到子串第一次出现的位置就返回,返回值指向子串的开头,如果找不到就返回NULL。这两个参数名很形象,在干草堆haystack中找一根针needle,按中文的说法叫大海捞针,显然haystack是长字符串,needle是要找的子串。
搜索子串有一个显而易见的算法,可以用两层的循环,外层循环把haystack中的每一个字符的位置依次假定为子串的开头,内层循环从这个位置开始逐个比较haystack和needle的每个字符是否相同。想想这个算法最多需要做多少次比较?其实有比这个算法高效得多的算法,有兴趣的读者可以参考。
1.7.&分割字符串
很多文件格式或协议格式中会规定一些分隔符或者叫界定符(Delimiter)&,例如/etc/passwd文件中保存着系统的帐号信息:
$ cat /etc/passwdroot:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/bin/shbin:x:2:2:bin:/bin:/bin/sh...
每条记录占一行,也就是说记录之间的分隔符是换行符,每条记录又由若干个字段组成,这些字段包括用户名、密码、用户id、组id、个人信息、主目录、登录Shell,字段之间的分隔符是:号。解析这样的字符串需要根据分隔符把字符串分割成几段,C标准库提供的strtok函数可以很方便地完成分割字符串的操作。tok是Token的缩写,分割出来的每一段字符串称为一个Token。
#include &string.h&char *strtok(char *str, const char *delim);char *strtok_r(char *str, const char *delim, char **saveptr);返回值:返回指向下一个Token的指针,如果没有下一个Token了就返回NULL
参数str是待分割的字符串,delim是分隔符,可以指定一个或多个分隔符,strtok遇到其中任何一个分隔符就会分割字符串。看下面的例子。
例&25.2.&strtok
#include &stdio.h&#include &string.h&int main(void){
char str[] = "root:x::0:root:/root:/bin/bash:";
token = strtok(str, ":");
printf("%s\n", token);
while ( (token = strtok(NULL, ":")) != NULL)
printf("%s\n", token);
return 0;}
$ ./a.outrootx0root/root/bin/bash
结合这个例子,strtok的行为可以这样理解:冒号是分隔符,把"root:x::0:root:/root:/bin/bash:"这个字符串分隔成"root"、"x"、""、"0"、"root"、"/root"、"/bin/bash"、""等几个Token,但空字符串的Token被忽略。第一次调用要把字符串首地址传给strtok的第一个参数,以后每次调用第一个参数只要传NULL就可以了,strtok函数自己会记住上次处理到字符串的什么位置(显然这是通过strtok函数中的一个静态指针变量记住的)。
用gdb跟踪这个程序,会发现str字符串被strtok不断修改,每次调用strtok把str中的一个分隔符改成'\0',分割出一个小字符串,并返回这个小字符串的首地址。
(gdb) startBreakpoint 1 at 0x8048415: file main.c, line 5.Starting program: /home/akaedu/a.outmain () at main.c:55 {(gdb) n6
char str[] = "root:x::0:root:/root:/bin/bash:";(gdb)9
token = strtok(str, ":");(gdb) display str1: str = "root:x::0:root:/root:/bin/bash:"(gdb) n10
printf("%s\n", token);1: str = "root\000x::0:root:/root:/bin/bash:"(gdb)root11
while ( (token = strtok(NULL, ":")) != NULL)1: str = "root\000x::0:root:/root:/bin/bash:"(gdb)12
printf("%s\n", token);1: str = "root\000x\000:0:root:/root:/bin/bash:"(gdb)x11
while ( (token = strtok(NULL, ":")) != NULL)1: str = "root\000x\000:0:root:/root:/bin/bash:"
刚才提到在strtok函数中应该有一个静态指针变量记住上次处理到字符串中的什么位置,所以不需要每次调用时都把字符串中的当前处理位置传给strtok,但是在函数中使用静态变量是不好的,以后会讲到这样的函数是不可重入的。strtok_r函数则不存在这个问题,它的内部没有静态变量,调用者需要自己分配一个指针变量来维护字符串中的当前处理位置,每次调用时把这个指针变量的地址传给strtok_r的第三个参数,告诉strtok_r从哪里开始处理,strtok_r返回时再把新的处理位置写回到这个指针变量中(这是一个Value-result参数)。strtok_r末尾的r就表示可重入(Reentrant),这个函数不属于C标准库,是在POSIX标准中定义的。关于strtok_r的用法Man Page上有一个很好的例子:
例&25.3.&strtok_r
#include &stdio.h&#include &stdlib.h&#include &string.h&int main(int argc, char *argv[]){
char *str1, *str2, *token, *
char *saveptr1, *saveptr2;
if (argc != 4) {
fprintf(stderr, "Usage: %s string delim subdelim\n",
exit(EXIT_FAILURE);
for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
token = strtok_r(str1, argv[2], &saveptr1);
if (token == NULL)
printf("%d: %s\n", j, token);
for (str2 = ; str2 = NULL) {
subtoken = strtok_r(str2, argv[3], &saveptr2);
if (subtoken == NULL)
printf(" --& %s\n", subtoken);
exit(EXIT_SUCCESS);}
$ ./a.out 'a/bbb///xxx:yyy:' ':;' '/'1: a/bbb///cc --& a --& bbb --& cc2: xxx --& xxx3: yyy --& yyy
a/bbb///xxx:yyy:这个字符串有两级分隔符,一级分隔符是:号或;号,把这个字符串分割成a/bbb///cc、xxx、yyy三个子串,二级分隔符是/,只有第一个子串中有二级分隔符,它被进一步分割成a、bbb、cc三个子串。由于strtok_r不使用静态变量,而是要求调用者自己保存字符串的当前处理位置,所以这个例子可以在按一级分隔符分割整个字符串的过程中穿插着用二级分隔符分割其中的每个子串。建议读者用gdb的display命令跟踪argv[1]、saveptr1和saveptr2,以理解strtok_r函数的工作方式。
Man Page的BUGS部分指出了用strtok和strtok_r函数需要注意的问题:
这两个函数要改写字符串以达到分割的效果
这两个函数不能用于常量字符串,因为试图改写.rodata段会产生段错误
在做了分割之后,字符串中的分隔符就被'\0'覆盖了
strtok函数使用了静态变量,它不是线程安全的,必要时应该用可重入的strtok_r函数,以后再详细介绍&可重入&和&线程安全&这两个概念
1、出于练习的目的,strtok和strtok_r函数非常值得自己动手实现一遍,在这个过程中不仅可以更深刻地理解这两个函数的工作原理,也为以后理解&可重入&和&线程安全&这两个重要概念打下基础。
2、解析URL中的路径和查询字符串。动态网页的URL末尾通常带有查询,例如:
/search?complete=1&hl=zh-CN&ie=GB2312&q=linux&meta=/s?wd=linux&cl=3
比如上面第一个例子,/search是路径部分,?号后面的complete=1&hl=zh-CN&ie=GB2312&q=linux&meta=是查询字符串,由五个&key=value&形式的键值对(Key-value Pair)&组成,以&隔开,有些键对应的值可能是空字符串,比如这个例子中的键meta。
现在要求实现一个函数,传入一个带查询字符串的URL,首先检查输入格式的合法性,然后对URL进行切分,将路径部分和各键值对分别传出,请仔细设计函数接口以便传出这些字符串。如果函数中有动态分配内存的操作,还要另外实现一个释放内存的函数。完成之后,为自己设计的函数写一个Man Page。
阅读(...) 评论()4369人阅读
C/C++(26)
C语言的库函数中,没有类似java中String类的split方法,可以把一个长字符串分割为字符串数组。不过,还是可以利用几个库函数,自己造出split的效果。虽然不像java那样支持分隔符为正则表达式,但一般情况下也够用了。
#include &stdio.h&
#include &stdlib.h&
#include &string.h&
* count the number of a character in a string
int count_char(const char *str, char c) {
int count = 0;
while ( *p ) {
if ( *p == c )
* split a string into words, must free after use
int split(char ***words, const char *line, char delim) {
int word_counter = count_char(line, delim) + 1;
*words = (char **) malloc(sizeof(char *) * word_counter);
int i = 0;
while ( 1 ) {
p = strchr(p, delim);
int len = ( p ) ? p - s : strlen(s);
(*words)[i] = (char *) malloc(sizeof(char) * (len + 1));
strncpy((*words)[i], s, len);
(*words)[i][len] = 0;
return word_
* unit test
int main(void) {
char *line = &300;D;Event: /&843/&,/&19/&,/&-10-46-00.00/&,/&/&,/&/&,/&/&,/&0/&,/&/&,/&/&,/&/&,/&/&,/&ROAMER MTC/&,/&52/&,/&Voice MTC/&,/&843/&,/&/&,/&MO/&,/&0011/&,/&BD/&,/&-10-46-52.00/&,/&1/&,/&/&,/&^810/&,/&11^^1^957^/&,/&^^/&,/&^^^/&,/&BD/&,/&MOSMTMSC/&,/&/&,/&/&,/&/&,/&/&,/&rui_momsc1_mom1_.dat/&,/&1/&,/&/&&;
printf(&%s/n&, line);
char **words = NULL;
int n = split(&words, line, ',');
printf(&split it into %d fields:/n&, n);
for ( i = 0; i & i++) {
printf(&field %d: [%s]/n&, i, words[i]);
free(words[i]);
free(words);
这个split函数原型是:int split(char ***words, const char *line, char delim);
为什么第一个参数是指向字符串数组的指针(char ***),而不是字符串数组(char **)呢?因为在C语言中,函数中的参数其实是它实际传入参数的副本。如果调用split时仅仅把字符串数组传入,在split函数中,实际上是对其副本执行malloc操作,而其正本并未有任何改变,没有分配到新的内存,导致程序执行时崩溃。
而使用指向字符串数组的指针就不一样了。split函数会在其副本所指向的内存上进行malloc操作,也就是在其正本所指向的内存上进行malloc操作,子函数中所作的改变在调用它的函数中得以体现。
林锐的《高质量C++/C编程指南》一书中,7.4节,《指针参数是如何传递内存的?》,对此问题有详细的解释:编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是_p,编译器使_p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。&&,(但如果)_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。
此外,本案例的另一个值得注意的地方,是执行strncpy()之后,应当及时在新的字符串的末尾置结束符,否则会出现奇怪的字符串溢出错误,不要以为strncpy()之前的memset()能够解决这一问题。
本案例的测试结果如下图:
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:178599次
积分:2514
积分:2514
排名:第8836名
原创:58篇
评论:141条
(2)(1)(1)(2)(3)(1)(3)(4)(4)(3)(6)(7)(6)(6)(5)(5)用strtok函数按分隔符提取字符串-c/c++-电脑编程网用strtok函数按分隔符提取字符串作者: 冷寒生 和相关&&#include "stdio.h"
#include "string.h"
#include "conio.h"
main()
{
&&&&char c1[] = "aa,bb,cc";
&&&&char *c2 = NULL;
&&&&c2 = strtok( c1, "," );
&&&&printf( "c1 = %s\n", c1 );
&&&&while ( c2 )
&&&&{
&&&&&&&&printf( "c2 = %s\n", c2 );
&&&&&&&&c2 =
strtok( NULL, "," ); /*继续查找*/
&&&&}
&&&&getch();
}
/*打印结果:
c1 = aa
c2 = aa
c2 = bb
c2 = cc
*/相关资料:|||||||用strtok函数按分隔符提取字符串来源网络,如有侵权请告知,即处理!编程Tags:                &                    共有 1601 人关注过本帖
标题:c语言中如何输入时自定义字符串分隔符?
来 自:安徽安庆
等 级:新手上路
结帖率:50%
&&已结贴√
&&问题点数:20&&回复次数:6&&&
c语言中如何输入时自定义字符串分隔符?
默认好像是空格,如何改成其他的,如“,”。
#include &stdio.h&
char a[10];
char b[10];
scanf(&%s,%s&,&a,&b);
printf(&a=%s\nb=%s\n&,a,b);
假如输入:abc,def
那么结果是a=abc,def
然后b就是乱码
如何让a=abc
[ 本帖最后由 码农C小查 于
15:07 编辑 ]
搜索更多相关主题的帖子:
等 级:版主
威 望:58
帖 子:3837
专家分:11358
printf(&a=%s\nb=%s\n&,a.b);
能编译过吗?a和b之间应该是逗号
总有那身价贱的人给作业贴回复完整的代码
等 级:论坛游侠
帖 子:53
专家分:135
程序代码:#include &stdio.h&
char a[<font color=#];
char b[<font color=#];
scanf(&%s%s&,a,b);&&&//输入改成这样就不是乱码了
printf(&a=%s,b=%s\n&,a,b); //, 在输出控制字符串中加逗号就有逗号了
printf(&a=%s $ b=%s\n&,a,b);
等 级:蝙蝠侠
帖 子:259
专家分:809
用gets()输入多好
等 级:黑侠
帖 子:197
专家分:680
用字符串首地址接受时不用加求址符
世界上幸福的事就是抓到一只羊,更幸福的事就是抓到两只羊……
来 自:萨塔星
等 级:青峰侠
帖 子:712
专家分:1788
程序代码:#include &stdio.h&
void getstring(char *);
int main(void)
&&& char test[<font color=#];
&&& char test2[<font color=#];
&&& getstring(test);
&&& getstring(test2);
&&& printf(&\n\nOutput:\n%s\n%s\n&,test,test2);
&&& return <font color=#;
void getstring(char *test)
&&& int count = <font color=#;
&&& while((test[count] = getchar()) != ',' && test[count] != '\n')
&&& test[count] = '<font color=#';&&//覆盖','或'\n'
附件: 只有本站会员才能下载或查看附件,请
I have not failed completely
等 级:论坛游侠
帖 子:102
专家分:109
版权所有,并保留所有权利。
Powered by , Processed in 0.023276 second(s), 8 queries.
Copyright&, BCCN.NET, All Rights Reserved

我要回帖

更多关于 c语言添加千位分隔符 的文章

 

随机推荐