C++ 使用数组和for循环,但不使用字符串或任何类
给定一个包含5个氨基酸符号的蛋白质片段作为输入,打印(在屏幕上)所有 翻译成该蛋白质片段的不同密码子序列(每行一个序列)。输入可以是 在任何情况下,如果任何输入无效,函数应在单行中打印“?” 这里有一个例子: 蛋白质片段MWQWH可由这四个密码子序列翻译,因此对于输入:“M”、“W”、“Q”、“W”、“H”(或“M”、“W”、“Q”、“W”、“H”),函数应打印以下内容:C++ 使用数组和for循环,但不使用字符串或任何类,c++,arrays,if-statement,for-loop,C++,Arrays,If Statement,For Loop,给定一个包含5个氨基酸符号的蛋白质片段作为输入,打印(在屏幕上)所有 翻译成该蛋白质片段的不同密码子序列(每行一个序列)。输入可以是 在任何情况下,如果任何输入无效,函数应在单行中打印“?” 这里有一个例子: 蛋白质片段MWQWH可由这四个密码子序列翻译,因此对于输入:“M”、“W”、“Q”、“W”、“H”(或“M”、“W”、“Q”、“W”、“H”),函数应打印以下内容: void printEncodingCodonSequences ( char aminoAcid1
void printEncodingCodonSequences (
char aminoAcid1,
char aminoAcid2,
char aminoAcid3,
char aminoAcid4,
char aminoAcid5
);
我不希望你回答所有的问题,只是一个如何做的提示。对于此任务,不允许使用字符串或任何容器类!有人告诉我必须使用嵌套循环和数组
在这个项目中,蛋白质片段由5个氨基酸组成(输入作为它们的符号),如果氨基酸有超过1个密码子,它将打印在新行中。鉴于您应该使用循环来实现这一点:这可以使用五个嵌套的循环来编程。在每一个循环中,你都要为一个氨基酸符号遍历所有可能的翻译密码子三元组。这是基本的想法 以下伪代码可以作为起点:
ATGTGGCAATGGCAT
ATGTGGCAGTGGCAT
ATGTGGCAATGGCAC
ATGTGGCAGTGGCAC
<>你现在要做的是用原始数组在C++中写这些循环。对于每个氨基酸符号,我们必须在循环中预先知道哪些密码子三联体(以及有多少密码子三联体)是候选密码子三联体。将它们存储为常量数组,并使用函数参数中提供的氨基酸在循环中访问此数组
由于不应该使用字符串和容器,所以强制使用C字符串(char数组)和原始数组来从C++中对上面的表进行编码。伪代码(
codon1
…codon5
)中的变量应该是const char*
(C字符串),并且可以使用cout
或printf
打印
上面的表可以写成如下数组。请注意,我将表中的每一行写为一个C字符串,该字符串以编码氨基酸符号的字母开头,然后是一个三元组的“列表”。所有这些三元组都以0结尾(这使得可以将它们作为C字符串指向)。要遍历三元组,只需找到null终止字符并将该指针递增1。如果此指针为非空,则会出现另一个三元组。如果它是null(请注意,在这些行的末尾,当它添加到每个字符串文字时,将添加另一个null),这是最后一个三元组
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
使用从该表中找到正确行的实用程序函数,可以将循环写入(此处为第一个acid符号):
在这个循环中,初始化使用实用函数(见下文),该函数返回表中的行,但不包括第一个字符(因此它指向给定acid的第一个密码子三元组)。增量操作只是将该指针增加C字符串长度(这将导致codon1
指向下一个空终止字符之后)。如果这是空的,我们就完成了
好的是,在这个循环的每个迭代中,
codon1
只需打印3个字符
这是上面循环中使用的实用函数,它在表中搜索特定字符并返回此行:
for(const char *codon1 = codonRow(aminoAcid1); codon1 += strlen(codon1); codon1 != NULL) {
...
}
const char*codonRow(char氨基酸)
{
对于(int i=0;i 好的,我不想告诉你密码子的确切数量,我来描述一个更一般的解决方案
您知道每个密码子转换为正好3个字符,因此您可以预先计算所需缓冲区的大小。在您的情况下,您当然可以使用固定大小的缓冲区。请记住为终止的NUL字符留出空间。此输出缓冲区将是一个数组。如下所示:
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;
}
接下来,您需要将每个密码子映射到所有可能的序列,并对给定的任意多个密码子重复此操作。因为这是一个组合问题,它非常适合递归。函数获取第一个密码子,并迭代不同的可能编码。在每次迭代中,它再次调用自身来处理r编码密码子
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);
}
实际上,循环对解决此问题没有特别的帮助。但是,您可以使用循环来验证所有输入是否有效,如:
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;
}
显然,您需要填写许多其他密码子映射。好吧,您需要将氨基酸序列转换为密码子序列。因此,您首先需要一个表来将氨基酸代码转换为密码子。因为您不允许使用类,所以一个表意味着一个数组。因为每个氨基酸可以转换为多个密码子,您需要一个数组:
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;
}
现在,您可以使用循环将大写字母转换为密码子集:
#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 },
};
要获得5种氨基酸的所有可能组合,您需要5个嵌套循环。要处理小写字母,您需要将它们转换为大写字母。您还需要处理无效代码(非字母和没有相应密码子的字母)在这里,isalpha
和toupper
函数可以提供帮助。关于这个问题:很难给出答案的提示,因为大多数StackOverflow用户不知道蛋白质片段是如何工作的。你能补充一些信息吗?你写过代码吗
#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 },
};
for (i = 0; AminoAcidCodons[aminoAcid1 - 'A'][i]; i++) {
/* AminoAcidCodons[aminoAcid1-'A'][i] is one of the codons that AminoAcid1 can be encoded as */
: