在C语言中分割字符串

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; char *p = str; while ( *p ) { if ( *p == c ) count++; p++; } return count; } /* * 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; char *p = line; while ( 1 ) { char *s = p; 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; if ( !p ) break; p++; i++; } return word_counter; } /* * unit test */ int main(void) { char *line = "300;D;Event: \"460008103448843\",\"19\",\"2010/09/07-10-46-00.00\",\"\",\"\",\"\",\"0\",\"\",\"\",\"\",\"\",\"ROAMER MTC\",\"52\",\"Voice MTC\",\"460008103448843\",\"\",\"MO\",\"0011\",\"45500000103BD\",\"2010/09/07-10-46-52.00\",\"1\",\"\",\"8647145557^353070016806810\",\"11^^1^957^\",\"^^\",\"^^^\",\"45500000103BD\",\"MOSMTMSC\",\"\",\"\",\"\",\"\",\"rui_momsc1_mom1_1572_02933.dat\",\"1\",\"\""; printf("%s\n", line); char **words = NULL; int n = split(&words, line, ','); printf("split it into %d fields:\n", n); int i; for ( i = 0; i < n; i++) { printf("field %d: [%s]\n", i, words[i]); free(words[i]); } free(words); return 0; }

这个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()能够解决这一问题。

本案例的测试结果如下图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值