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