Escriu un programa que demani una seqüència d'ADN i mostri el percentatge GC i la freqüència de cada base.
#include <stdio.h> /* Inclou la biblioteca estàndard d'entrada/sortida */
/* Necessària per a printf() i scanf() */
#include <string.h> /* Inclou la biblioteca per a funcions de cadenes */
/* Necessària per a strlen() */
#include <ctype.h> /* Inclou la biblioteca per a classificació de caràcters */
/* Necessària per a toupper() */
int main(){ /* Funció principal del programa, punt d'entrada d'execució */
char adn[501]; /* Array per emmagatzemar la seqüència d'ADN */
/* Mida 501: fins a 500 caràcters + '\0' */
/* Suficient per a una seqüència típica d'exercici */
printf("========================================\n");
printf(" ANALITZADOR DE SEQUENCIES D'ADN\n");
printf("========================================\n\n");
printf("Introdueix una sequencia d'ADN: "); /* Demana la seqüència a l'usuari */
scanf("%500s", adn); /* Llegeix fins a 500 caràcters */
/* %500s limita la lectura per evitar desbordaments de buffer */
/* scanf() amb %s llegeix fins a trobar un espai en blanc */
int longitud = strlen(adn); /* Calcula la longitud de la seqüència introduïda */
/* strlen() compta els caràcters fins a '\0' */
/* No inclou el caràcter nul en el recompte */
/* Arrays per comptar cada tipus de nucleòtid */
/* Utilitzem un array de 4 posicions: índex 0=A, 1=C, 2=G, 3=T */
int comptadors[4] = {0, 0, 0, 0}; /* Inicialitza tots els comptadors a 0 */
/* {0, 0, 0, 0} assigna 0 a cada posició */
int altres = 0; /* Comptador per a caràcters no vàlids (N, R, Y, etc.) */
int total_valides = 0; /* Comptador de bases vàlides (A, C, G, T) */
/* Bucle per recórrer la seqüència i comptar cada nucleòtid */
for(int i = 0; i < longitud; i++){ /* Itera des de l'índex 0 fins a longitud-1 */
char base = toupper(adn[i]); /* Converteix el caràcter a majúscula */
/* toupper() retorna la versió majúscula */
/* Si ja és majúscula, la retorna igual */
/* Això permet acceptar tant minúscules com majúscules */
/* Classifica la base i incrementa el comptador corresponent */
switch(base){ /* Avalua el caràcter actual */
case 'A': /* Si és Adenina */
comptadors[0]++; /* Incrementa el comptador d'A (índex 0) */
total_valides++; /* Incrementa el total de bases vàlides */
break; /* Surt de l'estructura switch */
case 'C': /* Si és Citosina */
comptadors[1]++; /* Incrementa el comptador de C (índex 1) */
total_valides++;
break;
case 'G': /* Si és Guanina */
comptadors[2]++; /* Incrementa el comptador de G (índex 2) */
total_valides++;
break;
case 'T': /* Si és Timina */
comptadors[3]++; /* Incrementa el comptador de T (índex 3) */
total_valides++;
break;
default: /* Si no és cap base estàndard (N, R, Y, S, W, etc.) */
altres++; /* Incrementa el comptador d'altres caràcters */
break;
}
}
/* Mostra els resultats de l'anàlisi */
printf("\n=== RESULTATS DE L'ANALISI ===\n");
printf("Sequencia: %s\n", adn); /* Mostra la seqüència original */
printf("Longitud total: %d caracters\n", longitud); /* Longitud total */
/* Taula de freqüències absolutes i relatives */
printf("\n--- FREQUENCIA DE NUCLEOTIDS ---\n");
char bases[] = {'A', 'C', 'G', 'T'}; /* Array amb les lletres de les bases */
for(int i = 0; i < 4; i++){ /* Per a cada base (A, C, G, T) */
float frequencia = 0.0; /* Variable per al percentatge, inicialitzada a 0 */
if(total_valides > 0) /* Evita la divisió per zero si no hi ha bases vàlides */
frequencia = (float)comptadors[i] / total_valides * 100;
/* Converteix a float per obtenir decimals */
/* Divideix pel total de bases vàlides i multiplica per 100 */
printf(" %c: %3d (%6.2f%%)", bases[i], comptadors[i], frequencia);
/* Mostra: base, recompte absolut, percentatge amb 2 decimals */
/* Afegeix una barra visual de freqüència */
int barres = (int)(frequencia / 2); /* Cada 2% = una barra */
for(int j = 0; j < barres; j++)
printf("|"); /* Imprimeix una barra per cada 2% */
printf("\n");
}
/* Càlcul del percentatge GC */
int gc = comptadors[1] + comptadors[2]; /* Suma de C (índex 1) i G (índex 2) */
float pct_gc = 0.0; /* Percentatge GC */
if(total_valides > 0)
pct_gc = (float)gc / total_valides * 100;
printf("\n--- CONTINGUT GC ---\n");
printf(" G + C: %d de %d bases valides\n", gc, total_valides);
printf(" Percentatge GC: %.2f%%\n", pct_gc);
/* Classificació del contingut GC */
if(pct_gc > 60)
printf(" Classificacio: ALT (ric en GC, possible genoma termofil)\n");
else if(pct_gc > 40)
printf(" Classificacio: MITJA (contingut GC tipic)\n");
else
printf(" Classificacio: BAIX (pobre en GC, possible genoma d'organisme mesofil)\n");
/* Informació sobre caràcters no vàlids */
if(altres > 0){
printf("\n--- AVIS ---\n");
printf(" S'han trobat %d caracters no estandard (no A,C,G,T).\n", altres);
printf(" Aquests caracters s'han ignorat en els calculs de frequencia.\n");
}
/* Càlcul de la relació AT/GC */
if(gc > 0){
int at = comptadors[0] + comptadors[3]; /* Suma de A i T */
float ratio_at_gc = (float)at / gc; /* Relació AT/GC */
printf("\n--- RELACIO AT/GC ---\n");
printf(" AT/GC = %.2f\n", ratio_at_gc);
if(ratio_at_gc > 1.5)
printf(" La sequencia es rica en A i T.\n");
else if(ratio_at_gc < 0.67)
printf(" La sequencia es rica en G i C.\n");
else
printf(" La sequencia te una proporcio equilibrada.\n");
}
return 0; /* Finalitza el programa amb èxit */
}
Identifica tots els codons ATG en una seqüència i mostra les posicions on apareixen.
#include <stdio.h> /* Inclou la biblioteca estàndard d'entrada/sortida */
/* Necessària per a printf() i scanf() */
#include <string.h> /* Inclou la biblioteca per a funcions de cadenes */
/* Necessària per a strlen() */
#include <ctype.h> /* Inclou la biblioteca per a classificació de caràcters */
/* Necessària per a toupper() */
int main(){ /* Funció principal del programa */
char adn[1001]; /* Array per emmagatzemar la seqüència d'ADN */
/* Mida 1001: fins a 1000 caràcters + '\0' */
int posicions[500]; /* Array per emmagatzemar les posicions on apareix ATG */
/* Com a màxim 500 posicions (si tota la seqüència fos ATGATG...) */
int total_atg = 0; /* Comptador de codons ATG trobats */
/* S'inicialitza a 0 per començar el recompte */
printf("========================================\n");
printf(" CERCADOR DE CODONS ATG (START CODONS)\n");
printf("========================================\n\n");
printf("Introdueix una sequencia d'ADN: "); /* Demana la seqüència */
scanf("%1000s", adn); /* Llegeix fins a 1000 caràcters */
int longitud = strlen(adn); /* Calcula la longitud de la seqüència */
/* Converteix tota la seqüència a majúscules per a comparació uniforme */
for(int i = 0; i < longitud; i++){
adn[i] = toupper(adn[i]); /* Converteix cada caràcter a majúscula */
}
printf("\nSequencia (majuscules): %s\n", adn); /* Mostra la seqüència en majúscules */
printf("Longitud: %d nucleotids\n\n", longitud);
/* Cerca de codons ATG en tots els marcs de lectura possibles */
/* Un codó són 3 nucleòtids consecutius */
/* Busquem en les 3 fases (marcs de lectura 0, 1, 2) */
printf("=== CERCA DE CODONS ATG EN TOTS ELS MARCS ===\n\n");
for(int marc = 0; marc < 3; marc++){ /* Per a cada marc de lectura (0, 1, 2) */
printf("--- Marc de lectura %d (comencant a posicio %d) ---\n", marc + 1, marc);
/* marc+1 per mostrar 1, 2, 3 en lloc de 0, 1, 2 */
total_atg = 0; /* Reinicia el comptador per a cada marc */
/* Recorre la seqüència en passos de 3 (cada codó) */
/* Comença a la posició 'marc' i avança de 3 en 3 */
for(int i = marc; i + 2 < longitud; i += 3){ /* i+2 < longitud: necessitem 3 nucleòtids */
/* i += 3: saltem de codó en codó */
/* Comprova si els 3 nucleòtids consecutius formen ATG */
if(adn[i] == 'A' && adn[i+1] == 'T' && adn[i+2] == 'G'){
/* && és l'operador lògic AND: TOTES les condicions han de ser certes */
/* Compara el primer nucleòtid amb 'A', el segon amb 'T' i el tercer amb 'G' */
/* Emmagatzema la posició (basada en 1 per a l'usuari) */
posicions[total_atg] = i + 1; /* +1 per mostrar posicions 1-based */
total_atg++; /* Incrementa el comptador de ATG trobats */
printf(" ATG trobat a la posicio %d (nucleotids %d-%d)\n",
i + 1, i + 1, i + 3);
/* Mostra la posició i el rang de nucleòtids */
/* Mostra el context: 6 nucleòtids abans i 6 després */
printf(" Context: ...");
for(int j = i - 6; j < i; j++) /* 6 nucleòtids abans */
if(j >= 0) printf("%c", adn[j]); /* Si està dins de la seqüència */
else printf(" "); /* Espais per alinear si està fora */
printf("[ATG]"); /* El codó ATG trobat */
for(int j = i + 3; j < i + 9 && j < longitud; j++) /* 6 nucleòtids després */
printf("%c", adn[j]);
printf("...\n");
}
}
/* Mostra el resum per a aquest marc de lectura */
printf(" Total ATG en marc %d: %d\n", marc + 1, total_atg);
if(total_atg == 0)
printf(" No s'ha trobat cap codó ATG en aquest marc.\n");
printf("\n");
}
/* Cerca addicional: TOTS els ATG independentment del marc */
printf("=== TOTS ELS ATG (INDEPENDENTMENT DEL MARC) ===\n");
total_atg = 0; /* Reinicia el comptador */
for(int i = 0; i + 2 < longitud; i++){ /* Recorre cada posició (no només cada 3) */
if(adn[i] == 'A' && adn[i+1] == 'T' && adn[i+2] == 'G'){
posicions[total_atg] = i + 1; /* Guarda la posició */
total_atg++;
}
}
printf("Total d'aparicions d'ATG: %d\n", total_atg);
if(total_atg > 0){
printf("Posicions: ");
for(int i = 0; i < total_atg; i++){
printf("%d", posicions[i]); /* Mostra cada posició */
if(i < total_atg - 1) printf(", "); /* Separador entre posicions */
}
printf("\n");
/* Calcula la distància entre ATG consecutius */
if(total_atg > 1){
printf("Distancies entre ATG consecutius: ");
for(int i = 0; i < total_atg - 1; i++){
printf("%d", posicions[i+1] - posicions[i]); /* Diferència de posicions */
if(i < total_atg - 2) printf(", ");
}
printf(" nucleotids\n");
}
}
/* Informació sobre la importància biològica de ATG */
printf("\n=== INFORMACIO BIOLOGICA ===\n");
printf("ATG es el codo d'inici (start codon) en la majoria d'organismes.\n");
printf("Codifica per l'aminoacid Metionina (Met, M).\n");
printf("En procariotes, ATG codifica per N-formilmetionina (fMet).\n");
printf("Altres codons d'inici menys comuns: GTG (Val), TTG (Leu) en alguns bacteris.\n");
return 0; /* Finalitza el programa amb èxit */
}
Amplia la taula de traducció per incloure almenys 10 aminoàcids diferents.
#include <stdio.h> /* Inclou la biblioteca estàndard d'entrada/sortida */
/* Necessària per a printf() i scanf() */
#include <string.h> /* Inclou la biblioteca per a funcions de cadenes */
/* Necessària per a strlen() i strncpy() */
#include <ctype.h> /* Inclou la biblioteca per a classificació de caràcters */
/* Necessària per a toupper() */
/* Definició de l'estructura per a un codó i el seu aminoàcid */
/* Una estructura agrupa el codó (3 nucleòtids) amb el seu significat */
struct Codo {
char triplet[4]; /* El codó: 3 nucleòtids + '\0' (ex: "ATG") */
/* Mida 4 per emmagatzemar 3 caràcters + '\0' */
char aminoacid; /* La lletra de l'aminoàcid (codi d'una lletra) */
/* Ex: 'M' per Metionina, 'A' per Alanina */
char nom[30]; /* Nom complet de l'aminoàcid */
/* Ex: "Metionina", "Alanina" */
int hidrofobic; /* Propietat: 1 = hidrofòbic, 0 = hidrofílic */
float pes_molecular; /* Pes molecular en Daltons (Da) */
};
/* Funció per inicialitzar la taula de traducció */
/* Omple un array d'estructures Codo amb la informació genètica */
/* Retorna el nombre d'entrades a la taula */
int inicialitzar_taula(struct Codo taula[]){ /* Rep un array d'estructures */
/* Retorna el nombre d'elements omplerts */
int i = 0; /* Índex per omplir la taula */
/* Cada entrada: triplet, aminoàcid, nom, hidrofòbic?, pes molecular */
/* Metionina (ATG és el codó d'inici) */
strcpy(taula[i].triplet, "ATG"); /* Copia el triplet a l'estructura */
taula[i].aminoacid = 'M'; /* Assigna la lletra de l'aminoàcid */
strcpy(taula[i].nom, "Metionina");/* Copia el nom complet */
taula[i].hidrofobic = 1; /* 1 = és hidrofòbic */
taula[i].pes_molecular = 149.2; /* Pes molecular en Da */
i++; /* Avança a la següent posició de la taula */
/* Alanina (4 codons: GCA, GCC, GCG, GCT) */
strcpy(taula[i].triplet, "GCA");
taula[i].aminoacid = 'A';
strcpy(taula[i].nom, "Alanina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 89.1;
i++;
strcpy(taula[i].triplet, "GCC");
taula[i].aminoacid = 'A';
strcpy(taula[i].nom, "Alanina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 89.1;
i++;
strcpy(taula[i].triplet, "GCG");
taula[i].aminoacid = 'A';
strcpy(taula[i].nom, "Alanina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 89.1;
i++;
strcpy(taula[i].triplet, "GCT");
taula[i].aminoacid = 'A';
strcpy(taula[i].nom, "Alanina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 89.1;
i++;
/* Glicina (4 codons: GGA, GGC, GGG, GGT) */
strcpy(taula[i].triplet, "GGA");
taula[i].aminoacid = 'G';
strcpy(taula[i].nom, "Glicina");
taula[i].hidrofobic = 0; /* No és hidrofòbica */
taula[i].pes_molecular = 75.1;
i++;
strcpy(taula[i].triplet, "GGC");
taula[i].aminoacid = 'G';
strcpy(taula[i].nom, "Glicina");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 75.1;
i++;
strcpy(taula[i].triplet, "GGG");
taula[i].aminoacid = 'G';
strcpy(taula[i].nom, "Glicina");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 75.1;
i++;
strcpy(taula[i].triplet, "GGT");
taula[i].aminoacid = 'G';
strcpy(taula[i].nom, "Glicina");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 75.1;
i++;
/* Leucina (6 codons: TTA, TTG, CTA, CTC, CTG, CTT) */
strcpy(taula[i].triplet, "TTA");
taula[i].aminoacid = 'L';
strcpy(taula[i].nom, "Leucina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 131.2;
i++;
strcpy(taula[i].triplet, "TTG");
taula[i].aminoacid = 'L';
strcpy(taula[i].nom, "Leucina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 131.2;
i++;
strcpy(taula[i].triplet, "CTA");
taula[i].aminoacid = 'L';
strcpy(taula[i].nom, "Leucina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 131.2;
i++;
strcpy(taula[i].triplet, "CTC");
taula[i].aminoacid = 'L';
strcpy(taula[i].nom, "Leucina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 131.2;
i++;
strcpy(taula[i].triplet, "CTG");
taula[i].aminoacid = 'L';
strcpy(taula[i].nom, "Leucina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 131.2;
i++;
strcpy(taula[i].triplet, "CTT");
taula[i].aminoacid = 'L';
strcpy(taula[i].nom, "Leucina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 131.2;
i++;
/* Valina (4 codons: GTA, GTC, GTG, GTT) */
strcpy(taula[i].triplet, "GTA");
taula[i].aminoacid = 'V';
strcpy(taula[i].nom, "Valina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 117.1;
i++;
strcpy(taula[i].triplet, "GTC");
taula[i].aminoacid = 'V';
strcpy(taula[i].nom, "Valina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 117.1;
i++;
strcpy(taula[i].triplet, "GTG");
taula[i].aminoacid = 'V';
strcpy(taula[i].nom, "Valina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 117.1;
i++;
strcpy(taula[i].triplet, "GTT");
taula[i].aminoacid = 'V';
strcpy(taula[i].nom, "Valina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 117.1;
i++;
/* Serina (4 codons: TCA, TCC, TCG, TCT - només alguns) */
strcpy(taula[i].triplet, "TCA");
taula[i].aminoacid = 'S';
strcpy(taula[i].nom, "Serina");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 105.1;
i++;
strcpy(taula[i].triplet, "TCC");
taula[i].aminoacid = 'S';
strcpy(taula[i].nom, "Serina");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 105.1;
i++;
/* Lisina (2 codons: AAA, AAG) */
strcpy(taula[i].triplet, "AAA");
taula[i].aminoacid = 'K';
strcpy(taula[i].nom, "Lisina");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 146.2;
i++;
strcpy(taula[i].triplet, "AAG");
taula[i].aminoacid = 'K';
strcpy(taula[i].nom, "Lisina");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 146.2;
i++;
/* Arginina (2 codons: AGA, AGG - dels 6 possibles) */
strcpy(taula[i].triplet, "AGA");
taula[i].aminoacid = 'R';
strcpy(taula[i].nom, "Arginina");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 174.2;
i++;
strcpy(taula[i].triplet, "AGG");
taula[i].aminoacid = 'R';
strcpy(taula[i].nom, "Arginina");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 174.2;
i++;
/* Prolina (4 codons: CCA, CCC, CCG, CCT) */
strcpy(taula[i].triplet, "CCA");
taula[i].aminoacid = 'P';
strcpy(taula[i].nom, "Prolina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 115.1;
i++;
strcpy(taula[i].triplet, "CCC");
taula[i].aminoacid = 'P';
strcpy(taula[i].nom, "Prolina");
taula[i].hidrofobic = 1;
taula[i].pes_molecular = 115.1;
i++;
/* Codons de parada (STOP codons) */
strcpy(taula[i].triplet, "TAA");
taula[i].aminoacid = '*'; /* Asterisc: símbol estàndard per a STOP */
strcpy(taula[i].nom, "STOP (Ocre)");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 0.0;
i++;
strcpy(taula[i].triplet, "TAG");
taula[i].aminoacid = '*';
strcpy(taula[i].nom, "STOP (Ambre)");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 0.0;
i++;
strcpy(taula[i].triplet, "TGA");
taula[i].aminoacid = '*';
strcpy(taula[i].nom, "STOP (Opal)");
taula[i].hidrofobic = 0;
taula[i].pes_molecular = 0.0;
i++;
return i; /* Retorna el nombre total d'entrades a la taula */
}
/* Funció per buscar un codó a la taula de traducció */
/* Retorna l'aminoàcid corresponent, o '?' si no el troba */
char traduir_codo(const char triplet[], struct Codo taula[], int mida_taula){
/* Paràmetres:
- triplet: cadena de 3 caràcters amb el codó
- taula: array d'estructures Codo amb la taula genètica
- mida_taula: nombre d'entrades a la taula */
for(int i = 0; i < mida_taula; i++){ /* Cerca lineal a la taula */
if(strcmp(triplet, taula[i].triplet) == 0) /* Compara el triplet */
return taula[i].aminoacid; /* Si el troba, retorna l'aminoàcid */
}
return '?'; /* Si no el troba, retorna '?' (desconegut) */
}
/* Funció per mostrar la taula de traducció */
void mostrar_taula(struct Codo taula[], int mida){
printf("\n=== TAULA DE TRADUCCIO GENETICA ===\n");
printf("Total de codons definits: %d\n\n", mida);
printf("%-6s %-5s %-20s %-10s %-10s\n", "CODO", "AA", "NOM", "HIDROFOBIC", "PES (Da)");
printf("--------------------------------------------------------------\n");
for(int i = 0; i < mida; i++){
printf("%-6s %-5c %-20s %-10s %10.1f\n",
taula[i].triplet, /* El codó */
taula[i].aminoacid, /* La lletra de l'aminoàcid */
taula[i].nom, /* El nom complet */
taula[i].hidrofobic ? "Si" : "No", /* Si és hidrofòbic */
taula[i].pes_molecular); /* El pes molecular */
}
}
int main(){ /* Funció principal */
struct Codo taula[50]; /* Array per a la taula de traducció */
/* 50 entrades és suficient per a l'exercici */
/* El codi genètic complet té 64 codons */
/* Inicialitza la taula de traducció */
int mida_taula = inicialitzar_taula(taula);
printf("Taula de traduccio inicialitzada amb %d entrades.\n", mida_taula);
/* Mostra la taula completa */
mostrar_taula(taula, mida_taula);
/* Demostració de traducció */
printf("\n=== DEMOSTRACIO DE TRADUCCIO ===\n");
char sequencia[200];
printf("Introdueix una sequencia d'ADN per traduir: ");
scanf("%199s", sequencia);
int longitud = strlen(sequencia);
printf("\nSequencia: %s\n", sequencia);
printf("Traduccio: ");
/* Tradueix la seqüència codó a codó */
for(int i = 0; i + 2 < longitud; i += 3){ /* Avança de 3 en 3 */
char codo[4]; /* Buffer per al codó actual */
strncpy(codo, sequencia + i, 3); /* Copia 3 caràcters */
codo[3] = '\0'; /* Afegeix el caràcter nul */
char aa = traduir_codo(codo, taula, mida_taula); /* Tradueix */
printf("%c", aa); /* Mostra l'aminoàcid */
if(aa == '*') break; /* Si és STOP, acaba la traducció */
}
printf("\n");
/* Estadístiques d'aminoàcids de la taula */
printf("\n=== ESTADISTIQUES DE LA TAULA ===\n");
int hidrofobics = 0, hidrofilics = 0;
for(int i = 0; i < mida_taula; i++){
if(taula[i].aminoacid != '*'){ /* No comptar STOP */
if(taula[i].hidrofobic)
hidrofobics++;
else
hidrofilics++;
}
}
printf("Codons hidrofobics: %d\n", hidrofobics);
printf("Codons hidrofilics: %d\n", hidrofilics);
return 0; /* Finalitza el programa amb èxit */
}
Escriu un programa complet que llegeixi una seqüència d'ADN, calculi estadístiques, identifiqui ORFs en els tres marcs de lectura i generi un informe.
#include <stdio.h> /* Inclou la biblioteca estàndard d'entrada/sortida */
/* Necessària per a printf(), scanf(), fopen(), fprintf(), fgets(), fclose() */
#include <stdlib.h> /* Inclou la biblioteca estàndard */
/* Necessària per a malloc(), realloc(), free(), qsort() */
#include <string.h> /* Inclou la biblioteca per a funcions de cadenes */
/* Necessària per a strlen(), strcpy(), strncpy(), strcat(), strcmp() */
#include <ctype.h> /* Inclou la biblioteca per a classificació de caràcters */
/* Necessària per a toupper() */
/* Constants del programa */
#define MAX_SEQ 10000 /* Longitud màxima de la seqüència */
#define MAX_ORF 500 /* Nombre màxim d'ORFs a detectar */
#define MAX_LINIA 1000 /* Longitud màxima d'una línia del fitxer */
/* Estructura per emmagatzemar un ORF (Open Reading Frame) */
typedef struct {
int marc; /* Marc de lectura (0, 1 o 2) */
int inici; /* Posició d'inici (1-based) */
int final; /* Posició final (1-based) */
int longitud_adn; /* Longitud en nucleòtids */
int longitud_aa; /* Longitud en aminoàcids */
char *sequencia_aa; /* Seqüència d'aminoàcids (memòria dinàmica) */
float pes_molecular; /* Pes molecular aproximat */
} ORF; /* 'ORF' és ara un tipus vàlid gràcies a typedef */
/* Variables globals */
char sequencia[MAX_SEQ]; /* Seqüència d'ADN carregada */
int longitud_seq = 0; /* Longitud real de la seqüència */
ORF orfs[MAX_ORF]; /* Array d'ORFs trobats */
int total_orfs = 0; /* Nombre total d'ORFs trobats */
/* Prototips de les funcions */
int carregar_sequencia(const char *nom_fitxer); /* Carrega la seqüència d'un fitxer */
void analitzar_composicio(); /* Calcula %GC i freqüències */
void identificar_orfs(); /* Troba tots els ORFs */
void mostrar_orfs(); /* Mostra els ORFs per pantalla */
void guardar_informe(const char *nom_fitxer); /* Guarda l'informe en un fitxer */
void alliberar_orfs(); /* Allibera la memòria dels ORFs */
/* Funcions auxiliars per a la traducció */
char traduir_codo(const char *codo); /* Tradueix un codó a aminoàcid */
int es_codo_inici(const char *codo); /* Comprova si és ATG (START) */
int es_codo_stop(const char *codo); /* Comprova si és TAA, TAG o TGA */
/* Funció de comparació per ordenar ORFs per longitud (qsort) */
int comparar_orfs_per_longitud(const void *a, const void *b);
int main(){ /* Funció principal */
char nom_fitxer[200]; /* Nom del fitxer d'entrada */
int opcio; /* Opció del menú */
printf("========================================\n");
printf(" ANALITZADOR DE SEQUENCIES D'ADN\n");
printf("========================================\n\n");
/* Demana el fitxer amb la seqüència */
printf("Nom del fitxer amb la sequencia d'ADN: ");
scanf("%199s", nom_fitxer);
/* Carrega la seqüència */
if(carregar_sequencia(nom_fitxer) == 0){
printf("Error en carregar la sequencia. Finalitzant.\n");
return 1;
}
printf("Sequencia carregada: %d nucleotids.\n", longitud_seq);
/* Menú d'opcions */
do{
printf("\n--- MENU D'ANALISI ---\n");
printf(" 1. Mostrar composicio nucleotidica\n");
printf(" 2. Identificar ORFs en tots els marcs\n");
printf(" 3. Mostrar ORFs trobats\n");
printf(" 4. Guardar informe complet\n");
printf(" 0. Sortir\n");
printf(" Opcio: ");
scanf("%d", &opcio);
getchar(); /* Consumeix el '\n' */
switch(opcio){
case 1:
analitzar_composicio();
break;
case 2:
identificar_orfs();
printf("S'han identificat %d ORFs.\n", total_orfs);
break;
case 3:
mostrar_orfs();
break;
case 4:
guardar_informe("informe_analisi.txt");
break;
case 0:
printf("\nAlliberant memoria...\n");
alliberar_orfs();
printf("Adeu!\n");
break;
default:
printf("Opcio no valida.\n");
}
} while(opcio != 0);
return 0; /* Finalitza el programa */
}
/* Funció per carregar la seqüència des d'un fitxer */
int carregar_sequencia(const char *nom_fitxer){
FILE *fitxer = fopen(nom_fitxer, "r"); /* Obre en mode lectura */
if(fitxer == NULL){
printf("Error: No s'ha pogut obrir el fitxer '%s'.\n", nom_fitxer);
printf("Creant fitxer d'exemple...\n");
/* Crea un fitxer d'exemple */
fitxer = fopen(nom_fitxer, "w");
if(fitxer == NULL) return 0;
fprintf(fitxer, "ATGGCCGCTTGATAG\n");
fprintf(fitxer, "CCGATGCTAGCTTAA\n");
fprintf(fitxer, "GGGCCCAAATTTTGA\n");
fclose(fitxer);
fitxer = fopen(nom_fitxer, "r");
if(fitxer == NULL) return 0;
printf("Fitxer d'exemple creat.\n");
}
char linia[MAX_LINIA];
sequencia[0] = '\0'; /* Inicialitza la seqüència com a buida */
/* Llegeix el fitxer línia per línia */
while(fgets(linia, MAX_LINIA, fitxer) != NULL){
/* Elimina el salt de línia */
int len = strlen(linia);
if(len > 0 && linia[len-1] == '\n')
linia[len-1] = '\0';
/* Ignora línies que comencen amb '>' (format FASTA) */
if(linia[0] == '>') continue;
/* Converteix a majúscules i afegeix a la seqüència */
for(int i = 0; linia[i] != '\0'; i++){
linia[i] = toupper(linia[i]);
}
strcat(sequencia, linia); /* Concatena la línia */
}
fclose(fitxer);
longitud_seq = strlen(sequencia); /* Calcula la longitud total */
/* Filtra només els caràcters vàlids (A, C, G, T) */
int j = 0; /* Índex d'escriptura */
for(int i = 0; i < longitud_seq; i++){
if(sequencia[i] == 'A' || sequencia[i] == 'C' ||
sequencia[i] == 'G' || sequencia[i] == 'T'){
sequencia[j] = sequencia[i]; /* Conserva només bases vàlides */
j++;
}
}
sequencia[j] = '\0'; /* Finalitza la cadena filtrada */
longitud_seq = j; /* Actualitza la longitud */
return longitud_seq; /* Retorna la longitud (0 si està buida) */
}
/* Funció per analitzar la composició nucleotídica */
void analitzar_composicio(){
if(longitud_seq == 0){
printf("No hi ha sequencia carregada.\n");
return;
}
int a = 0, c = 0, g = 0, t = 0; /* Comptadors per a cada base */
/* Compta cada nucleòtid */
for(int i = 0; i < longitud_seq; i++){
switch(sequencia[i]){
case 'A': a++; break;
case 'C': c++; break;
case 'G': g++; break;
case 'T': t++; break;
}
}
int total = a + c + g + t; /* Total de bases vàlides */
printf("\n=== COMPOSICIO NUCLEOTIDICA ===\n");
printf("Longitud de la sequencia: %d nucleotids\n\n", longitud_seq);
printf("%-10s %8s %10s\n", "BASE", "NOMBRE", "PERCENTATGE");
printf("--------------------------------\n");
if(total > 0){
printf("%-10s %8d %9.2f%%\n", "Adenina (A)", a, (float)a/total*100);
printf("%-10s %8d %9.2f%%\n", "Citosina (C)", c, (float)c/total*100);
printf("%-10s %8d %9.2f%%\n", "Guanina (G)", g, (float)g/total*100);
printf("%-10s %8d %9.2f%%\n", "Timina (T)", t, (float)t/total*100);
}
printf("--------------------------------\n");
printf("%-10s %8d\n", "TOTAL", total);
/* Contingut GC */
int gc = c + g;
float pct_gc = (total > 0) ? (float)gc/total*100 : 0;
printf("\nContingut GC: %.2f%%\n", pct_gc);
printf("Relacio AT/GC: %.2f\n", (total > 0 && gc > 0) ? (float)(a+t)/gc : 0);
}
/* Funció per identificar tots els ORFs en els 3 marcs de lectura */
void identificar_orfs(){
if(longitud_seq == 0){
printf("No hi ha sequencia carregada.\n");
return;
}
/* Allibera ORFs anteriors si n'hi ha */
alliberar_orfs();
total_orfs = 0;
/* Busca en cada marc de lectura (0, 1, 2) */
for(int marc = 0; marc < 3; marc++){
int posicio = marc; /* Comença a la posició del marc */
/* Recorre la seqüència en aquest marc */
while(posicio + 2 < longitud_seq){
char codo[4]; /* Buffer per al codó actual */
strncpy(codo, sequencia + posicio, 3);
codo[3] = '\0';
/* Si troba un codó d'inici (ATG) */
if(es_codo_inici(codo)){
int inici_orf = posicio; /* Guarda la posició d'inici */
int longitud_orf = 3; /* Comença amb 3 nucleòtids (ATG) */
/* Avança codó a codó fins trobar un STOP o final de seqüència */
posicio += 3;
int stop_trobat = 0;
while(posicio + 2 < longitud_seq){
strncpy(codo, sequencia + posicio, 3);
codo[3] = '\0';
if(es_codo_stop(codo)){ /* Si troba un codó de parada */
longitud_orf += 3; /* Afegeix el codó STOP */
stop_trobat = 1;
break; /* Surt del bucle interior */
}
longitud_orf += 3; /* Afegeix la longitud del codó */
posicio += 3; /* Avança al següent codó */
}
/* Si l'ORF és significatiu (mínim 30 nucleòtids = 10 aminoàcids) */
if(longitud_orf >= 30 && total_orfs < MAX_ORF){
ORF *orf = &orfs[total_orfs]; /* Punter a l'ORF actual */
orf->marc = marc;
orf->inici = inici_orf + 1; /* Posició 1-based */
orf->final = inici_orf + longitud_orf; /* Posició final */
orf->longitud_adn = longitud_orf;
orf->longitud_aa = (stop_trobat) ? (longitud_orf / 3) - 1 : longitud_orf / 3;
/* Si hi ha STOP, resta 1 (el codó STOP no es tradueix a aminoàcid) */
/* Si no hi ha STOP, tots els codons es tradueixen */
/* Reserva memòria per a la seqüència d'aminoàcids */
orf->sequencia_aa = (char*)malloc((orf->longitud_aa + 1) * sizeof(char));
orf->pes_molecular = 0.0;
/* Tradueix l'ORF a aminoàcids */
if(orf->sequencia_aa != NULL){
int aa_idx = 0; /* Índex per a la seqüència d'aminoàcids */
for(int i = 0; i < orf->longitud_adn - 3; i += 3){
/* No tradueix l'últim codó si és STOP */
char codo_trad[4];
strncpy(codo_trad, sequencia + inici_orf + i, 3);
codo_trad[3] = '\0';
char aa = traduir_codo(codo_trad);
orf->sequencia_aa[aa_idx] = aa;
/* Acumula el pes molecular */
orf->pes_molecular += pes_aminoacid(aa);
aa_idx++;
}
orf->sequencia_aa[aa_idx] = '\0'; /* Finalitza la cadena */
}
total_orfs++; /* Incrementa el comptador d'ORFs */
}
/* Si no s'ha trobat STOP, posicio ja està al final */
if(!stop_trobat) break; /* Surt del bucle exterior per a aquest marc */
} else {
posicio += 3; /* Avança al següent codó si no és ATG */
}
}
}
/* Ordena els ORFs per longitud (de més llarg a més curt) */
qsort(orfs, total_orfs, sizeof(ORF), comparar_orfs_per_longitud);
printf("Analisi completada: %d ORFs identificats.\n", total_orfs);
}
/* Funció per mostrar els ORFs trobats */
void mostrar_orfs(){
if(total_orfs == 0){
printf("No s'han identificat ORFs. Executa primer l'opcio 2.\n");
return;
}
printf("\n=== ORFs IDENTIFICATS (ordenats per longitud) ===\n\n");
printf("%-5s %-5s %-8s %-8s %-8s %-8s %-12s %s\n",
"NUM", "MARC", "INICI", "FINAL", "LONG_ADN", "LONG_AA", "PES_MOLEC", "SEQUENCIA AA");
printf("--------------------------------------------------------------------------------\n");
for(int i = 0; i < total_orfs; i++){
printf("%-5d %-5d %-8d %-8d %-8d %-8d %-10.1f %s\n",
i + 1,
orfs[i].marc + 1,
orfs[i].inici,
orfs[i].final,
orfs[i].longitud_adn,
orfs[i].longitud_aa,
orfs[i].pes_molecular,
orfs[i].sequencia_aa ? orfs[i].sequencia_aa : "N/A");
}
}
/* Funció per guardar l'informe complet en un fitxer */
void guardar_informe(const char *nom_fitxer){
FILE *fitxer = fopen(nom_fitxer, "w"); /* Obre en mode escriptura */
if(fitxer == NULL){
printf("Error: No s'ha pogut crear el fitxer '%s'.\n", nom_fitxer);
return;
}
/* Escriu la capçalera de l'informe */
fprintf(fitxer, "========================================\n");
fprintf(fitxer, " INFORME D'ANALISI DE SEQUENCIA D'ADN\n");
fprintf(fitxer, "========================================\n\n");
/* Informació general de la seqüència */
fprintf(fitxer, "--- DADES GENERALS ---\n");
fprintf(fitxer, "Longitud de la sequencia: %d nucleotids\n", longitud_seq);
fprintf(fitxer, "Sequencia (primers 100 nt): %.100s%s\n\n",
sequencia, longitud_seq > 100 ? "..." : "");
/* Composició nucleotídica */
int a = 0, c = 0, g = 0, t = 0;
for(int i = 0; i < longitud_seq; i++){
switch(sequencia[i]){
case 'A': a++; break;
case 'C': c++; break;
case 'G': g++; break;
case 'T': t++; break;
}
}
int total = a + c + g + t;
float pct_gc = (total > 0) ? (float)(c+g)/total*100 : 0;
fprintf(fitxer, "--- COMPOSICIO NUCLEOTIDICA ---\n");
fprintf(fitxer, "Adenina (A): %d (%.2f%%)\n", a, (float)a/total*100);
fprintf(fitxer, "Citosina (C): %d (%.2f%%)\n", c, (float)c/total*100);
fprintf(fitxer, "Guanina (G): %d (%.2f%%)\n", g, (float)g/total*100);
fprintf(fitxer, "Timina (T): %d (%.2f%%)\n", t, (float)t/total*100);
fprintf(fitxer, "Contingut GC: %.2f%%\n\n", pct_gc);
/* ORFs identificats */
fprintf(fitxer, "--- ORFs IDENTIFICATS ---\n");
fprintf(fitxer, "Nombre total d'ORFs: %d\n\n", total_orfs);
if(total_orfs > 0){
fprintf(fitxer, "%-6s %-6s %-8s %-8s %-8s %-8s %-12s %s\n",
"NUM", "MARC", "INICI", "FINAL", "LONG_ADN", "LONG_AA", "PES_MOLEC", "SEQUENCIA AA");
fprintf(fitxer, "--------------------------------------------------------------------------------\n");
for(int i = 0; i < total_orfs; i++){
fprintf(fitxer, "%-6d %-6d %-8d %-8d %-8d %-8d %-10.1f %s\n",
i + 1,
orfs[i].marc + 1,
orfs[i].inici,
orfs[i].final,
orfs[i].longitud_adn,
orfs[i].longitud_aa,
orfs[i].pes_molecular,
orfs[i].sequencia_aa ? orfs[i].sequencia_aa : "N/A");
}
/* Detall de cada ORF */
fprintf(fitxer, "\n--- DETALL DELS ORFs ---\n\n");
for(int i = 0; i < total_orfs; i++){
fprintf(fitxer, "ORF %d:\n", i + 1);
fprintf(fitxer, " Marc de lectura: %d\n", orfs[i].marc + 1);
fprintf(fitxer, " Posicio: %d - %d\n", orfs[i].inici, orfs[i].final);
fprintf(fitxer, " Longitud ADN: %d nucleotids\n", orfs[i].longitud_adn);
fprintf(fitxer, " Longitud proteica: %d aminoacids\n", orfs[i].longitud_aa);
fprintf(fitxer, " Pes molecular estimat: %.1f Da\n", orfs[i].pes_molecular);
if(orf[i].sequencia_aa){
fprintf(fitxer, " Sequencia d'aminoacids: %s\n", orfs[i].sequencia_aa);
}
fprintf(fitxer, "\n");
}
}
fclose(fitxer);
printf("Informe guardat a '%s'.\n", nom_fitxer);
}
/* Funció per alliberar la memòria dels ORFs */
void alliberar_orfs(){
for(int i = 0; i < total_orfs; i++){
if(orfs[i].sequencia_aa != NULL){
free(orfs[i].sequencia_aa); /* Allibera la seqüència d'aminoàcids */
orfs[i].sequencia_aa = NULL; /* Evita punters penjants */
}
}
total_orfs = 0; /* Reinicia el comptador */
}
/* Funció per traduir un codó a aminoàcid */
char traduir_codo(const char *codo){
/* Taula de traducció simplificada */
/* Aminoàcids representats pel codi d'una lletra */
if(strcmp(codo, "GCA")==0 || strcmp(codo, "GCC")==0 ||
strcmp(codo, "GCG")==0 || strcmp(codo, "GCT")==0) return 'A'; /* Alanina */
if(strcmp(codo, "TGC")==0 || strcmp(codo, "TGT")==0) return 'C'; /* Cisteina */
if(strcmp(codo, "GAC")==0 || strcmp(codo, "GAT")==0) return 'D'; /* Aspartat */
if(strcmp(codo, "GAA")==0 || strcmp(codo, "GAG")==0) return 'E'; /* Glutamat */
if(strcmp(codo, "TTC")==0 || strcmp(codo, "TTT")==0) return 'F'; /* Fenilalanina */
if(strcmp(codo, "GGA")==0 || strcmp(codo, "GGC")==0 ||
strcmp(codo, "GGG")==0 || strcmp(codo, "GGT")==0) return 'G'; /* Glicina */
if(strcmp(codo, "CAC")==0 || strcmp(codo, "CAT")==0) return 'H'; /* Histidina */
if(strcmp(codo, "ATA")==0 || strcmp(codo, "ATC")==0 ||
strcmp(codo, "ATT")==0) return 'I'; /* Isoleucina */
if(strcmp(codo, "AAA")==0 || strcmp(codo, "AAG")==0) return 'K'; /* Lisina */
if(strcmp(codo, "TTA")==0 || strcmp(codo, "TTG")==0 ||
strcmp(codo, "CTA")==0 || strcmp(codo, "CTC")==0 ||
strcmp(codo, "CTG")==0 || strcmp(codo, "CTT")==0) return 'L'; /* Leucina */
if(strcmp(codo, "ATG")==0) return 'M'; /* Metionina (START) */
if(strcmp(codo, "AAC")==0 || strcmp(codo, "AAT")==0) return 'N'; /* Asparagina */
if(strcmp(codo, "CCA")==0 || strcmp(codo, "CCC")==0 ||
strcmp(codo, "CCG")==0 || strcmp(codo, "CCT")==0) return 'P'; /* Prolina */
if(strcmp(codo, "CAA")==0 || strcmp(codo, "CAG")==0) return 'Q'; /* Glutamina */
if(strcmp(codo, "AGA")==0 || strcmp(codo, "AGG")==0 ||
strcmp(codo, "CGA")==0 || strcmp(codo, "CGC")==0 ||
strcmp(codo, "CGG")==0 || strcmp(codo, "CGT")==0) return 'R'; /* Arginina */
if(strcmp(codo, "TCA")==0 || strcmp(codo, "TCC")==0 ||
strcmp(codo, "TCG")==0 || strcmp(codo, "TCT")==0 ||
strcmp(codo, "AGC")==0 || strcmp(codo, "AGT")==0) return 'S'; /* Serina */
if(strcmp(codo, "ACA")==0 || strcmp(codo, "ACC")==0 ||
strcmp(codo, "ACG")==0 || strcmp(codo, "ACT")==0) return 'T'; /* Treonina */
if(strcmp(codo, "GTA")==0 || strcmp(codo, "GTC")==0 ||
strcmp(codo, "GTG")==0 || strcmp(codo, "GTT")==0) return 'V'; /* Valina */
if(strcmp(codo, "TGG")==0) return 'W'; /* Triptòfan */
if(strcmp(codo, "TAC")==0 || strcmp(codo, "TAT")==0) return 'Y'; /* Tirosina */
if(strcmp(codo, "TAA")==0 || strcmp(codo, "TAG")==0 ||
strcmp(codo, "TGA")==0) return '*'; /* STOP */
return 'X'; /* Desconegut */
}
/* Funció: comprova si un codó és d'inici (ATG) */
int es_codo_inici(const char *codo){
return (strcmp(codo, "ATG") == 0); /* Retorna 1 si és ATG, 0 si no */
}
/* Funció: comprova si un codó és de parada */
int es_codo_stop(const char *codo){
return (strcmp(codo, "TAA") == 0 ||
strcmp(codo, "TAG") == 0 ||
strcmp(codo, "TGA") == 0);
}
/* Funció: retorna el pes molecular aproximat d'un aminoàcid */
float pes_aminoacid(char aa){
switch(aa){
case 'A': return 89.1; /* Alanina */
case 'C': return 121.2; /* Cisteina */
case 'D': return 133.1; /* Aspartat */
case 'E': return 147.1; /* Glutamat */
case 'F': return 165.2; /* Fenilalanina */
case 'G': return 75.1; /* Glicina */
case 'H': return 155.2; /* Histidina */
case 'I': return 131.2; /* Isoleucina */
case 'K': return 146.2; /* Lisina */
case 'L': return 131.2; /* Leucina */
case 'M': return 149.2; /* Metionina */
case 'N': return 132.1; /* Asparagina */
case 'P': return 115.1; /* Prolina */
case 'Q': return 146.2; /* Glutamina */
case 'R': return 174.2; /* Arginina */
case 'S': return 105.1; /* Serina */
case 'T': return 119.1; /* Treonina */
case 'V': return 117.1; /* Valina */
case 'W': return 204.2; /* Triptòfan */
case 'Y': return 181.2; /* Tirosina */
default: return 110.0; /* Pes mitjà per a desconeguts */
}
}
/* Funció de comparació per a qsort (ordenar ORFs per longitud descendent) */
int comparar_orfs_per_longitud(const void *a, const void *b){
const ORF *orf_a = (const ORF*)a; /* Converteix void* a ORF* */
const ORF *orf_b = (const ORF*)b;
/* Ordena de més llarg a més curt (descendent) */
if(orf_a->longitud_adn > orf_b->longitud_adn)
return -1; /* a va abans si és més llarg */
else if(orf_a->longitud_adn < orf_b->longitud_adn)
return 1; /* a va després si és més curt */
else
return 0; /* Mateixa longitud */
}