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
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
#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
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