C:将DNA序列压缩成二进制
您好,我正在努力解决如何获得一个函数来转换成二进制位的DNA代码,需要使它看起来像这样:ACGTT->XXXXXX 11 11100100从右到左 对于A=0,C=1,G=2,T=3。现在我想用字符来做,然后用>>2将它移出函数,但我不能理解函数本身。。。 我这样试过,结果它返回NULLC:将DNA序列压缩成二进制,c,bin,C,Bin,您好,我正在努力解决如何获得一个函数来转换成二进制位的DNA代码,需要使它看起来像这样:ACGTT->XXXXXX 11 11100100从右到左 对于A=0,C=1,G=2,T=3。现在我想用字符来做,然后用>>2将它移出函数,但我不能理解函数本身。。。 我这样试过,结果它返回NULL char CompressChar(char c){ char temp[8]="XXXXXXXX"; if (c=='A'){ temp[7] = '0'; temp[6] = '0'; } if (c=
char CompressChar(char c){
char temp[8]="XXXXXXXX";
if (c=='A'){
temp[7] = '0';
temp[6] = '0';
}
if (c=='C'){
temp[7]='1';
temp[6]='0';
}
if(c=='G'){
temp[7]='0';
temp[6]='1';
}
if(c=='T'){
temp[7]='1';
temp[6]='1';
}
return temp;
}我认为您希望每个字母(称为核苷酸iirc?)代表2个二进制数字 首先,
chartemp[8]=“XXXXXXXX”代码>没有意义,因为C中的字符串以null结尾,并且您没有为null结尾符分配空间,应该是[8+1]
。你需要16位,而不是8位
函数返回的char
不正确,需要返回整个数组。这必须通过一个参数来完成,因为不能在C中返回数组。不能返回指向本地数据的指针,所以最好将分配留给调用方。无论如何忽略该函数
此外,将其转换为“二进制字符串”也没有多大意义。最好将其转换为二进制数,然后根据需要将该数字转换为字符串
包括“向后顺序”在内的转换可以这样进行:
uint16_t dna_to_bin (const char* str)
{
uint16_t result = 0;
size_t i;
for(i=0; i<16; i+=2) // loop over bits in the resulting binary number
{
typedef enum // local enum just for readability
{
A = 0,
C = 1,
G = 2,
T = 3,
} dna_t;
dna_t type=0; // default is 0 if nothing to decode
if(*str != '\0') // keep decoding string until reaching the end
{
switch(*str)
{
case 'A': type = A; break;
case 'C': type = C; break;
case 'G': type = G; break;
case 'T': type = T; break;
}
str++;
}
result |= (uint16_t)type << i; // store data at correct position in the result
}
return result;
}
temp
是char
的数组。返回temp
将返回指向其第一个元素的指针(因为数组自然会衰减到该元素),即返回&temp[0]
。这不是一个有效的char
,编译器应该警告您(如果不是,则启用更多警告)。此外,解决方案是不要将返回类型更改为char*
,因为temp
的生命周期以函数结束。那么指针将立即失效。你需要考虑另一种方法来“返回”字符串。“ACGTT->xxxxxx 11 11100100从右到左,对于A=0 C=1 G=2 T=3”也许我很密集,但我不理解这种解释。每个字母对应2位吗?还有,为什么需要二进制字符串而不是二进制数?
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdbool.h>
uint16_t dna_to_bin (const char* str)
{
uint16_t result = 0;
size_t i;
for(i=0; i<16; i+=2)
{
typedef enum
{
A = 0,
C = 1,
G = 2,
T = 3,
} dna_t;
dna_t type=0;
if(*str != '\0')
{
switch(*str)
{
case 'A': type = A; break;
case 'C': type = C; break;
case 'G': type = G; break;
case 'T': type = T; break;
}
str++;
}
result |= (uint16_t)type << i;
}
return result;
}
void print_bin (uint16_t bin)
{
bool remove_zeroes = true;
for(size_t i=0; i<16; i++)
{
uint16_t mask = 1u << (16-1-i);
uint16_t bit = bin & mask;
if(bit == 0)
{
if(!remove_zeroes)
{
printf("0");
}
}
else
{
remove_zeroes = false;
printf("1");
}
}
}
int main (void)
{
const char STR_DNA[] = "ACGTT";
uint16_t bin = dna_to_bin(STR_DNA);
puts(STR_DNA);
printf("Hex: %.4"PRIX16 "\n", bin);
printf("Bin: ");
print_bin(bin);
return (0);
}
ACGTT
Hex: 03E4
Bin: 1111100100