编写程序以在C中创建变量

时间:2013-01-22 01:20:27

标签: c variables bioinformatics

我正在用C编写一个程序来读取FASTA文件中的文本和每个名字(例如> COTV-SPAn232-096)我希望我的程序识别出'>'然后在\ n之前使用以下文本作为变量的名称。

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

  

COTV-SPAn232-096   MKILNSYNDFIISFINFILFPTIQNVSISKLNILGYILSFIRIISISMDFDILKFSNIIQDYGLIFPDDIKKIQNEKFLVLERGLSGKLYAIHIYDFMARFDNETIFGIAKFLYRNNTKILDVLFINKDLFDKTDILYPKSTITLSSYSDEYIDYTYKTIKLIFLNLFNSFRFSKIDSKLSYLYLPLRKDINNVIL

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

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

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

3 个答案:

答案 0 :(得分:6)

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

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

哈希表的C库示例在网上比比皆是:这个StackOverflow question提供了一些。

答案 1 :(得分:2)

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

好消息是您不需要将新变量命名为新名称。您只需要一个包含名称的第二个变量。您只需要一对变量 - 一个用于name,另一个用于value

答案 2 :(得分:2)

  

以序列名称读取计划,将该名称设置为动态数组的变量,并使用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指针分配空间,并为char *指针内的标题和序列fasta_t分配空间:

#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元素的标题,例如:

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

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

完成后,请确保在free()指针内fasta_t *个别指针,fasta_t *指针本身,然后指向指针的fasta_t **指针:

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;

为方便起见,一旦你掌握了处理struct和内存管理的问题,你就会想要编写设置,访问,编辑和分解fasta_t *元素的包装函数,以及为fasta_t *元素列表执行相同操作的包装函数。