Pepe
Pepe

Reputation: 515

Adding a sort algo to my program break functions before it

So I wrote a sorting algorithm (I'm still learning so it's probably a little mess).

Now when I add it to my main.c, it breaks the functions before it without even starting, and it makes no sense.

The sorting function is:

void ordinaAlfabeticamente(RecordSoggetto *elenco, int nElementi) {
    printf("avviando sorting");
    int i, j, comparatore;
    RecordSoggetto *copia = (RecordSoggetto *)malloc(sizeof(RecordSoggetto));
    _Bool isStillSorting = true;
    while (isStillSorting) {
        isStillSorting = false;
        for (i = 1; i < nElementi; i++) {
            memcpy(copia, &elenco[i], sizeof(RecordSoggetto));
            j = i - 1;
            comparatore = strcmp(elenco[j].cognome, copia->cognome);
            if (comparatore == 0) {
                comparatore = strcmp(elenco[j].nome, copia->nome);
            }
            while (j > 0 && comparatore) {
                isStillSorting = true;
                memcpy(&elenco[j + 1], &elenco[j], sizeof(RecordSoggetto));
                j--;
                memcpy(&elenco[j + 1], copia, sizeof(RecordSoggetto));
            }
        }
    }
}

And the main:

int main() {
    srand(time(NULL));
    VD database;
    caricaDati(&database, "../Database.dat");
    ordinaAlfabeticamente(database.v, database.nElementi);
    stampaElencoCriminali(database.v, database.nElementi);

    inizializzaVettoreDinamico(&database);

    return 0;
}

Now the interesting part, if the function ordinaAlfabeticamente is in the main the function caricaDati just gives up at the first line, like, literally.

caricaDati:

void caricaDati(VD *dati, char *nomefile) {
    printf("avviando carica dati\n");
    FILE *fp = apriFile(nomefile, "rb"); //apriFile is just open with control
    printf("file aperto");
    fread(&dati->nElementi, sizeof(int), 1, fp);
    printf("letto numero elementi");
    dati->v = (RecordSoggetto *)malloc(dati->nElementi * sizeof(RecordSoggetto));
    fread(dati->v, sizeof (RecordSoggetto), dati->nElementi, fp);
    printf("letto criminali");
    chiudiFile(fp);
};

The printf are for control and just the first one starts, I also tried to put a printf in the function apriFile but they don't start, so I'm assuming that the function just dies after the first printf.

To be more specific, once I start the program it just prints avviando carica dati\n and enters an infinite loop.

HOWEVER

If I just delete the call for ordinaAlfabeticamente in the main I get no problems.

Should I make something js-like to wait for the caricaDati to finish before the sorting function starts?

I TRIED TO TRANSLATE EVERYTHING TO ENGLISH TO MAKE IT MORE READABLE:

So I've wrote a sorting algo (I'm still learning so it's probably a little mess).

Now when I add it to my main.c it breaks the functions before it without even starting, and it makes no sense.

The sorting function is:

void sortAlphabetically(RecordSoggetto *elementList, int nElements) {
    printf("start sorting");
    int i, j, comparatore;
    RecordSoggetto *copy = (RecordSoggetto *)malloc(sizeof(RecordSoggetto));
    _Bool isStillSorting = true;
    while (isStillSorting) {
        isStillSorting = false;
        for (i = 1; i < nElements; i++) {
            memcpy(copy, &elementList[i], sizeof(RecordSoggetto));
            j = i - 1;
            comparatore = strcmp(elementList[j].surname, copy->surname);
            if (comparatore == 0) {
                comparatore = strcmp(elementList[j].name, copy->name);
            }
            while (j > 0 && comparatore) {
                isStillSorting = true;
                memcpy(&elementList[j + 1], &elementList[j], sizeof(RecordSoggetto));
                j--;
                memcpy(&elementList[j + 1], copy, sizeof(RecordSoggetto));
            }
        }
    }
}

And the main:

int main() {
    srand(time(NULL));
    VD database;
    loadData(&database, "../Database.dat");
    sortAlphabetically(database.v, database.nElementi);
    printElementList(database.v, database.nElementi);

    inizializzaVettoreDinamico(&database); // not relevant

    return 0;
}

Now the interesting part, if the function sortAlphabetically is in the main the function loadData just gives up at the first line, like, literally.

loadData:

void loadData(VD *data, char *filename) {
    printf("starting load data\n");
    FILE * fp = openFile(filename, "rb"); //apriFile is just open with control
    printf("file opened");
    fread(&data->nElements, sizeof(int), 1, fp);
    printf("read number of elements");
    data->v = (RecordSoggetto *)malloc(data->nElements * sizeof(RecordSoggetto));
    fread(data->v, sizeof (RecordSoggetto), data->nElements, fp);
    printf("read elements");
    closeFile(fp);
};

The printf are for control and just the first one starts, I also tried to put a printf in the function apriFile but they don't start, so I'm assuming that the function just dies after the first printf.

To be more specific, once I start the program it just print start load data\n and enters an infinite loop.

HOWEVER

If I just delete the call for sortAlphabetically in the main I get no problems.

Should I make something js-like to wait for the loadData to finish before the sorting function starts?

Upvotes: 1

Views: 46

Answers (1)

chqrlie
chqrlie

Reputation: 144770

Your sorting algorithm is incorrect, it does not swap the records in the right place.

Here is a modified version:

void ordinaAlfabeticamente(RecordSoggetto *elenco, int nElementi) {
    _Bool isStillSorting = true;
    while (isStillSorting) {
        isStillSorting = false;
        for (int i = 1; i < nElementi; i++) {
            int comparatore = strcmp(elenco[i - 1].cognome, elenco[i].cognome);
            if (comparatore > 0 ||
                (comparatore == 0 && strcmp(elenco[i - 1].nome, elenco[i].nome) > 0)) {
                // swap records that are out of order
                RecordSoggetto tmp = elenco[i - 1];
                elenco[i - 1] = elenco[i];
                elenco[i] = tmp;
                isStillSorting = true;
            }
        }
    }
}

Using English for identifiers is indeed more readable and easier to share with foreigners:

void sortAlphabetically(RecordSoggetto *elementList, int nElements) {
    _Bool isStillSorting = true;
    while (isStillSorting) {
        isStillSorting = false;
        for (int i = 1; i < nElements; i++) {
            int cmp = strcmp(elementList[i - 1].cognome, elementList[i].cognome);
            if (cmp > 0 ||
                (cmp == 0 && strcmp(elementList[i - 1].nome, elementList[i].nome) > 0)) {
                // swap records that are out of order
                RecordSoggetto tmp = elementList[i - 1];
                elementList[i - 1] = elementList[i];
                elementList[i] = tmp;
                isStillSorting = true;
            }
        }
    }
}

Old timers (such as I) will contend that shorter names for local variables actually increase readability. I let you be the judge for your own environment:

void sortAlphabetically(RecordSoggetto *array, int n) {
    int done = 0;
    while (!done) {
        done = 1;
        for (int i = 1; i < n; i++) {
            int cmp = strcmp(array[i - 1].cognome, array[i].cognome);
            if (cmp > 0 || (cmp == 0 && strcmp(array[i - 1].nome, array[i].nome) > 0)) {
                // swap records that are out of order
                RecordSoggetto tmp = array[i - 1];
                array[i - 1] = array[i];
                array[i] = tmp;
                done = 0;
            }
        }
    }
}

Upvotes: 2

Related Questions