Uložení obdélníkovýho vstupu do pole[radku][znaku] – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Uložení obdélníkovýho vstupu do pole[radku][znaku] – C / C++ – Fórum – Programujte.comUložení obdélníkovýho vstupu do pole[radku][znaku] – C / C++ – Fórum – Programujte.com

 

Why0
Duch
5. 1. 2011   #1
-
0
-

Ahoj, už den si lámu hlavu s tím, jak syntakticky zapsat problém v nadpisu:
Potřebuji ze standartního vstupu do dynamicky alokovanýho pole zapsat libovolně velkej vstup , ale vždy obdélníkovej, konec se značí feof stdinem. (V semestrálce takto musím zadat obdélníkové bludiště) Napsal jsem tohle, dělám to až teď do šesti do rána, a už fakt nevím, poradíte prosím někdo?
Aktuálně to dělá to, že po zadání prvního řádku, to šahá kam nemá a hodí to error...

#include <stdio.h>

#include <stdlib.h>
#include <string.h>
#define OUT_OF_MEMORY -3
#define S_EOF -2
#define INVALID_INPUT -1
#define OK 0

int read_row(int *needed_cols, char *b_row[]) {
char ch, last='0';
int i,n;
i = 0;
if (!*needed_cols) *needed_cols=3;
printf("needed_cols: %d", *needed_cols);
b_row = (char **) malloc ( sizeof ( *b_row ) * (*needed_cols) );
if (! *b_row) return (OUT_OF_MEMORY);

//ch = getchar();
while (((last != "\n") || (last != EOF)) && (scanf("%c",&ch)==1)) {
if ((*needed_cols) && (i >= *needed_cols)) {
return (INVALID_INPUT);
}
printf("ch: %c", ch);
if (i == *needed_cols) {
*needed_cols = (int)((*needed_cols) * 1.5);
b_row = (char*) realloc(*b_row, sizeof ( *b_row) * (*needed_cols));
}
b_row[i] = ch;
last=ch;
i++;
//scanf("%c",&ch);
}
if ((*needed_cols) && (i != *needed_cols)) {
return (INVALID_INPUT);
}
if (ch == EOF) {
return (S_EOF);
}
*needed_cols = i;
return (OK);
}
void alokuj_pole(int n, char *** pole)
{
*pole = (char**) malloc ( sizeof ( *pole ) * n );
}
void realokuj_pole(float n, float pomer, char *pole[])
{
n = (int)(n * pomer);
pole = (char**) realloc(pole, sizeof ( *pole) * n);
}
int main(int argc, char** argv) {
int velikost, i, i2, i3, vystup, needed_cols, last_needed_cols;
char ** matice;
velikost=10;
needed_cols=0;
//matice = (char *) malloc ( sizeof matice * velikost );
alokuj_pole(velikost, &matice);
i=0;
printf("Zadejte bludiste:\n");
while (vystup!=S_EOF || vystup!=INVALID_INPUT || vystup!=OUT_OF_MEMORY)
{
printf("Tohle probehlo: %d\n", i);
vystup=read_row(&needed_cols, &matice[i]);
last_needed_cols=needed_cols;
printf("matice polozka: %c\n", &matice[i]);
if (i==velikost) realokuj_pole(i, 2, matice);
i++;
}
if (vystup==INVALID_INPUT || vystup==OUT_OF_MEMORY)
printf("Nespravny vstup");
else if (vystup==S_EOF)
for(i2=0;i2<=i;i2++)
{
for(i3=0;i3<=last_needed_cols;i3++)
printf("%c", matice[i2][i3]);
printf(" \n");
}
}

Nahlásit jako SPAM
IP: 90.178.117.–
Fenry
~ Anonymní uživatel
24 příspěvků
5. 1. 2011   #2
-
0
-

Po prvním zběžném prolítnutí vidím 2 problémy.

Na řádku 55

char matice;

by mělo spíš být
char ** matice;


poté tedy na radku 57 musí být toto:
alokuj_pole(velikost, matice);


a na řádku 46 má být toto
pole = (char**) malloc ( sizeof ( *pole ) * n );


To jsou věci, které jsem viděl na první pohled, snad to k nakopnutí bude stačit, pokud ne, tak napište.

Nahlásit jako SPAM
IP: 89.176.51.–
KIIV
~ Moderátor
+43
God of flame
5. 1. 2011   #3
-
0
-

To Fenry : hlavne to chce pak taky alokovat jednotlive radky samostatne .. takhle bys alokoval jen pole ukazatelu na radky.. ale to nestaci

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Fenry0
Newbie
5. 1. 2011   #4
-
0
-

To KIIV : No pokud správně koukám, tak řádky si alokuje ve funkci read_row().

Nahlásit jako SPAM
IP: 89.176.51.–
Why0
Duch
5. 1. 2011   #5
-
0
-

Díky moc! Vypadá to, že se tím něco vyřešilo, bohužel ne všechno. Zmizely errory, takže se to už spustí, nicméně po zadání prvního řádku, to napíše chybu (něco, že segmentation fault, core dumped), takže to šahá někam, kam nemá přístup - a háže to error na řádky s implementací funkcí realokuj_pole a alokuj_pole (46 a 51), tak tam asi pořád někde chyběj nebo přebejvaj * ? Včera jsem to celou noc studoval, něco jsem už pochopil, ale v něčem pořád nemám tak uplně jasno, takže je to docela možný :( ... nenapadá vás něco? :) původní příspěvek jsem editoval na nový upravený kód.

Nahlásit jako SPAM
IP: 90.178.117.–
KIIV
~ Moderátor
+43
God of flame
5. 1. 2011   #6
-
0
-

no hadam ze to bude tim ze sice alokujes pole ukazatelu.. nicmene je to hodnotou predana promenna takze o tu alokovanou pamet prijdes :)

takze alokuj_pole(velikost, &matice);

void alokuj_pole(int n, char *** pole)

a v nem pak
*pole = (char**) malloc ( sizeof ( *pole ) * n );

Nahlásit jako SPAM
IP: 94.142.234.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Fenry0
Newbie
5. 1. 2011   #7
-
0
-

Kompletně zeditováno:
Nemáš inicializovanou proměnnou needed_cols

Edit: Dále na řádku 20 má být

b_row = (char **) malloc ( sizeof ( *b_row ) * n );

Nahlásit jako SPAM
IP: 89.176.51.–
Why0
Duch
5. 1. 2011   #8
-
0
-

Tak tomu nerozumím, obě ty vaše řešení odstranily warning při spouštění v netbeansech, ale pořád po zadání prvního řádku, to háže tu chybu, že to šahá kam nemá - a odkazuje mě to na řádek (tady 24), kde je tohle:

while ((ch != '\n') && (ch != EOF)) {

ale co tam může bejt špatně? Uvozovky jsem tam zkoušel dát i ", ale to by mělo bejt jedno...

Fenry napsal:
Nemáš inicializovanou proměnnou needed_cols


No, to mám na ř. 54, hned první řádek fce main, ne? :)

Kód jsem zas upravil do nejnovější podoby po vašich opravách...

Nahlásit jako SPAM
IP: 90.178.117.–
Fenry0
Newbie
5. 1. 2011   #9
-
0
-

na řádku 54 jsi proměnou needed_cols deklaroval, ale neinicializoval. Má tedy nedefinovanou hodnotu.

Nahlásit jako SPAM
IP: 89.176.51.–
Why0
Duch
5. 1. 2011   #10
-
0
-

Ajo, už jsem to tam přidal... no, ale chyba pořád stejná :( ještě jsem se to snažil trochu upravit, ale pořád nic :( jeden znak to ještě sní ale jakmile zadám dva a odentruju, hned error... a když dám jeden znak a odentruju, podruhý už to hodí error i po jednom dalšim... :(

Nahlásit jako SPAM
IP: 90.178.117.–
Why0
Duch
5. 1. 2011   #11
-
0
-

Tak už asi vím, v čem je problém, ale vůbec nevím proč!
Ono to totiž nečeká na vstup scanf, ani getchar. Hned po spuštění to desetkrát projede a vypíše to, co je na řádku 14 (dosadí pokaždý 3), 62 a 65, přičemž v 65 jako položku matice vypíše takový bílý políčko, přičemž samotnej cyklus na ř. 19, kterej je odpovědnej za uložení ze scanf to ani jednou neprojede :( Nevíte co tam je špatně?

Netbeansy ukazujou warning na ř. 19, 26, 28
Díky moc, T.

Nahlásit jako SPAM
IP: 90.178.117.–
Fenry0
Newbie
5. 1. 2011   #12
-
0
-

To Why : Pracuji na tom, buď ještě večer, nebo zítra ráno to sem postnu

Nahlásit jako SPAM
IP: 89.176.51.–
Fenry0
Newbie
6. 1. 2011   #13
-
0
-

To Why : Tak už to mám hotové. Je tam mnoho oprav, projdi si to řádek po řádku. Abych upozornil na nejzáludnější chyby:

řádek 13 - způsobí, že nebude možno načíst řádek delší než 3 znaky (podmínka ve funkci read_row() už v prvním volá ní po načtení čtvtého znaku způsobí ukončení funkce.

řádek 15 - má být *b_row ...

řádek 28 - má být (*b_row)[i] ...

řádek 60 - všude má být && namísto ||

k čemu je dobrý řádek 64? last_needed_cols se může zrušit a dále v souboru místo toho použít needed_cols

přikládám soubor, možná je v něm trochu rozházené odsazování, já to původně kopíroval tady ze stránek a trochu mi to blblo


Celé si to důkladně projdi

Edit: v tom přiloženém souboru na začátku main() inicializuj promennou vystup

vystup = 0;
nebo
vystup = OK;

Nahlásit jako SPAM
IP: 89.176.51.–
Why0
Duch
6. 1. 2011   #14
-
0
-

To Fenry :
Funguje! Moc díky :-)
Akorát jsem nepochopil pár věcí, např

int read_row(int *needed_cols, char ** b_row)

proč tam jsou dvě hvězdičky - mají v tom prsty ukazatele? :)

A jaktože tohle funguje, když to je typ int a pak tam ukládáš char? :)
    int ch;

ch = getchar();


A jak pak to velký pole můžu používat ve funkcích? Např nějakej znak změnit (aby se změnila i hodnota mimo funkci) a vypsat? :-) Udělal jsem to takhle, ale nějak to moc nefunguje...
v mainu:
vypis_matici(&matice,needed_cols,i);

fce:
void vypis_matici(char *** matice[], int *needed_cols, int *i)

{
int i2=0, i3=0;
*matice[0][0]='a'; // hypotetická změna třeba prvního prvku na něco jinýho
for(i2=0;i2<=*i;i2++)
{
for(i3=0;i3<=*needed_cols;i3++)
printf("%c", *matice[i2][i3]);
printf(" \n");
}
}


Ještě jednou díky moc, odhaduju, že na to, co jsi mi poradil bych přicházel ještě další tejden :-))

Nahlásit jako SPAM
IP: 90.178.117.–
Fenry0
Newbie
6. 1. 2011   #15
-
0
-

To Why : Jsem rád, že to pomohlo

int read_row(int *needed_cols, char ** b_row)

Hvězdičky znamenají, že druhý argument té funkce je ukazatel na ukazatel na char. Dalo by se to zapsat i takto:
int read_row(int *needed_cols, char *b_row[])
ale já raději používám tu první formu zápisu.

Ad getchar() a int:
funkce getchar vrací proměnou typu int. Přetypování na char se provede implicitně až na tomto řádku, závorky jsou nezbytné kvůli prioritě operátorů:
(*b_row)[i] = ch;

ASCII znaky se vejdou do nejnižších 7 bitů, takže při přetypování na char nedojde ke ztrátě informace

A ten poslední problém bych vyřešil následovně:

v main:
vypis_matici(matice,needed_cols,i);

a fce:


void vypis_matici(char ** matice, int nc, int i) {
int i2 = 0;
int i3 = 0;
matice[0][0] = 'a';
for(i2 = 0; i2 < i; i2++) {
for(i3 = 0; i3 < nc; i3++) {
printf("%c", matice[i2][i3]);
}
printf("\n");
}
}

Nahlásit jako SPAM
IP: 89.176.51.–
Why0
Duch
6. 1. 2011   #16
-
0
-

Ahá, už je mi to mnohem jasnější :-) ještě jednou díky

ad ten poslední problém:
Hodil jsem to tam, a nefunguje, prej je chyba na řádu volání tý fce a na řádku její definice s parametrama :(
//edit: tak v pohodě, jen jsem nevěděl, že funkce musí bejt deklarovaná dřív, než se volá, to mi nedošlo, v php to tak neni :-)


- a takže když ve fci to pole deklaruju jako ukazatel (char ** matice), tak ta funkce pak bude měnit i to pole se stejnym názvem, který je mimo tu funkci, jo?
// tím pádem u tohodle si můžu odpovědět sám, že ano :-)

Mno, tak jsem zvědavej, teď musím udělat BSF a zjistit nejkratší vzdálenost v bludišti, aby se sesbíraly všechny dostupný diamanty (*) :D

Nahlásit jako SPAM
IP: 90.178.117.–
Fenry0
Newbie
6. 1. 2011   #17
-
0
-

No názvy "matice" ve všech funkcích nejsou úplně dobře zvolené z hlediska didaktiky, protože každý z nich má rozsah platnosti pouze v tom bloku (funkci), kde je deklarován. Tudíž poslední funkci můžu stejně dobře napsat jako



void vypis_matici(char ** pole, int nc, int i) {
int i2 = 0;
int i3 = 0;
pole[0][0] = 'a';
for(i2 = 0; i2 < i; i2++) {
for(i3 = 0; i3 < nc; i3++) {
printf("%c", pole[i2][i3]);
}
printf("\n");
}
}

a opět to bude fungovat. Funkci se nepredava jmeno, nebo neco podobneho, ale ukazatel na tu matici.

Edit: ano, bude měnit to pole "matice"

Teď bych prozměnu chtěl o něco poprosit já tebe, učím se sám programovat v C/C++ ale chybí mi nějaké příklady, mohl by jsi mi tedy prosím do pošty hodit zadání té práce? Popřípadě i jiná pokud jich máš víc. Díky.

Nahlásit jako SPAM
IP: 89.176.51.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 38 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý