首页 > 解决方案 > 打印文件中所有字符串的 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

标签: csubstring

解决方案


我注意到除了最后一行之外,文件中的每一行都以'\n'. 由于getline()也将 in 写入\nline当它在文件中找到时),因此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)。


推荐阅读