http://biancheng.dnbcw.info/c/452773.html
http://biancheng.dnbcw.info/c/452774.html
http://www.oschina.net/code/snippet_2325404_47570
http://blog.csdn.net/bg2bkk/article/details/37569555
c/cpp中如何分割字符串,类似于split的功能
1,分割字符串
char *strtok(char *str, const char *delim);
功能:分解字符串为一组字符串。str为要分解的字符串,delim为分隔符字符串。实质上的处理是,strtok在str中查找包含在delim中的字符并用NULL(’\0′)来替换,直到找遍整个字符串。
说明:首次调用时,str指向要分解的字符串,之后再次调用要把str设成NULL。strtok在str中查找包含在delim中的字符并用NULL(’\0′)来替换,直到找遍整个字符串。
返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。
示例:
1. #include
2. #include
3.
4. int main(){
5. //id,姓名,语文,数学,英语
6. charstr[]="2,张三,89,99,66";
7. char*token=strtok(str,",");
8. while(token!=NULL){
9. printf("%s\t",token);
10. token=strtok(NULL,",");
11. }
12. printf("\n");
13. return 0;
14. }
示例程序输出:
1. 2 张三 89 99 66
说明:str参数必须设置为数组的形式,而不是字符串常量(如:char *str="2,张三,89,99,66";),因为strtok在执行过程中会对str进行修改,必须保证str是可写的。
2,分割字符串(还是分割字符串)
char *strsep(char **stringp, const char *delim);
1. #include
2. #include
3.
4. int main(){
5. //id,姓名,语文,数学,英语
6. charstr[]="2,张三,89,99,66";
7. //str是一个指针常量,而strsep的第一个参数需要一个指向指针的指针,所以不能对str做取地址操作,
8. //这里再定义一个指针变量就可以取地址操作了。否则会出现段错误。
9. char *strv=str;
10. char*token=strsep( &strv,",");
11. while(token!=NULL){
12. printf("%s\t",token);
13. token=strsep( &strv,",");
14. }
15. printf("\n");
16. return 0;
17. }
说明:此函数也会修改第一个参数的内容,所以必须保证提供的不是字符串常量。
相关资料:
· c/c++|Linux下C程序访问mysql数据库
· c/c++|Linux下C语言字符串操作之分割字符串
· c/c++|向量空间模型——计算文本(英文)相似度
· c/c++|Linux下C语言字符串操作之连接和查找
· c/c++|C语言之预处理命令
Linux下C语言字符串操作之分割字符串来源网络,如有侵权请告知,即处理!
废话不多说,直接上代码:
1. #include
2. #include <mysql/mysql.h>
3.
4. #define HOST "192.168.56.2"
5. #define DB "webdevtest"
6. #define USER "webdev"
7. #define PWD "webdev"
8. #define PORT 3306
9.
10. int main(){
11. MYSQL mysql;
12.
13. //连接之前得先初始化
14. mysql_init(&mysql);
15.
//连接mysql数据库
1. if(!mysql_real_connect(&mysql,HOST,USER,PWD,DB,PORT,NULL,0)){
2. printf("连接数据库发生错误!\n");
3. return-1;
4. }
5. printf("连接数据库成功!\n");
6.
7. //设置查询时的编码
8. mysql_query(&mysql,"setnames utf8");
9.
//执行查询语句
char *sql="select * from test_sell_records limit 20";
1. if(mysql_query(&mysql,sql)!=0){
2. printf("执行mysql语句发生错误!\n");
3. mysql_close(&mysql);
4. return-1;
5. }
6. //获取结果集
7. MYSQL_RES*result=mysql_store_result(&mysql);
8. unsigned inti,num_fields;
9. //获取字段数
10. num_fields=mysql_num_fields(result);
1. //循环打印出各行
2. MYSQL_ROW row;
3. while((row=mysql_fetch_row(result))!=NULL){
4. for(i=0;i 5. printf("%s\t",row[i]); 6. } 7. printf("\n"); 8. } 9. 10. //释放结果集 11. mysql_free_result(result); 12. //关闭连接 13. mysql_close(&mysql); 14. return 0; 15. } 以上用到的函数为: 1. gcc -o mysql_test mysql_test.c-lmysqlclient 在Linux下用C语言开发mysql客户端程序,需要安装mysql开发包,请参考: 相关资料: · c/c++|Linux下C程序访问mysql数据库 · c/c++|Linux下C语言字符串操作之分割字符串 · c/c++|向量空间模型——计算文本(英文)相似度 · c/c++|Linux下C语言字符串操作之连接和查找 Linux下C程序访问mysql数据库来源网络,如有侵权请告知,即处理! #include #include #include #include #include #include #include #include #include #include #include #include #include #define N 7 MYSQL my_sql; DIR * my_dir = NULL; char *args[N] ={NULL,NULL,NULL,NULL,NULL,NULL,NULL}; void read_dir(char *); void connect_mysql(); void set_work(); void get_file_infor(const char *,char *); void write_mysql(); int main(int argc,char *argv[]) { if(argc != 2) { fprintf(stderr,"arguments is not two!\n"); return -1; }else { connect_mysql(); set_work(); read_dir(argv[1]); } mysql_close(&my_sql); return EXIT_SUCCESS; } void read_dir(char *dirname) { struct dirent * dir; int n = 0; my_dir = opendir(dirname); if(!my_dir) { fprintf(stderr,"open dir fail %s\n",strerror(errno)); }else { while((dir = readdir(my_dir))) { if(strcmp(".",dir->d_name)&&strcmp("..",dir->d_name)) { for(;n < N;n++) { args[n] = (char*)malloc(256); if(!args[n]) { fprintf(stderr,"malloc fail\n"); closedir(my_dir); exit(-1); } } args[0] = dir->d_name; get_file_infor(dir->d_name,dirname); printf("\n"); } } } } void connect_mysql() { mysql_init(&my_sql); if(mysql_real_connect(&my_sql,"localhost","ma","123456ma", "student",0,0,0)) { printf("connect mysql success\n"); }else{ fprintf(stderr,"connect mysql fail%s",mysql_error(&my_sql)); exit(-1); } } void set_work() { int res1,res2; res1 =mysql_query(&my_sql,"set names utf8"); res2 = mysql_query(&my_sql,"use student"); if(res1) { fprintf(stderr,"set character fail!%s\n",mysql_error(&my_sql)); }else printf("set character success !\n"); if(res2) { fprintf(stderr,"use student database fail !%s\n",mysql_error(&my_sql)); }else printf("use database success !\n"); } void write_mysql() { printf("\t#######start write into mysql#######\n"); int res ; char * infor = (char *)malloc(512); memset(infor,0,512); sprintf(infor,"INSERT INTOFile(filename,filemode,filelink,fileown,filegroup,filetime,filesize) VALUES('%s','%s',%s,'%s','%s','%s',%s)",args[0],args[1],args[2],args[3],args[4],args[5],args[6]); infor[strlen(infor)]= '\0'; // printf("%s\n",infor); res = mysql_query(&my_sql,infor); if(!res) printf("Insert %lu rows\n",(unsignedlong)mysql_affected_rows(&my_sql)); else fprintf(stderr,"Insert data fail%s\n",mysql_error(&my_sql)); } void get_file_infor(const char *path1,char*arg) { struct stat filestat; int n = 0; char *path = (char *)malloc(256); memset(path,0,256); sprintf(path,"%s/%s",arg,path1); if(lstat(path,&filestat)) { fprintf(stderr,"get inode information fail%s\n",strerror(errno)); return; }else { switch(filestat.st_mode & S_IFMT) { case S_IFBLK: args[1] ="block";break; case S_IFCHR: args[1] = "character";break; case S_IFDIR: args[1] = "directory";break; case S_IFIFO: args[1] = "FIFO/pipe";break; case S_IFLNK: args[1] = "symlink";break; case S_IFREG: args[1] = "regularfile";break; case S_IFSOCK: args[1] = "socket";break; default: args[1] = "unknown"; } sprintf(args[2],"%ld ",(unsigned long)filestat.st_nlink); struct passwd * passwd = getpwuid(filestat.st_uid); sprintf(args[3],"%s ",passwd->pw_name); struct group * group = getgrgid(filestat.st_gid); sprintf(args[4],"%s ",group->gr_name); struct tm *filetime = gmtime(&(filestat.st_mtime)); sprintf(args[5],"%d/%d/%d",filetime->tm_year+1900,filetime->tm_mon,filetime->tm_mday); sprintf(args[6],"%lld",filestat.st_size); write_mysql(); } } 在python中,如果要求当前时间的unix时间戳,我特别喜欢这么用: [python] view plaincopy 1. import time 2. timestr = time.time() 3. timestamp = int(timestr.split('.')[0]) 如果要处理一个字符串型的“192.168.1.254”,想把每个字段都分开,怎么办呢,C标准库中有函数strtok()的实现,可以一用。 [cpp] view plaincopy 1. #include 2. #include 3. #include 4. 5. int main() 6. { 7. char ip_str[] = "192.168.1.250"; 8. char *ip_arr[4] ; 9. char * s = strtok(ip_str, "."); 10. int i=0; 11. while(s) 12. { 13. ip_arr[i] = s; 14. s = strtok(NULL, "."); 15. i++; 16. // printf("%s\n",s); 17. } 18. 19. for(i=0; i<4; i++) 20. printf("%s\n",ip_arr[i]); 21. } [html] view plaincopy 1. /* 2. * linux/lib/string.c 3. * 4. * Copyright (C) 1991, 1992 Linus Torvalds 5. */ 6. 7. /* 8. * stupid library routines.. The optimized versions should generally be found 9. * as inline code in 10. * 11. * These are buggy as well.. 12. * 13. * * Fri Jun 25 1999, Ingo Oeser 14. * - Added strsep() which will replace strtok() soon (because strsep() is 15. * reentrant and should be faster). Use only strsep() in new code, please. 16. * 17. * * Sat Feb 09 2002, Jason Thomas 18. * Matthew Hawkins 19. * - Kissed strtok() goodbye 20. */ 因为strsep是线程安全的,并且速度上更快一些,所以采用strsep来替换strtok,接下来我会试一试strsep。在这里感慨下,没事的时候或者写程序的时候,用man和查看源码的方式,能学到很多基本的知识,比如内核源码的lib文件夹下,linux内核使用的rbtree结构,还有lib文件夹的string.c,include下的string.h里的各种strcpy,strcat等基本函数的实现,都是非常经典而且久经考验的。 在strtok使用的代码里,有两处很有意思。 其中一个,修改第7行,如下所示: [cpp] view plaincopy 1. #include 2. #include 3. #include 4. 5. int main() 6. { 7. char *ip_str = "192.168.1.250"; 8. char *ip_arr[4] ; 9. char * s = strtok(ip_str, "."); 10. int i=0; 11. while(s) 12. { 13. ip_arr[i] = s; 14. s = strtok(NULL, "."); 15. i++; 16. // printf("%s\n",s); 17. } 18. 19. for(i=0; i<4; i++) 20. printf("%s\n",ip_arr[i]); 21. } [cpp] view plaincopy 1. Program terminated with signal 11, Segmentation fault. 2. #0 strtok () at ../sysdeps/i386/i686/strtok.S:245 3. 245 movb $0, (%edx) /* Terminate string. */ 4. (gdb) where 5. #0 strtok () at ../sysdeps/i386/i686/strtok.S:245 6. #1 0x0804841e in main () at test.c:9 而这段代码在VS下是没有问题的,所以这个原因需要找一下。 这个原因找到了,在链接http://www.cnblogs.com/longzhao1234/archive/2012/05/31/2528317.html 通过阅读源代码,因为函数内部会修改原字符串变量,所以传入的参数不能是不可变字符串(即文字常量区)。 VS在很多情况下要比GCC优秀很多,VS的CPP支持是最全面的,可以这么说。好多CPP的作者啦,大牛啦,都是M$的VC组的,好牛逼的地方。 另外在改一处,这次只改第16行,将printf语句注释掉,代码如下: [cpp] view plaincopy 1. #include 2. #include 3. #include 4. 5. int main() 6. { 7. char ip_str[] = "192.168.1.250"; 8. char *ip_arr[4] ; 9. char * s = strtok(ip_str, "."); 10. int i=0; 11. while(s) 12. { 13. ip_arr[i] = s; 14. s = strtok(NULL, "."); 15. i++; 16. printf("%s\n",s); 17. } 18. 19. for(i=0; i<4; i++) 20. printf("%s\n",ip_arr[i]); 21. } 分析core文件,出错如下: [cpp] view plaincopy 1. Program terminated with signal 11, Segmentation fault. 2. #0 __strlen_ia32 () at ../sysdeps/i386/i586/strlen.S:99 3. 99 movl (%eax), %ecx /* get word (= 4 bytes) in question */ 4. (gdb) where 5. #0 __strlen_ia32 () at ../sysdeps/i386/i586/strlen.S:99 6. #1 0x00b9ddd5 in _IO_puts (str=0x0) at ioputs.c:37 7. #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',代表行缓冲结束,需要输出,如果我不让他输出,会怎样? 打印结果为: [cpp] view plaincopy 1. 168 1 250 (null) 好吧我也不知道是什么了,而且这个结果与是否有'\0'符号无关。 这两个地方一定要找出来问题,嗯。 接下来我们看看strsep的用法吧 [cpp] view plaincopy 1. #include 2. #include 3. #include 4. 5. int main() 6. { 7. char ip_str[] = "192.168.1.250"; 8. char *p = ip_str; 9. char *ip_arr[4] ; 10. char * s = strsep(&p, "."); 11. int i=0; 12. while(s) 13. { 14. ip_arr[i] = s; 15. s = strsep(&p, "."); 16. i++; 17. // printf("%s\n",s); 18. } 19. 20. for(i=0; i<4; i++) 21. printf("%s\n",ip_arr[i]); 22. }
mysql_init()
mysql_real_connect()
mysql_query()
mysql_store_result()
mysql_num_fields()
mysql_fetch_now()
mysql_free_result()
mysql_close()
还有,编译的时候不要忘记了添加 -lmysqlclient 参数:
http://blog.chinaunix.net/uid-20769015-id-3540362.html
mysql官方C API参考:http://dev.mysql.com/doc/refman/5.1/en/c-api-functions.html
这里的split函数,我非常喜欢,在java、c#和python中都有,很方便,不用担心踩地雷,但是C/CPP中,就没有了,这点比较遗憾。
在这里,strtok是非线程安全的,这点也可以在程序的第二次strtok调用中看到,因此linux用strsep来替换strtok了,我在linux2.6.22的源码/lib/string.c和linux-3.3中同文件中,c文件开头就是这样一段话:
将char ip_str[] ="192.168.1.250";改为char *ip_str = "192.168.1.250";就会core dump,通过gdb和core文件来看,程序崩溃在了
如 char *tokenremain ="abcdefghij"//编译时为文字常量,不可修改。
strtok(tokenremain,"cde");
strsep(&tokenremain,"cde");
编译通过,运行时会报段错误。
又崩溃了,我也整个人都不好了。
用法也差不多。