c - 打印文件中所有字符串的 k-mer
问题描述
我有一个包含字符串列表的文件。我尝试生成所有这些 k-mer。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* substr(const char *string, size_t start, size_t end) {
const char *char_start = &string[start];
const char *char_end = &string[end];
char *substring = (char *) calloc(1, char_end - char_start + 1);
memcpy(substring, char_start, char_end - char_start + 1);
return substring;
}
int main(void) {
FILE *file;
file = fopen("out/clean_read_1.txt", "r");
if (file == NULL) {
perror("File not found!\n");
exit(0);
}
char *line = NULL;
size_t i, len = 0, k = 5;
ssize_t read;
while ( (read = getline(&line, &len, file)) != -1 ) {
for ( i = 0; i < strlen(line) - k; i++ )
printf("%s\n", substr(line, i, i + k - 1));
}
printf("\n");
fclose(file);
return 0;
}
这是文件:
ACCAG
CAGTGAA
TGAACGGTA
我不明白为什么代码不生成最后一个 k-mer。
预期的正确输出:
ACCAG
CAGTG
AGTGA
GTGAA
TGAAC
GAACG
AACGG
ACGGT
CGGTA
我的代码输出不正确:
ACCAG
CAGTG
AGTGA
GTGAA
TGAAC
GAACG
AACGG
ACGGT
解决方案
我注意到除了最后一行之外,文件中的每一行都以'\n'
. 由于getline()
也将 in 写入\n
(line
当它在文件中找到时),因此strlen(line)
将始终比该行中可见字符的数量多一个,除非使用最后一行,因为它不包含'\n'
.
例如,在处理文件中倒数第二行时,line
将包含"CAGTGAA\n\0"
. 不计算终止'\0'
,那些是 7 个字母字符 + - 字符'\n'
。总共有 8 个strlen(line)
将返回。因此strlen(line) - k
将等于 3 导致for
-loop 循环 3 次。
但是当使用文件中的最后一行时,line
将包含"TGAACGGTA\0"
. 不计算 terminating '\0'
,那些是 9 个字母字符,但没有'\n'
-character 所以strlen(line)
只会返回 9。因此strlen(line) - k
将等于 4 导致for
-loop 只循环 4 次而不是 5 次,导致不生成第 5 个 k-mer。
您需要执行以下操作之一:
A) 在文件末尾添加一个空行,以便当前最后一行也以'\n'
.
或: B)更改for
-loop:
while ( (read = getline(&line, &len, stdin)) != -1 ) {
for ( i = 0; line[i+k-1] != '\n' && line[i+k-1] != '\0'; i++ )
或:C)'\n'
当它位于带有终止符的行尾时覆盖,'\0'
以便这些行仅包含您要使用的字母字符。然后更改for
-loop 中的条件以考虑到这些行现在比以前短了一个字符。(请注意,由于getline()
返回写入的字符数,而不是计数'\0'
,并且您将其存储在 中read
,因此无需一次又一次地重新计算字符串的长度):
while ( (read = getline(&line, &len, stdin)) != -1 ) {
if (line[read - 1] == '\n') line[--read] = '\0';
for ( i = 0; i <= read - k; i++ )
您的代码至少还有一个问题。substring
您为每次调用分配空间substr()
但您从未释放它,导致内存泄漏(严格来说您也应该 free line
)。
推荐阅读
- python - 如何将 Boost.Python 中的 map_indexing_suite 与自定义非标准对象一起使用?
- webrtc - jitsi 会议截图
- java - JWT 验证失败:无法为 RSA 签名指定密钥字节。请指定 PublicKey 或 PrivateKey 实例
- javascript - 如何使用jquery在循环中更改每个按钮的值
- entity-framework-core - 实体框架核心排除 INNER JOIN
- c# - 封装没有 lambda 表达式的字段
- c# - 如何使用 C# 中的 zkemkeeper 库在图片框中的运行时获取指纹?
- python - 根据熊猫组比较日期
- machine-learning - TFF 联邦学习,评估方法
- ios - 自定义委托以使用 UIView 类中的 pushViewController