C语言碱基配对程序输出异常:如何实现逐个字符对应输出?
碱基配对逐个字符处理问题排查与解决
问题说明
需求是实现逐个字符处理的碱基配对,预期输出为每行单个碱基与其配对碱基的对应关系:
G -- C C -- G T -- A T -- A C -- G T -- A T -- A A -- T C -- G C -- G C -- G G -- C T -- A
但实际运行后,输出的是从当前字符开始的剩余字符串与配对字符的对应,不符合预期:
GCTTCTTACCCGTGCCCCAC -- C CTTCTTACCCGTGCCCCAC -- G TTCTTACCCGTGCCCCAC -- A TCTTACCCGTGCCCCAC -- A CTTACCCGTGCCCCAC -- G TTACCCGTGCCCCAC -- A TACCCGTGCCCCAC -- A ACCCGTGCCCCAC -- T CCCGTGCCCCAC -- G CCGTGCCCCAC -- G CGTGCCCCAC -- G GTGCCCCAC -- C TGCCCCAC -- A GCCCCAC -- C CCCCAC -- G CCCAC -- G CCAC -- G CAC -- G AC -- T C -- G
问题代码
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/mman.h> int main(int argc, char **argv){ int buff = 100; char *ptr = mmap (NULL,buff, PROT_WRITE | PROT_READ ,MAP_PRIVATE| MAP_ANONYMOUS,0,0); if(ptr == MAP_FAILED){ printf("Mapping Failed\n"); return 1; } char *oof = mmap (NULL,buff, PROT_WRITE | PROT_READ ,MAP_PRIVATE| MAP_ANONYMOUS,0,0); if(oof == MAP_FAILED){ printf("Mapping Failed\n"); return 1; } int f1 = open("file.txt", O_RDWR); int length = read(f1,ptr,sizeof(char)*buff); for(int i = 0; i<length;i++){ if(ptr[i] == 'A'){ oof[i] = 'T'; } if(ptr[i] == 'T'){ oof[i] = 'A'; } if(ptr[i] == 'C'){ oof[i] = 'G'; } if(ptr[i] == 'G'){ oof[i] = 'C'; } printf("%s -- %s\n", &ptr[i],&oof[i]); } }
核心错误点
- printf格式符误用:
%s用于输出以\0结尾的字符串,但你传入的&ptr[i]是从第i个字符开始的整个剩余字符序列(读入的文件内容未添加字符串结束符\0),所以会输出从当前位置到内存中随机\0的所有内容,而非单个字符。 - oof数组无结束符:即使
&oof[i]指向配对后的字符,后续内存没有\0,输出时会读取到未知内容,但核心问题还是格式符用错。
修复方案
将printf中的格式符从%s改为%c,直接传入单个字符(无需取地址),同时补充文件关闭、内存释放等健壮性代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> int main(int argc, char **argv){ int buff = 100; char *ptr = mmap(NULL, buff, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); if(ptr == MAP_FAILED){ printf("Mapping Failed\n"); return 1; } char *oof = mmap(NULL, buff, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); if(oof == MAP_FAILED){ printf("Mapping Failed\n"); munmap(ptr, buff); // 释放已分配的内存 return 1; } int f1 = open("file.txt", O_RDONLY); // 只读打开即可 if(f1 == -1){ printf("Open file failed\n"); munmap(ptr, buff); munmap(oof, buff); return 1; } int length = read(f1, ptr, buff); close(f1); // 关闭文件 for(int i = 0; i < length; i++){ // 用else if减少不必要的判断 if(ptr[i] == 'A'){ oof[i] = 'T'; } else if(ptr[i] == 'T'){ oof[i] = 'A'; } else if(ptr[i] == 'C'){ oof[i] = 'G'; } else if(ptr[i] == 'G'){ oof[i] = 'C'; } else { oof[i] = '?'; // 处理未知碱基 } // 用%c输出单个字符,无需取地址 printf("%c -- %c\n", ptr[i], oof[i]); } // 释放mmap内存 munmap(ptr, buff); munmap(oof, buff); return 0; }
额外优化点
- 将连续的
if改为else if,避免不必要的条件判断 - 打开文件时用
O_RDONLY替代O_RDWR,符合只读需求 - 添加文件打开失败的错误处理
- 补充
munmap释放内存,避免内存泄漏 - 增加未知碱基的容错处理
内容的提问来源于stack exchange,提问作者Goodoboi69
相关产品推荐
相关产品推荐

