Matematické Fórum

Nevíte-li si rady s jakýmkoliv matematickým problémem, toto místo je pro vás jako dělané.

Nástěnka
!! 17.06.2018 (Jel.) Khanova škola zve nadšence ke spolupráci na překladech návodů pro učitele a rodiče.
! 04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
17.01.2016 (Jel.) Rok 2016 s novými a novějšími krystaly od kolegy Pavla!
17.01.2016 (Jel.) Nabídka knih z oborů matematiky, fyziky, chemie
23.10.2013 (Jel.) Zkuste před zadáním dotazu použít některý z online-nástrojů, konzultovat použití můžete v sekci CAS.

Nejste přihlášen(a). Přihlásit

#1 30. 10. 2018 16:38

Noname753
Zelenáč
Příspěvky: 1
Reputace:   
 

Setřídění spojáku

Ahoj,
potřeboval bych pomoct najít chybu v následujícím spojáku psaným v C.
Má za úkol setřídit od nejmenšího po největší a vypsat čísla, která jsou na vstupu oddělená mezerou nebo koncem řádku a konec pozná načtením prázdného řádku. Pro většinu vstupů funguje, ale údajně ne pro všechny.
Díky za odpověď.

Příklad vstupu:
1
5
9
7 5 3 6 5 4
8 5 2
0
-1
-7
-5 -2 -3
-9 -8 -6 -4

Výstup:
-9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 5 5 5 6 7 8 9

Code:

#include <stdio.h> /* for printf */
#include <stdlib.h> /* for malloc */

typedef struct cislo {
    int hodnota;
    struct cislo *p_dalsi;
} uzel;

typedef struct {
    int pocet;
    uzel *p_hlava;
    uzel *p_ocas;
} seznam;

seznam *vytvorSeznam()
{
    seznam *p_seznam = (seznam*)malloc(sizeof(seznam));
    p_seznam->p_hlava = NULL;
    p_seznam->p_ocas = NULL;
    p_seznam->pocet = 0;
    return p_seznam;
}

void uvolniSeznam(seznam *p_seznam)
{
    uzel *p_aktualni = p_seznam->p_hlava;
    uzel *p_stara;
    while (p_aktualni != NULL) {
        p_stara = p_aktualni;
        p_aktualni = p_aktualni->p_dalsi;
        free(p_stara);
    }
    free(p_seznam);
}

uzel *pridejNaKonecSeznamu(seznam *p_seznam, int hodnota) {
    uzel *p_novy;
    p_novy = (uzel*)malloc(sizeof(uzel));
    if (p_novy == NULL) { printf("Nedostatek pameti!\n"); exit(1); }
    p_novy->p_dalsi = NULL;
    if (p_seznam->p_ocas != NULL) 
    {
        p_seznam->p_ocas->p_dalsi = p_novy;
        p_seznam->p_ocas = p_novy;
    }
    else
    {
        p_seznam->p_hlava = p_novy;
        p_seznam->p_ocas = p_novy;
    }
    p_novy->hodnota = hodnota;
    p_seznam->pocet++;
    return p_novy;
}

uzel *pridejDoprostredSeznamu(seznam *p_seznam, int hodnota) {
    
    uzel *p_aktualni = p_seznam->p_hlava;
    uzel *p_novy;
    uzel *p_predchozi=NULL;
    p_novy = (uzel*)malloc(sizeof(uzel));
    if (p_novy == NULL){ printf("Nedostatek pameti!\n"); exit(1); }
        while (p_aktualni->p_dalsi != NULL && p_aktualni->hodnota < hodnota) {
            //printf("Pred: %d < %d\n", p_aktualni->hodnota, hodnota);
            p_predchozi = p_aktualni;
            p_aktualni = p_aktualni->p_dalsi;
            //printf("Po: %d < %d\n", p_aktualni->hodnota, hodnota);
            //    printf("Predchozi: %d", p_predchozi->hodnota);
            //    printf("Aktualni: %d", p_aktualni->hodnota);
            
        }
    if (p_aktualni != p_seznam->p_hlava && p_aktualni != p_seznam->p_ocas) {
        printf("Pridavam doprostred mezi dva prvky\n");
        p_predchozi->p_dalsi = p_novy;
        p_novy->p_dalsi = p_aktualni;
    }
    else if (p_aktualni == p_seznam->p_hlava && p_aktualni == p_seznam->p_ocas) { 
        printf("Pridavam k jednomu prvku\n");
        if (p_aktualni->hodnota < hodnota) { return pridejNaKonecSeznamu(p_seznam, hodnota); } 
        else { p_novy->p_dalsi = p_aktualni; p_seznam->p_hlava = p_novy; }
    }
    else if (p_aktualni == p_seznam->p_hlava) { 
        printf("Pridavam na zacatek\n"); 
        p_novy->p_dalsi = p_aktualni; p_seznam->p_hlava = p_novy; }
    
    else if (p_aktualni == p_seznam->p_ocas) {
        
        if (p_aktualni->hodnota < hodnota) { printf("Pridavam na konec\n"); return pridejNaKonecSeznamu(p_seznam, hodnota); }
        else { printf("Pridavam na predposledni misto\n"); p_predchozi->p_dalsi = p_novy; p_novy->p_dalsi = p_aktualni; }
    }

    p_novy->hodnota = hodnota;
    p_seznam->pocet++;
    return p_novy;
}


void vypisSeznam(seznam *p_seznam) {
    uzel *p_aktualni = p_seznam->p_hlava;
    while (p_aktualni != NULL)
    {
        printf("%d ", p_aktualni->hodnota);
        p_aktualni = p_aktualni->p_dalsi;
    }
}

int main() {
    seznam *p_seznam = vytvorSeznam();
    int cislo = 0, minus = 0;
    char znak = getchar();
    while (znak != '\n' && znak != EOF)
    {    
        cislo = 0;
        while (znak != '\n' && znak != ' ') {
            if (znak == '-') { minus = 1; znak = getchar(); }
            if (znak != '\n' && znak != ' ') { cislo = cislo * 10 + znak - '0'; znak = getchar(); }
        }
        if (minus) { cislo = -1 * cislo; minus = 0; }
        printf("Nactene cislo: %d\n", cislo);
        if (p_seznam->pocet == 0) { pridejNaKonecSeznamu(p_seznam, cislo); }
        else { pridejDoprostredSeznamu(p_seznam, cislo); }
        vypisSeznam(p_seznam);
        printf("\n");
        znak = getchar();

    }

    vypisSeznam(p_seznam);
    uvolniSeznam(p_seznam);
    for (;;);
    return 0;
}

Offline

 

#2 30. 10. 2018 23:31

MichalAld
Moderátor
Příspěvky: 1936
Reputace:   56 
 

Re: Setřídění spojáku

To bude těžké... podle mě to máš napsané dost zbytečně komplikovaně, a tudíž je to dost nepřehledné.

Nevím, v čem konkrétně má být chyba, jestli v načítání toho čísla, nebo v zařazování do seznamu.
Pokud jde o to první (načítání čísel), je to takové dost divné. Třeba z mezery na začátku řádku to podle mě vytvoří číslo nula.
Znaménk minus uvnitř čísla to zpracuje stejně jako na začátku čísla, a pokud tam napíšeš nějaké písmeno, tak to z něj asi také vygeneruje nějaké číslo.

Já bych to dělal trochu jinak, nejprve bych si načetl všechna písmena až po oddělovací token (v tomto případě po mezeru nebo ten \n) a ukládal si je do nějakého pole (kam by se na ně dalo také koukat), a převedl bych si to až nakonec, až bych tam měl celé číslo. Lze na to použít fci sscanf. Také v rámci načítání jednotlivých znaků kontrolovat jestli jsou to povolené znaky (čísla a znaménko minus).

Pak třeba nechápu, na co máš tu proměnou p_ocas, moc nerozumím, k čemu je potřeba. A ten počet prvků vlastně taky né -
a tím pádem ani celá struktura seznam. Stačil by přece ukazatel na ten první prvek. Ale já nevím, třeba to nějaký důvod má. I to zařazování mi přijde takové komplikované.

Offline

 

Zápatí

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson