【问题标题】:Writing a program to create variables as it needs them in C编写程序以在 C 中根据需要创建变量
【发布时间】:2013-01-05 04:23:15
【问题描述】:

我正在用 C 编写一个程序来读取 FASTA 文件中的文本以及每个名称(例如 >COTV-SPAn232-096),我希望我的程序能够识别“>”,然后在\n 用作变量的名称。

对变量进行硬编码的问题在于,该程序需要尽可能动态,因为它可以读取任意数量的不同数据集。例如,我的测试集有 15 个不同的序列,看起来像这样:

COTV-SPAn232-096 MKILNSYNDFIISFINFILFPTIQNVSISKLNILGYILSFIRIISISMDFDILKFSNIIQDYGLIFPDDIKKIQNEKFLVLERGLSGKLYAIHIYDFMARFDNETIFGIAKFLYRNNTKILDVLFINKDLFDKTDILYPKSTITLSSYSDEYIDYTYKTIKLIFLNLFNSFRFSKIDSKLSYLYLPLRKDINNVIL

计划以序列的名称读取,将该名称设置为动态数组的变量,并使用 malloc/realloc 处理存储实际序列,以便以后比较所有不同的序列。我可以处理除变量变量名之外的所有内容。

简单地四处寻找答案,似乎无法用 C 语言完成,但可以用 python 和其他一些语言完成。我真的希望这不是实际情况,但如果是这样的话,有没有人有其他建议来处理这个问题?是的,这是生物信息学,我可能应该使用 python、perl、java 或其他语言,但我宁愿继续在 C 中解决这个问题,以便进一步精通 C。

提前感谢我可能收到的任何答案!

【问题讨论】:

  • 在 C 中工作作为精通 C 的一种方式是可以理解的。但是考虑到你的领域,你打算在 C 领域呆多久?更“现代”的语言拥有比 C 语言更好、更容易使用的文本/字符串操作工具,很难想象你会长期留在 C 语言中。不过学一会C还是很值得的。
  • 我推荐学习 C,因为 Python 在 I/O 操作上非常慢。 IME,在现代 Linux 系统上,Python 在读取标准输入和写入标准输出时可能比 C 慢 9-10 倍,即使使用“Pythonic”代码也是如此。大部分生物信息学都是关于解析和处理文本文件的,所以如果你打算编写运行速度尽可能快的软件,C 并不是唯一的选择,但它的性能通常比 Python、Perl 或其他解释性脚本要好得多语言。

标签: c variables bioinformatics


【解决方案1】:

这在 C 中是不可能的,但从来没有理由创建具有动态名称的变量(事实上,即使您在 C 中创建了这样的变量,您将如何使用它们?)

改为使用hash table- 这是一种从键映射到值的数据结构。在您的情况下,您希望它从字符串(您的序列名称)映射到字符串(您的序列)。

网上有很多用于哈希表的 C 库示例:StackOverflow question 提供了一些。

【讨论】:

    【解决方案2】:

    坏消息是它不能在 C 中完成,因为 C 变量是一个编译时概念。变量充当包含数据的内存区域的“标签”;一旦编译器完成,大多数变量的名称都会被丢弃。它们可能会被写入单独的文件以供调试器使用,但这对人类来说很方便。

    好消息是您不需要将新变量命名为新名称。您所需要的只是包含名称的第二个变量。一对变量——一个用于name 和一个用于value 就足够了。

    【讨论】:

      【解决方案3】:

      计划以序列的名称读取,将该名称设置为动态数组的变量,并使用 malloc/realloc 处理存储实际序列,以便以后比较所有不同的序列。我可以处理除变量变量名之外的所有内容。

      不要用序列头/名称来命名变量,而是创建一个struct 来保存序列头/名称和序列,例如:

      typedef struct {
          char *header;
          char *sequence;
      } fasta_t;
      

      然后创建fasta_t指针列表(“指向指针的指针”):

      fasta_t **fasta_elements = NULL;
      

      使用malloc()N 类型为fasta_t * 的元素分配空间,例如

      fasta_elements = malloc(N * sizeof(fasta_t *));
      

      检查你是否真的得到了你要求的内存是个好主意:

      if (!fasta_elements) {
          /* i.e., if fasta_elements is still NULL */
          fprintf(stderr, "ERROR: Could not allocate space for FASTA element list!\n");
          return EXIT_FAILURE;
      }
      

      (在我看来,您应该养成使用malloc() 的每个指针都这样做的习惯。)

      现在已经分配了空间,读入N 元素(如果我们需要使列表更大,请使用realloc(),但我们现在假设N 元素)。在一个循环中,为单个 fasta_t 指针分配空间,以及为 fasta_t 指针内的标题和序列 char *s 分配空间:

      #define MAX_HEADER_LENGTH 256
      #define MAX_SEQUENCE_LENGTH 4096
      
      /* ... */
      
      size_t idx;
      char current_header[MAX_HEADER_LENGTH] = {0};
      char current_sequence[MAX_SEQUENCE_LENGTH] = {0};
      
      for (idx = 0U; idx < N; idx++) 
      {
          /* set up space for the fasta_t struct members (the header and sequence pointers) */
          fasta_elements[idx] = malloc(sizeof(fasta_t));
      
          /* parse current_header and current_sequence out of FASTA input */
          /* ... */
      
          /* validate input -- does current_header start with a '>' character, for instance? */
          /* data in bioinformatics is messy -- validate input where you can */
      
          /* set up space for the header and sequence pointers */
          /* sizeof(char) is redundant in C, because sizeof(char) is always 1, but I'm putting it here for completeness */
          fasta_elements[idx]->header = malloc((strlen(current_header) + 1) * sizeof(char)); 
          fasta_elements[idx]->sequence = malloc((strlen(current_sequence) + 1) * sizeof(char));
      
          /* copy each string to the list pointer, for which we just allocated space */
          strncpy(fasta_elements[idx]->header, current_header, strlen(current_header) + 1);
          strncpy(fasta_elements[idx]->sequence, current_sequence, strlen(current_sequence) + 1);
      }
      

      打印出i+1'th 元素的头部,例如:

      fprintf(stdout, "%s\n", fasta_elements[i]->header);
      

      (请记住,C 中的索引是从 0 开始的——例如,第 10 个元素的索引为 9。)

      完成后,请务必在 fasta_t * 指针、fasta_t * 指针本身以及 fasta_t ** 指向指针的指针中添加 free() 各个指针:

      for (idx = 0U; idx < N; idx++) 
      {
          free(fasta_elements[i]->header), fasta_elements[i]->header = NULL;
          free(fasta_elements[i]->sequence), fasta_elements[i]->sequence = NULL;
          free(fasta_elements[i]), fasta_elements[i] = NULL;
      }
      free(fasta_elements), fasta_elements = NULL;
      

      为方便起见,一旦您掌握了处理structs 和内存管理的窍门,您将需要编写用于设置、访问、编辑和分解fasta_t * 元素的包装器函数以及包装器对fasta_t * 元素列表执行相同操作的函数。

      【讨论】:

        猜你喜欢
        • 2014-05-19
        • 1970-01-01
        • 1970-01-01
        • 2012-11-01
        • 1970-01-01
        • 2021-08-11
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        相关资源
        最近更新 更多