首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用数组和for循环,但不使用字符串或任何类

使用数组和for循环,但不使用字符串或任何类
EN

Stack Overflow用户
提问于 2013-03-17 02:21:24
回答 3查看 2.3K关注 0票数 3
代码语言:javascript
复制
void printEncodingCodonSequences (
            char aminoAcid1,
            char aminoAcid2,
            char aminoAcid3, 
            char aminoAcid4,
            char aminoAcid5
);

给定一个由5个氨基酸符号组成的蛋白质片段作为输入,在屏幕上打印出翻译成该蛋白质片段的所有不同的密码子序列(每行一个序列)。输入可以是任何大小写,如果任何输入无效,函数应打印‘?’。在一行中。

这里有一个例子:蛋白质片段MWQWH可以由这四个密码子序列翻译,因此对于输入:‘M’,‘W’,‘Q’,‘W’,‘H’(或‘m’,‘W’,‘Q’,‘W’,‘H’),函数应该打印以下内容:

代码语言:javascript
复制
ATGTGGCAATGGCAT
ATGTGGCAGTGGCAT
ATGTGGCAATGGCAC
ATGTGGCAGTGGCAC

我不期望你回答所有的问题,只是提示一下怎么做。对于此任务,不允许任何字符串或任何容器类!我被告知我必须对数组使用嵌套循环。

在这个项目中,蛋白质片段由5个氨基酸组成(输入为它们的符号),如果氨基酸有超过1个密码子,它将打印在新的一行中。

EN

回答 3

Stack Overflow用户

发布于 2013-03-17 04:03:55

考虑到您应该使用循环来实现这一点:这可以使用五个嵌套循环进行编程。在每一个循环中,你都会经历一个氨基酸符号的所有可能的翻译密码子三联体。这就是基本的想法。

下面的伪代码可以作为一个开始:

代码语言:javascript
复制
for each translating codon triplet codon1 for aminoAcid1:
    for each translating codon triplet codon2 for aminoAcid2:
        for each translating codon triplet codon3 for aminoAcid3:
            for each translating codon triplet codon4 for aminoAcid4:
                for each translating codon triplet codon5 for aminoAcid5:
                    print codon1 + codon2 + codon3 + codon4 + codon5
                end for
            end for
        end for
    end for
end for

您现在要做的就是使用原始数组在C++中编写这些循环。你事先知道,对于每个氨基酸符号,哪些(以及多少个)密码子三联体是我们在循环中必须经过的候选。将它们存储为常量数组,并使用函数参数中提供的氨基酸在循环中访问此数组。

因为您不应该使用字符串和容器,所以您必须使用C字符串(字符数组)和类似的原始数组来在C++中对上面的表进行编码。伪代码(codon1 ... codon5)中的变量应该只是const char* (C字符串),并且可以使用coutprintf打印。

上面的表格可以写成如下所示的数组。请注意,我将表中的每一行都写为一个C字符串,它以编码氨基酸符号的字母开头,然后是一个三元组的“列表”。所有这些三元组都以0结尾(这使得可以将它们指向C字符串)。要遍历三元组,您只需找到空的终止字符并将该指针递增1即可。如果这个指针不为空,则会出现另一个三元组。如果它是null (请注意,在这些行的末尾,将添加另一个null,因为它被添加到每个字符串文字中),这是最后一个三元组。

代码语言:javascript
复制
const char *codons[] = {
    "AGCT\0GCC\0GCA\0GCG\0",
    "RCGT\0CGC\0CGA\0CGG\0AGA\0AGG\0",
    // ...
    "*TAA\0TGA\0TAG\0"
};

使用从该表中找到正确行的实用函数,然后可以将循环写成(这里是第一个acid符号):

代码语言:javascript
复制
for(const char *codon1 = codonRow(aminoAcid1); codon1 += strlen(codon1); codon1 != NULL) {
    ...
}

在此循环中,初始化使用了实用函数(见下文),该函数返回表中的行,但不包括第一个字符(因此它指向给定酸的第一个密码子三元组)。增量操作只是将该指针增加C字符串长度(这将导致codon1指向紧跟在下一个空终止字符之后)。如果这是null,我们就完成了。

有趣的是,在这个循环的每次迭代中,codon1指向一个C字符串(好吧,它正好指向上面数组的字符串文字的中间),并将被适当地终止。所以打印codon1将只打印3个字符。

这是在上面的循环中使用的实用函数,它在表中搜索表中的特定字符并返回此行:

代码语言:javascript
复制
const char *codonRow(char aminoAcid)
{
    for(int i = 0; i < sizeof(codons)/sizeof(*codons); ++i) {
        const char *row = codons[i];   // Fetch the row from the array
        if (row[0] == aminoAcid)       // Compare the amino acid symbol
            return row + 1;            // Remove the amino acid symbol
    }
    // error:
    std::cerr << "No such amino acid: " << aminoAcid << std::endl;
    return 0;
}
票数 1
EN

Stack Overflow用户

发布于 2013-03-17 04:04:04

好吧,我将忽略你被告知有多少密码子的确切信息,并描述一个更一般的解决方案。

您知道每个密码子转换为3个字符,因此您可以预先计算所需缓冲区的大小。在您的例子中,当然可以使用固定大小的缓冲区。记住要为终止NUL字符留出空格。该输出缓冲区将是一个数组。它看起来像这样:

代码语言:javascript
复制
void printEncodingCodonSequences(
        char aminoAcid1,
        char aminoAcid2,
        char aminoAcid3, 
        char aminoAcid4,
        char aminoAcid5         )
{
     char outputBuffer[16]; // 5 codons, exactly
     char codons[] = { aminoAcid1, aminoAcid2, aminoAcid3, aminoAcid4, aminoAcid5 };
     findCodonEncodingCombinations(outputBuffer, outputBuffer, codons, 5);
}

接下来,您需要将每个密码子映射到所有可能的序列,并对给定的密码子数量重复此操作。因为这是一个组合问题,所以它非常适合递归。该函数接受第一个密码子,并遍历不同可能的编码。在每次迭代中,它会再次调用自身来处理剩余的密码子。

代码语言:javascript
复制
int findCodonEncodingCombinations( char* outputBuffer, char* outputPos, char* codons, int remaining )
{
    if (remaining == 0) {
        *outputPos = 0;
        puts(outputBuffer);
        puts("\n");
        return 1;
    }

    int combinations = 0;

    switch (*codon) {
        case 'D': // GAT, GAC
        case 'd':
            outputPos[0] = 'G';
            outputPos[1] = 'A';
            outputPos[2] = 'T';
            combinations += findCodonEncodingCombinations(outputBuffer, outputPos + 3, codons + 1, remaining - 1);
            outputPos[2] = 'C';
            combinations += findCodonEncodingCombinations(outputBuffer, outputPos + 3, codons + 1, remaining - 1);
            break;
    }

    return combinations;
}

实际上,循环对这个问题并没有特别的帮助。但是,您可以使用一个命令来验证所有输入是否有效,例如:

代码语言:javascript
复制
void printEncodingCodonSequences(
        char aminoAcid1,
        char aminoAcid2,
        char aminoAcid3, 
        char aminoAcid4,
        char aminoAcid5         )
{
     char outputBuffer[16]; // 5 codons, exactly
     char codons[] = { aminoAcid1, aminoAcid2, aminoAcid3, aminoAcid4, aminoAcid5 };
     if (!validateCodons(codons, 5)) return;
     findCodonEncodingCombinations(outputBuffer, outputBuffer, codons, 5);
}

bool validateCodons( char* codons, int count )
{
    while (count--) {  // it's a loop :)
        switch (*codons++) {
            case 'd':
            case 'D':
            //...
                break;

            default: // unrecognized codon
                puts("?\n");
                return false;
        }
    }

    return true;
}

显然,您需要填写许多其他密码子映射。

票数 0
EN

Stack Overflow用户

发布于 2013-03-17 04:13:25

你想把氨基酸序列翻译成密码子序列。因此,您需要的第一件事是一个将氨基酸代码转换为密码子的表。因为不允许使用类,所以表就是数组。由于每个氨基酸可能会翻译成一个以上的密码子,因此您需要一个数组:

代码语言:javascript
复制
#define MAX_CODONS  6   /* maximum number of codons for one amino acid */
char *AminoAcidCodons[26][MAX_CODONS+1] = {
    /* A */ { "GCT", "GCC", "GCA", "GCT", 0 },
    /* B */ { 0 },
    /* C */ { "TGT", "TGC", 0 },
          :
    /* Y */ { "TAT", "TAC", 0 },
    /* Z */ { 0 },
};

现在,您可以使用循环将大写字母转换为密码子集:

代码语言:javascript
复制
for (i = 0; AminoAcidCodons[aminoAcid1 - 'A'][i]; i++) {
    /* AminoAcidCodons[aminoAcid1-'A'][i] is one of the codons that AminoAcid1 can be encoded as */
     :

要获得5种氨基酸的所有可能组合,您需要5个嵌套循环。要处理小写字母,您需要将它们转换为大写字母。您还需要处理无效代码(非字母和没有对应密码子的字母)。isalphatoupper函数可以在这里提供帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15452925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档