Tema 7 - Cerca i Ordenació

Cerca lineal de proteïna

Implementa una cerca lineal per trobar un nom de proteïna en un array de structs. Si la troba, mostra'n la longitud.

#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 strcmp() i strlen() */

/* Definició de l'estructura Proteina */
/* Una struct agrupa dades relacionades d'un mateix concepte */
struct Proteina {  /* 'struct Proteina' és el nom complet del tipus */
    char nom[50];       /* Nom o identificador de la proteïna */
                        /* Array de 50 caràcters (49 útils + '\0') */
    char sequencia[200]; /* Seqüència d'aminoàcids */
                         /* Array de 200 caràcters per a la seqüència */
    int longitud;        /* Longitud de la seqüència (calculada) */
};

/* Funció de cerca lineal en un array de proteïnes */
/* Busca una proteïna pel seu nom i retorna la seva posició (índex) */
/* Retorna -1 si no la troba */
int cerca_lineal(struct Proteina array[], int mida, const char* nom_buscat){
    /* Paràmetres:
       - array[]: array d'estructures Proteina on buscar
       - mida: nombre d'elements de l'array
       - nom_buscat: cadena amb el nom a buscar (const: no es modificarà)
       Retorna: índex de la proteïna trobada o -1 */

    /* Bucle de cerca lineal: recorre l'array element per element */
    for(int i = 0; i < mida; i++){  /* Itera des de l'índex 0 fins a mida-1 */
        /* Compara el nom de la proteïna actual amb el nom buscat */
        /* strcmp() compara dues cadenes alfabèticament */
        /* Retorna 0 si són IGUALS */
        if(strcmp(array[i].nom, nom_buscat) == 0){
            /* Si els noms coincideixen, retorna l'índex on s'ha trobat */
            return i;  /* 'return' finalitza la funció immediatament */
                       /* No cal seguir buscant un cop trobada */
        }
    }

    /* Si el bucle acaba sense haver trobat coincidència */
    return -1;  /* Retorna -1 per indicar "no trobat" */
                /* -1 és un valor convencional perquè no pot ser un índex vàlid */
                /* Els índexs vàlids van de 0 a mida-1 */
}

int main(){  /* Funció principal del programa */

    /* Declara i inicialitza un array de 5 proteïnes */
    struct Proteina proteines[5] = {
        {"Insulina",     "MALWMRLLPLLALLALWGPDPAAAFVNQHLCGSHLVEALYLVCGERGFFYTPKT", 0},
        /* Inicialització completa: nom, seqüència, longitud (0 = per calcular) */
        {"Hemoglobina",  "MVLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHF", 0},
        {"Albumina",     "DAHKSEVAHRFKDLGEENFKALVLIAFAQYLQQCPFEDHVKLVNEVTEF", 0},
        {"Colagen",      "GPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPM", 0},
        {"Queratina",    "MSRRKFVASSSSLNSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS", 0}
    };

    int num_proteines = 5;  /* Nombre total de proteïnes a l'array */
                            /* Es podria calcular amb sizeof(proteines)/sizeof(proteines[0]) */

    /* Calcula la longitud de cada proteïna a partir de la seva seqüència */
    printf("=== CALCULANT LONGITUDS ===\n");
    for(int i = 0; i < num_proteines; i++){
        proteines[i].longitud = strlen(proteines[i].sequencia);
        /* strlen() retorna el nombre de caràcters de la cadena (sense comptar '\0') */
        printf("  %s: %d aminoacids\n", proteines[i].nom, proteines[i].longitud);
    }

    /* Demana a l'usuari quina proteïna vol buscar */
    char buscar[50];  /* Buffer per al nom a buscar */
    printf("\nQuina proteina vols buscar? ");  /* Demana el nom */
    scanf("%49s", buscar);  /* Llegeix fins a 49 caràcters (deixant espai per a '\0') */
                            /* %49s limita la lectura per evitar desbordaments */

    /* Crida a la funció de cerca lineal */
    int posicio = cerca_lineal(proteines, num_proteines, buscar);
    /* Passa l'array, la mida i el nom a buscar */
    /* El resultat s'emmagatzema a 'posicio' */

    /* Avalua el resultat de la cerca */
    if(posicio != -1){  /* Si s'ha trobat (posicio != -1) */
        printf("\n=== PROTEINA TROBADA ===\n");
        printf("  Nom:      %s\n", proteines[posicio].nom);  /* Mostra el nom */
        printf("  Sequencia: %s\n", proteines[posicio].sequencia);  /* Mostra la seqüència */
        printf("  Longitud:  %d aminoacids\n", proteines[posicio].longitud);  /* Mostra la longitud */
        printf("  Index a l'array: %d\n", posicio);  /* Mostra la posició */
    } else {  /* Si no s'ha trobat (posicio == -1) */
        printf("\nProteina '%s' no trobada a la base de dades.\n", buscar);
        printf("Proteines disponibles:\n");
        for(int i = 0; i < num_proteines; i++)
            printf("  - %s\n", proteines[i].nom);  /* Mostra les proteïnes disponibles */
    }

    /* Demostració de l'eficiència de la cerca lineal */
    printf("\n=== ANALISI DE LA CERCA LINEAL ===\n");
    printf("Complexitat temporal: O(n)\n");  /* Notació Big O: creix linealment amb n */
    printf("  Millor cas: O(1) - l'element buscat es el primer\n");
    printf("  Pitjor cas: O(n) - l'element buscat es l'ultim o no hi es\n");
    printf("  Cas mitja:  O(n/2) - aproximadament la meitat de l'array\n");

    return 0;  /* Finalitza el programa amb èxit */
}

Ordenació amb qsort()

Ordena un vector de floats (pH de mostres) amb qsort() de manera ascendent i mostra el resultat.

#include <stdio.h>  /* Inclou la biblioteca estàndard d'entrada/sortida */
                     /* Necessària per a printf() */
#include <stdlib.h>  /* Inclou la biblioteca estàndard */
                     /* Necessària per a qsort() - Quick Sort */
                     /* qsort() és una funció d'ordenació ràpida incorporada a C */

/* Funció de comparació per a qsort() */
/* Aquesta funció és necessària perquè qsort() sigui genèrica */
/* qsort() necessita saber COM comparar dos elements */
int comparar_floats(const void *a, const void *b){
    /* Paràmetres:
       - a, b: punters genèrics (void*) als elements a comparar
       - const: la funció no modificarà els valors
       Retorna:
       - valor negatiu si *a < *b (a va abans que b)
       - 0 si *a == *b (són iguals)
       - valor positiu si *a > *b (a va després que b) */

    /* Converteix els punters void* a float* i obté els valors */
    float valor_a = *(const float*)a;  /* (const float*)a: converteix void* a float* */
                                        /* *(const float*)a: desreferencia per obtenir el float */
    float valor_b = *(const float*)b;  /* Igual per a b */

    /* Compara els valors i retorna el resultat */
    if(valor_a < valor_b)
        return -1;  /* a és menor que b: a va abans (ordre ascendent) */
    else if(valor_a > valor_b)
        return 1;   /* a és major que b: a va després (ordre ascendent) */
    else
        return 0;   /* Són iguals: ordre indiferent */
}

/* Funció alternativa: comparació en ordre descendent */
int comparar_floats_desc(const void *a, const void *b){
    float valor_a = *(const float*)a;
    float valor_b = *(const float*)b;

    /* Inverteix la lògica per obtenir ordre descendent */
    if(valor_a > valor_b)
        return -1;  /* a és major: va abans (ordre descendent) */
    else if(valor_a < valor_b)
        return 1;   /* a és menor: va després (ordre descendent) */
    else
        return 0;
}

int main(){  /* Funció principal del programa */

    /* Array de pH de mostres de laboratori */
    float pH_mostres[] = {7.4, 5.2, 8.1, 6.3, 7.0, 4.8, 9.2, 6.8, 7.35, 5.9};
    /* Valors típics de pH en mostres biològiques:
       - Sang: ~7.4
       - Orina: 5.0-8.0
       - Saliva: 6.2-7.4
       - Suc gàstric: 1.5-3.5 */

    /* Calcula el nombre d'elements de l'array */
    int n = sizeof(pH_mostres) / sizeof(pH_mostres[0]);
    /* sizeof(pH_mostres): mida total de l'array en bytes (10 * 4 = 40 bytes) */
    /* sizeof(pH_mostres[0]): mida d'un element (4 bytes per a float) */
    /* 40 / 4 = 10 elements */

    /* Mostra l'array original (sense ordenar) */
    printf("=== MESURES DE pH DE MOSTRES BIOLOGIQUES ===\n\n");
    printf("Array original (sense ordenar):\n  ");
    for(int i = 0; i < n; i++){
        printf("%.2f ", pH_mostres[i]);  /* Mostra cada valor amb 2 decimals */
    }
    printf("\n\n");

    /* Crida a qsort() per ordenar l'array */
    /* Sintaxi: qsort(array, nombre_elements, mida_element, funcio_comparacio) */
    qsort(pH_mostres,         /* Punter al primer element de l'array */
          n,                  /* Nombre d'elements a ordenar */
          sizeof(float),      /* Mida en bytes de cada element */
          comparar_floats);   /* Funció de comparació (punter a funció) */
    /* qsort() modifica l'array original in situ */
    /* Utilitza l'algorisme Quick Sort: eficiència mitjana O(n log n) */

    /* Mostra l'array ordenat ascendentment */
    printf("Array ordenat ascendentment (pH de menor a major):\n  ");
    for(int i = 0; i < n; i++){
        printf("%.2f ", pH_mostres[i]);
    }
    printf("\n");

    /* Mostra informació addicional sobre les mostres */
    printf("\n=== INFORMACIO ADDICIONAL ===\n");
    printf("pH minim:  %.2f\n", pH_mostres[0]);    /* Després d'ordenar ascendent, el mínim és el primer */
    printf("pH maxim:  %.2f\n", pH_mostres[n-1]);  /* El màxim és l'últim */
    printf("pH mitja:  %.2f\n", (pH_mostres[0] + pH_mostres[n-1]) / 2);  /* Mitjana aritmètica simple */

    /* Classificació de les mostres segons el pH */
    printf("\n=== CLASSIFICACIO DE LES MOSTRES ===\n");
    for(int i = 0; i < n; i++){
        printf("  pH %.2f: ", pH_mostres[i]);
        if(pH_mostres[i] < 5.5)
            printf("ACID (possible suc gastric o fermentacio)\n");
        else if(pH_mostres[i] < 6.5)
            printf("Lleugerament acid (possible orina)\n");
        else if(pH_mostres[i] < 7.5)
            printf("NEUTRE (possible sang o saliva)\n");
        else if(pH_mostres[i] < 8.5)
            printf("Lleugerament basic (possible orina alcalina)\n");
        else
            printf("BASIC (possible mostra contaminada)\n");
    }

    /* Demostració de l'ordenació descendent */
    printf("\n=== ORDENACIO DESCENDENT (DEMOSTRACIO) ===\n");
    qsort(pH_mostres, n, sizeof(float), comparar_floats_desc);
    printf("Array ordenat descendentment (pH de major a menor):\n  ");
    for(int i = 0; i < n; i++){
        printf("%.2f ", pH_mostres[i]);
    }
    printf("\n");

    return 0;  /* Finalitza el programa amb èxit */
}

Ordenació de proteïnes i cerca binària

Crea una funció de comparació que ordeni proteïnes per longitud de manera descendent i busca la més llarga amb bsearch().

#include <stdio.h>  /* Inclou la biblioteca estàndard d'entrada/sortida */
#include <stdlib.h>  /* Inclou la biblioteca estàndard */
                     /* Necessària per a qsort() i bsearch() */
#include <string.h>  /* Inclou la biblioteca per a funcions de cadenes */
                     /* Necessària per a strlen() i strcmp() */

/* Definició de l'estructura Proteina */
struct Proteina {
    char nom[50];        /* Nom de la proteïna */
    char sequencia[200]; /* Seqüència d'aminoàcids */
    int longitud;        /* Longitud de la seqüència */
};

/* Funció de comparació per ordenar per LONGITUD (ascendent) */
/* Aquesta funció s'usa amb qsort() per ordenar l'array */
int comparar_per_longitud_asc(const void *a, const void *b){
    /* Converteix els punters void* a punters a struct Proteina */
    const struct Proteina *prot_a = (const struct Proteina*)a;
    const struct Proteina *prot_b = (const struct Proteina*)b;
    /* (const struct Proteina*): cast de void* al tipus correcte */

    /* Compara les longituds de les dues proteïnes */
    if(prot_a->longitud < prot_b->longitud)
        return -1;  /* a és més curta: va abans (ascendent) */
    else if(prot_a->longitud > prot_b->longitud)
        return 1;   /* a és més llarga: va després (ascendent) */
    else
        return 0;   /* Mateixa longitud */
}

/* Funció de comparació per ordenar per LONGITUD (descendent) */
int comparar_per_longitud_desc(const void *a, const void *b){
    const struct Proteina *prot_a = (const struct Proteina*)a;
    const struct Proteina *prot_b = (const struct Proteina*)b;

    /* Inverteix la lògica per obtenir ordre descendent */
    if(prot_a->longitud > prot_b->longitud)
        return -1;  /* a és més llarga: va abans (descendent) */
    else if(prot_a->longitud < prot_b->longitud)
        return 1;   /* a és més curta: va després (descendent) */
    else
        return 0;
}

/* Funció de comparació per a bsearch() */
/* bsearch() necessita una funció que compari la CLAU amb un ELEMENT */
int comparar_per_bsearch(const void *clau, const void *element){
    /* clau: punter al valor buscat (int: longitud buscada) */
    /* element: punter a un element de l'array (struct Proteina) */

    int longitud_buscada = *(const int*)clau;  /* Desreferencia la clau per obtenir l'enter */
    const struct Proteina *prot = (const struct Proteina*)element;  /* Converteix l'element */

    /* Compara la longitud buscada amb la longitud de l'element */
    if(longitud_buscada < prot->longitud)
        return -1;
    else if(longitud_buscada > prot->longitud)
        return 1;
    else
        return 0;  /* Longituds iguals: trobat! */
}

int main(){  /* Funció principal */

    /* Declara i inicialitza un array de proteïnes */
    struct Proteina proteines[] = {
        {"Colagen",      "GPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPM", 0},
        {"Insulina",     "MALWMRLLPLLALLALWGPDPAAAFVNQHLCGSHLVEALYLVCGERGFFYTPKT", 0},
        {"Queratina",    "MSRRKFVASSSSLNSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS", 0},
        {"Hemoglobina",  "MVLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHF", 0},
        {"Albumina",     "DAHKSEVAHRFKDLGEENFKALVLIAFAQYLQQCPFEDHVKLVNEVTEF", 0},
        {"Mioglobina",   "MGLSDGEWQLVLNVWGKVEADIPGHGQEVLIRLFKGHPETLEKFDKFKHLKSEDEMKASEDLKKHGATVLTALGGILKKKGHHEAEIKPLAQSHATKHKIPVKYLEFISECIIQVLQSKHPGDFGADAQGAMNKALELFRKDMASNYKELGFQG", 0}
    };

    int n = sizeof(proteines) / sizeof(proteines[0]);  /* Calcula el nombre de proteïnes */

    /* Calcula les longituds de totes les proteïnes */
    printf("=== PROTEINES I LES SEVES LONGITUDS ===\n");
    for(int i = 0; i < n; i++){
        proteines[i].longitud = strlen(proteines[i].sequencia);
        printf("  %-15s: %3d aminoacids\n", proteines[i].nom, proteines[i].longitud);
    }

    /* Ordena per longitud descendent (de més llarga a més curta) */
    printf("\n=== ORDENACIO PER LONGITUD (DESCENDENT) ===\n");
    qsort(proteines, n, sizeof(struct Proteina), comparar_per_longitud_desc);
    /* qsort() modifica l'array original */

    /* Mostra l'array ordenat */
    printf("%-15s %8s %s\n", "PROTEINA", "LONGITUD", "SEQUENCIA (primers 40 aa)");
    printf("----------------------------------------------\n");
    for(int i = 0; i < n; i++){
        printf("%-15s %8d %.40s...\n", 
               proteines[i].nom, 
               proteines[i].longitud, 
               proteines[i].sequencia);  /* %.40s: mostra com a màxim 40 caràcters */
    }

    /* La proteïna més llarga és la primera (després d'ordenar descendent) */
    printf("\nProteina mes llarga: %s (%d aminoacids)\n", 
           proteines[0].nom, proteines[0].longitud);

    /* Cerca binària amb bsearch() */
    /* REQUISIT: l'array ha d'estar ORDENAT segons el criteri de cerca */
    printf("\n=== CERCA BINARIA (bsearch) ===\n");
    printf("Nota: bsearch() requereix que l'array estigui ordenat.\n");

    /* Busca una proteïna amb longitud 51 (Insulina) */
    int longitud_buscar = 51;  /* Longitud a buscar */
    printf("Buscant proteina amb longitud %d...\n", longitud_buscar);

    /* bsearch() retorna un punter a l'element trobat, o NULL si no el troba */
    struct Proteina *trobada = (struct Proteina*)bsearch(
        &longitud_buscar,       /* Punter a la clau de cerca (l'adreça de l'enter) */
        proteines,              /* Punter a l'array on buscar */
        n,                      /* Nombre d'elements de l'array */
        sizeof(struct Proteina),/* Mida de cada element */
        comparar_per_bsearch    /* Funció de comparació clau-element */
    );

    if(trobada != NULL){  /* Si bsearch() ha trobat l'element */
        printf("  Proteina trobada: %s\n", trobada->nom);
        printf("  Longitud: %d aminoacids\n", trobada->longitud);
        printf("  Sequencia: %.50s...\n", trobada->sequencia);
    } else {
        printf("  No s'ha trobat cap proteina amb longitud %d.\n", longitud_buscar);
    }

    /* Comparativa cerca lineal vs cerca binària */
    printf("\n=== COMPARATIVA D'EFICIENCIA ===\n");
    printf("Cerca lineal:  O(n)   - recorre tot l'array\n");
    printf("Cerca binaria: O(log n) - divideix l'espai de cerca a cada pas\n");
    printf("  Amb %d elements:\n", n);
    printf("    Lineal: fins a %d comparacions (pitjor cas)\n", n);
    printf("    Binaria: fins a %d comparacions (pitjor cas)\n", 
           (int)(log2(n) + 1));  /* Nombre màxim de passos en cerca binària */

    return 0;  /* Finalitza el programa amb èxit */
}

/* Funció auxiliar per calcular log2 (no disponible a math.h en tots els sistemes) */
int log2(int x){
    int resultat = 0;
    while(x > 1){
        x /= 2;
        resultat++;
    }
    return resultat;
}

Mini Projecte – Ordenació de proteïnes per longitud

Escriu un programa que llegeixi proteïnes d'un fitxer, les ordeni segons el criteri triat per l'usuari i guardi el resultat.

#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(), free(), qsort(), bsearch() */
#include <string.h>  /* Inclou la biblioteca per a funcions de cadenes */
                     /* Necessària per a strlen(), strcpy(), strcmp(), strcat() */
#include <ctype.h>   /* Inclou la biblioteca per a classificació de caràcters */
                     /* Necessària per a toupper() */

/* Definició global del tipus Proteina amb typedef */
/* typedef crea un àlies: 'Proteina' en lloc de 'struct Proteina' */
typedef struct {
    char *nom;        /* Punter al nom (memòria dinàmica per a flexibilitat) */
    char *sequencia;  /* Punter a la seqüència (memòria dinàmica) */
    int longitud;     /* Longitud de la seqüència */
} Proteina;  /* Ara 'Proteina' és un tipus vàlid */

/* Variables globals per a la gestió de proteïnes */
Proteina *llista = NULL;  /* Array dinàmic de proteïnes (creixerà amb malloc/realloc) */
int total = 0;            /* Nombre total de proteïnes carregades */

/* Prototips de les funcions del programa */
int carregar_proteines(const char *nom_fitxer);  /* Carrega proteïnes d'un fitxer */
void mostrar_proteines();                        /* Mostra la llista per pantalla */
void ordenar_proteines();                        /* Menú d'ordenació */
void guardar_proteines(const char *nom_fitxer);  /* Guarda la llista en un fitxer */
void cercar_proteina();                          /* Cerca binària per nom */
void alliberar_memoria();                        /* Allibera tota la memòria */

/* Funcions de comparació per a qsort() */
int comparar_per_nom(const void *a, const void *b);           /* Alfabètica ascendent */
int comparar_per_longitud_asc(const void *a, const void *b);  /* Longitud ascendent */
int comparar_per_longitud_desc(const void *a, const void *b); /* Longitud descendent */

/* Funció de comparació per a bsearch() (cerca per nom) */
int comparar_per_nom_bsearch(const void *clau, const void *element);

int main(){  /* Funció principal del programa */

    char nom_fitxer[100];  /* Nom del fitxer d'entrada */
    int opcio;             /* Opció del menú */

    printf("========================================\n");
    printf("  GESTOR DE PROTEINES - ORDENACIO\n");
    printf("========================================\n\n");

    /* Demana el fitxer de dades */
    printf("Nom del fitxer de proteines: ");
    scanf("%99s", nom_fitxer);

    /* Carrega les proteïnes del fitxer */
    int carregades = carregar_proteines(nom_fitxer);
    if(carregades == 0){
        printf("No s'han pogut carregar proteines. El programa finalitzara.\n");
        return 1;
    }
    printf("S'han carregat %d proteines correctament.\n\n", carregades);

    /* Bucle del menú principal */
    do{
        printf("\n--- MENU PRINCIPAL ---\n");
        printf("  1. Mostrar llista actual\n");
        printf("  2. Ordenar proteines\n");
        printf("  3. Cercar proteina per nom (cerca binaria)\n");
        printf("  4. Guardar llista ordenada\n");
        printf("  0. Sortir\n");
        printf("  Opcio: ");
        scanf("%d", &opcio);
        getchar();  /* Consumeix el '\n' del buffer */

        switch(opcio){
            case 1: 
                mostrar_proteines(); 
                break;
            case 2: 
                ordenar_proteines(); 
                break;
            case 3: 
                cercar_proteina(); 
                break;
            case 4: 
                guardar_proteines("proteines_ordenades.txt"); 
                break;
            case 0:
                printf("\nAlliberant memoria i sortint...\n");
                alliberar_memoria();
                printf("Adeu!\n");
                break;
            default:
                printf("Opcio no valida.\n");
        }
    } while(opcio != 0);

    return 0;  /* Finalitza el programa */
}

/* Funció per carregar proteïnes d'un fitxer */
int carregar_proteines(const char *nom_fitxer){
    FILE *fitxer = fopen(nom_fitxer, "r");  /* Obre el fitxer en mode lectura */
    if(fitxer == NULL){
        printf("Error: No s'ha pogut obrir el fitxer '%s'.\n", nom_fitxer);
        printf("Creant fitxer d'exemple 'proteines.txt'...\n");

        /* Crea un fitxer d'exemple si no existeix */
        fitxer = fopen(nom_fitxer, "w");
        if(fitxer == NULL) return 0;

        /* Escriu dades d'exemple en format: nom,sequencia */
        fprintf(fitxer, "Insulina,MALWMRLLPLLALLALWGPDPAAAFVNQHLCGSHLVEALYLVCGERGFFYTPKT\n");
        fprintf(fitxer, "Hemoglobina,MVLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHF\n");
        fprintf(fitxer, "Albumina,DAHKSEVAHRFKDLGEENFKALVLIAFAQYLQQCPFEDHVKLVNEVTEF\n");
        fprintf(fitxer, "Colagen,GPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPMGPM\n");
        fprintf(fitxer, "Queratina,MSRRKFVASSSSLNSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS\n");
        fprintf(fitxer, "Mioglobina,MGLSDGEWQLVLNVWGKVEADIPGHGQEVLIRLFKGHPETLEKFDKFKHLKSEDEMKASEDLKKHGATVLTALGGILKKKGHHEAEIKPLAQSHATKHKIPVKYLEFISECIIQVLQSKHPGDFGADAQGAMNKALELFRKDMASNYKELGFQG\n");
        fclose(fitxer);

        /* Torna a obrir en mode lectura */
        fitxer = fopen(nom_fitxer, "r");
        if(fitxer == NULL) return 0;
        printf("Fitxer d'exemple creat. Si us plau, torna a executar el programa.\n");
        fclose(fitxer);
        return 0;
    }

    char linia[1000];  /* Buffer per a cada línia */

    /* Bucle de lectura línia per línia */
    while(fgets(linia, sizeof(linia), fitxer) != NULL){
        /* Elimina el salt de línia */
        int len = strlen(linia);
        if(len > 0 && linia[len-1] == '\n')
            linia[len-1] = '\0';

        /* Separa el nom i la seqüència (format: nom,sequencia) */
        char *coma = strchr(linia, ',');  /* strchr() busca un caràcter en una cadena */
                                          /* Retorna un punter a la primera ocurrència */
        if(coma == NULL) continue;  /* Si no hi ha coma, ignora la línia */

        *coma = '\0';  /* Separa la cadena en dues parts */
        char *nom_linia = linia;           /* Primera part: nom */
        char *seq_linia = coma + 1;        /* Segona part: seqüència (després de la coma) */

        /* Expandir l'array dinàmic amb realloc() */
        Proteina *temp = (Proteina*)realloc(llista, (total + 1) * sizeof(Proteina));
        /* realloc() amb NULL es comporta com malloc() */
        /* Augmenta l'array en un element cada cop */

        if(temp == NULL){
            printf("Error de memoria.\n");
            break;
        }
        llista = temp;

        /* Reserva memòria per al nom i la seqüència */
        llista[total].nom = (char*)malloc((strlen(nom_linia) + 1) * sizeof(char));
        llista[total].sequencia = (char*)malloc((strlen(seq_linia) + 1) * sizeof(char));

        if(llista[total].nom == NULL || llista[total].sequencia == NULL){
            printf("Error de memoria.\n");
            break;
        }

        /* Copia les dades */
        strcpy(llista[total].nom, nom_linia);
        strcpy(llista[total].sequencia, seq_linia);
        llista[total].longitud = strlen(seq_linia);  /* Calcula la longitud */

        total++;  /* Incrementa el comptador */
    }

    fclose(fitxer);
    return total;  /* Retorna el nombre de proteïnes carregades */
}

/* Funció per mostrar la llista de proteïnes */
void mostrar_proteines(){
    if(total == 0){
        printf("\nNo hi ha proteines carregades.\n");
        return;
    }

    printf("\n=== LLISTA DE PROTEINES ===\n");
    printf("%-5s %-20s %8s %s\n", "NUM", "NOM", "LONGITUD", "SEQUENCIA (primers 40 aa)");
    printf("--------------------------------------------------------------\n");
    for(int i = 0; i < total; i++){
        printf("%-5d %-20s %8d %.40s%s\n", 
               i + 1, 
               llista[i].nom, 
               llista[i].longitud,
               llista[i].sequencia,
               llista[i].longitud > 40 ? "..." : "");
    }
}

/* Funció per al menú d'ordenació */
void ordenar_proteines(){
    if(total == 0){
        printf("\nNo hi ha proteines per ordenar.\n");
        return;
    }

    int criteri;
    printf("\n--- CRITERIS D'ORDENACIO ---\n");
    printf("  1. Per nom (alfabetic ascendent)\n");
    printf("  2. Per longitud (ascendent: de mes curta a mes llarga)\n");
    printf("  3. Per longitud (descendent: de mes llarga a mes curta)\n");
    printf("  Selecciona el criteri: ");
    scanf("%d", &criteri);

    /* Selecciona la funció de comparació segons el criteri */
    int (*funcio_comparacio)(const void*, const void*) = NULL;  /* Punter a funció */
    /* Un punter a funció emmagatzema l'adreça d'una funció */
    /* La sintaxi és complexa: tipus_retorn (*nom)(paràmetres) */

    const char *descripcio = "";  /* Descripció de l'ordenació */

    switch(criteri){
        case 1:
            funcio_comparacio = comparar_per_nom;
            descripcio = "nom (alfabetic ascendent)";
            break;
        case 2:
            funcio_comparacio = comparar_per_longitud_asc;
            descripcio = "longitud (ascendent)";
            break;
        case 3:
            funcio_comparacio = comparar_per_longitud_desc;
            descripcio = "longitud (descendent)";
            break;
        default:
            printf("Criteri no valid.\n");
            return;
    }

    /* Executa l'ordenació amb qsort() */
    qsort(llista, total, sizeof(Proteina), funcio_comparacio);

    printf("\nLlista ordenada per %s:\n", descripcio);
    mostrar_proteines();
}

/* Funció per guardar la llista en un fitxer */
void guardar_proteines(const char *nom_fitxer){
    if(total == 0){
        printf("\nNo hi ha proteines per guardar.\n");
        return;
    }

    FILE *fitxer = fopen(nom_fitxer, "w");
    if(fitxer == NULL){
        printf("Error: No s'ha pogut crear el fitxer '%s'.\n", nom_fitxer);
        return;
    }

    /* Escriu la capçalera */
    fprintf(fitxer, "========================================\n");
    fprintf(fitxer, "  PROTEINES ORDENADES\n");
    fprintf(fitxer, "========================================\n\n");
    fprintf(fitxer, "%-5s %-20s %8s %s\n", "NUM", "NOM", "LONGITUD", "SEQUENCIA");
    fprintf(fitxer, "--------------------------------------------------------------\n");

    /* Escriu cada proteïna */
    for(int i = 0; i < total; i++){
        fprintf(fitxer, "%-5d %-20s %8d %s\n", 
                i + 1, 
                llista[i].nom, 
                llista[i].longitud,
                llista[i].sequencia);
    }

    fclose(fitxer);
    printf("\nFitxer '%s' creat correctament amb %d proteines.\n", nom_fitxer, total);
}

/* Funció per cercar una proteïna amb cerca binària */
void cercar_proteina(){
    if(total == 0){
        printf("\nNo hi ha proteines per cercar.\n");
        return;
    }

    /* La cerca binària REQUEREIX que l'array estigui ordenat */
    /* Primer ordenem per nom alfabèticament */
    qsort(llista, total, sizeof(Proteina), comparar_per_nom);
    printf("Llista ordenada alfabeticament per a la cerca binaria.\n");

    char nom_buscar[100];
    printf("\nNom de la proteina a cercar: ");
    scanf("%99s", nom_buscar);

    /* Cerca binària amb bsearch() */
    Proteina *trobada = (Proteina*)bsearch(
        nom_buscar,                 /* Clau: el nom a buscar */
        llista,                     /* Array on buscar */
        total,                      /* Nombre d'elements */
        sizeof(Proteina),           /* Mida de cada element */
        comparar_per_nom_bsearch    /* Funció de comparació */
    );

    if(trobada != NULL){
        printf("\n=== PROTEINA TROBADA ===\n");
        printf("  Nom:      %s\n", trobada->nom);
        printf("  Longitud: %d aminoacids\n", trobada->longitud);
        printf("  Sequencia: %s\n", trobada->sequencia);
    } else {
        printf("\nProteina '%s' no trobada.\n", nom_buscar);
        printf("Proteines disponibles:\n");
        for(int i = 0; i < total; i++)
            printf("  - %s\n", llista[i].nom);
    }
}

/* Funció per alliberar tota la memòria dinàmica */
void alliberar_memoria(){
    for(int i = 0; i < total; i++){
        free(llista[i].nom);       /* Allibera el nom */
        free(llista[i].sequencia); /* Allibera la seqüència */
    }
    free(llista);  /* Allibera l'array de punters */
    llista = NULL;
    total = 0;
}

/* ============================================ */
/* FUNCIONS DE COMPARACIÓ PER A qsort()         */
/* ============================================ */

/* Comparació per nom (alfabètica ascendent) */
int comparar_per_nom(const void *a, const void *b){
    const Proteina *p1 = (const Proteina*)a;  /* Converteix void* a Proteina* */
    const Proteina *p2 = (const Proteina*)b;
    return strcmp(p1->nom, p2->nom);  /* strcmp() ja retorna -1, 0 o 1 */
}

/* Comparació per longitud ascendent */
int comparar_per_longitud_asc(const void *a, const void *b){
    const Proteina *p1 = (const Proteina*)a;
    const Proteina *p2 = (const Proteina*)b;

    if(p1->longitud < p2->longitud)
        return -1;
    else if(p1->longitud > p2->longitud)
        return 1;
    else
        return 0;
}

/* Comparació per longitud descendent */
int comparar_per_longitud_desc(const void *a, const void *b){
    const Proteina *p1 = (const Proteina*)a;
    const Proteina *p2 = (const Proteina*)b;

    /* Inverteix la lògica per a ordre descendent */
    if(p1->longitud > p2->longitud)
        return -1;
    else if(p1->longitud < p2->longitud)
        return 1;
    else
        return 0;
}

/* Funció de comparació per a bsearch() (cerca per nom) */
int comparar_per_nom_bsearch(const void *clau, const void *element){
    /* clau: punter a la cadena amb el nom buscat */
    /* element: punter a un element Proteina de l'array */
    const char *nom_buscat = (const char*)clau;
    const Proteina *prot = (const Proteina*)element;
    return strcmp(nom_buscat, prot->nom);  /* Compara les cadenes */
}