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
22. 8. 2021 (L) Přecházíme zpět na doménu forum.matweb.cz!
04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
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: 4873
Reputace:   125 
 

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