免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6908 | 回复: 16
打印 上一主题 下一主题

[C] 如何更加效率的将多行文本(字符串)拼接成一行? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-06-26 08:51 |只看该作者 |倒序浏览
如题。输入文件就是基因组文件,文件格式如下:
……
>1
TTATCCACAGAACTGTGCGTCCTTTGTTAACTTCTACTACGTATATATACAAGTAAACCTTTGAAACCAAAGACCTGCGG
TGCCGCACAGCGCCGCGAGTCGATTCAATCGGTTCCGGAGCGAAAAAGCTGTGGCACAATCGGTTTCCTTCGCGTTCGTT
CGGCCAGGCGCCGGACATGCTTCAATGGAACGGTCGGCACGATTTCGAATCAGAATCCTCGAGACTGCGCAGTCCGTTCA
CACACCAGGCCGACAATCCAGATCGGCAACCTGAACGACGTTCCGCCCTGTGGTGGAACAGGCGGACCCCATGTACCGCC
GTCGTCGAGCACAACAATCACATTCGGGGCGATACCCAGCCGGCGCGCATCCATTCCTGTCGCTTGACCCCGCGTCGCTG
GCGGTTGCTTCCAAAGGAGAAGTCACCACGATGAAGTCGGCGTTCTCATTCCTGCCCAACTGGCCGCTTACGCCGGATGC
……
文件中有多个这种格式的块,每个块的行数不同,每行的字符个数相同(除了每个块的最后一行)。

现在我需要将文件中每个块中除了以">"开头的行之外的多行文本(字符串)拼接成一行,如何做效率才更高?我自己写的一个函数处理270多万行的数据竟然了用了3万多秒,合8个多小时,这也太不正常了。。。

函数代码如下:
  1. char *get_segment(int seq_lines, long record_offset){
  2.     char *line_tmp = (char *)malloc(MAX_LINE_TMP*sizeof(char));
  3.     int max_line_tmp = MAX_LINE_TMP;
  4.     *segment = '\0';
  5.     fseek(fp,record_offset,SEEK_SET);
  6.     while(fgets(line_tmp, max_line_tmp, fp) != NULL){
  7.         if(strchr(line_tmp,'>') != NULL){
  8.             break;
  9.         }
  10.         else{
  11.             line_tmp[strlen(line_tmp)-1] = '\0';//\r and \n at at the end of line
  12.             strcat(segment,line_tmp);
  13.         }
  14.     }
  15.     free(line_tmp);
  16.     return segment;
  17. }
复制代码
函数的两个参数是我对文件进行预处理得到的每个块的行数以及相对于文件开始位置的偏移量。
我学习C语言不久,新手一枚,还请大家指点!

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
2 [报告]
发表于 2013-06-26 08:59 |只看该作者
主要可以优化以下两点:
segment中内容是否很长,那么每次strcat都要找到结尾会很花时间的,自己记录下尾部位置,改用memcpy。
>只出现在开始处,就不要用strchr判断了,直接判断首字符。

论坛徽章:
0
3 [报告]
发表于 2013-06-26 09:01 |只看该作者
本帖最后由 xlwang_0903 于 2013-06-26 09:05 编辑

回复 2# hellioncu

segment的确会很长,相当的长。您说的记录位置指的是segment的长度吗?另外,有没有其他效率更高的算法或者是方法?


   

论坛徽章:
1
子鼠
日期:2013-08-23 16:36:37
4 [报告]
发表于 2013-06-26 09:14 |只看该作者
这里面的效率主要涉及到fseek strcat 函数,是否可以先全部或部分读到内存在进行判断,这样效率应该会提高很多

论坛徽章:
0
5 [报告]
发表于 2013-06-26 09:25 |只看该作者
float001 发表于 2013-06-26 09:14
这里面的效率主要涉及到fseek strcat 函数,是否可以先全部或部分读到内存在进行判断,这样效率应该会提高很 ...


您指的是文件的全部或部分读入内存吗?

论坛徽章:
1
子鼠
日期:2013-08-23 16:36:37
6 [报告]
发表于 2013-06-26 09:37 |只看该作者
回复 5# xlwang_0903


    对啊 ,这样不是比一行一行的读取快很多

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
7 [报告]
发表于 2013-06-26 09:56 |只看该作者
  1. #include <stdio.h>

  2. int main()
  3. {
  4.     FILE *fin = fopen( "a.txt", "rt" );
  5.     FILE *fout = fopen( "b.txt", "wt" );
  6.     // 遇到>时,前面加个回车,并把这行原样输出
  7.     {
  8.         int c;
  9.         while( c=fgetc(fin), c!=EOF )
  10.         {
  11.             switch( c )
  12.             {
  13.             case '>':
  14.                 fputc('\n',fout);
  15.                 fputc(c,fout);
  16.                 while( c=fgetc(fin), c!=EOF && c!='\n' ) fputc(c,fout);
  17.                 fputc('\n',fout);
  18.                 break;
  19.             case '\n':
  20.                 break;
  21.             default:
  22.                 fputc(c,fout);
  23.             }
  24.         }
  25.     }
  26.     fclose( fout );
  27.     fclose( fin );

  28.     return 0;
  29. }
复制代码

论坛徽章:
0
8 [报告]
发表于 2013-06-26 10:07 |只看该作者
bruceteen 发表于 2013-06-26 09:56

逐个字符读取的话会更快吗?

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
9 [报告]
发表于 2013-06-26 10:19 |只看该作者
xlwang_0903 发表于 2013-06-26 10:07
逐个字符读取的话会更快吗?

有程序,有数据,你试一下不就知道了吗?

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:50:28
10 [报告]
发表于 2013-06-26 10:31 |只看该作者
1楼正解。
每次要扫描整个字符串,找末尾的\x00,随着这个字符串越来越大,这样不慢才怪了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP