» »

[C++][naloga]strukture, delo s tekstom in datotekami

[C++][naloga]strukture, delo s tekstom in datotekami

Dr_S ::

Pozdravljeni

Imam za narest 3 različne programe v C++ in vas prosi če mi malce namignete kako naj rešim te naloge.

1) Napišite strukturo Ulomek. Napišite funkcijo za seštevanje dveh ulomkov (rezultat je tudi ulomek). S pomočjo te funkcije izdelajte funkcijo "Vsota vrstic", ki prejme 2D polje ulomkov in izpiše vsoto vseh ulomkov v vsaki vrstici polja.

2) Napišite program, ki izpiše vhodno tekstovno datoteko na zaslon tako, da število črk v vrstici ne preseže n znakov. Besedo, ki se ne more v celoti izpisati v trenutni vrstici, pomaknemo na začetke naslednje.

3)V trgovskem centru je lahko več trgovin. V Sloveniji pa je lahko več trgovskih centrov. Sestavite strukturi trgovina in trgovski center ( napišite 5 podatkov). Uporabite dvosmerno dinamično povezan seznam. Izdelajte funkcijo, ki "ponazori" selitev določene trgovine (vhodni podatek v funkcijo) iz enega trgovinskega centra v drugega ( tudi to sta vhodna podatka).

Lp

[edit: "Prošnja za pomoč" je malo preveč obsežen naslov, poleg tega za v prihodnje preberi pravila glede imenovanja tem]
  • spremenil: Gundolf ()

Gundolf ::

Naj ti namignem kako rešiti tele naloge?

Uporabi keyworde struct/class.
Za delo s tekstom uporabi strukturo string (za vključitev teh funkcij rabiš vključiti header string -> #include <string>), za branje/pisanje datotek rabiš header fstream. Če funkcij, ki jih najdeš v teh dveh headerjih, še ne poznaš, ti priporočam da si jih malo pogledaš - da ugotoviš kaj vse ti je na voljo za programiranje.

Dr_S ::

Prvo nalogo sem nekak spacal skupaj.
Pri drugi pa imam problem, ker mi noče ponavljati zanke oz ne gre do konca datoteke.

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;

int main()
{	string vrstica;
	int stZnakov,Skoz,temp;
	int i=0;
	cout<<"Vpisi stevilo znakov"<<endl;
	cin>>stZnakov;
	Skoz=stZnakov;
	
	ifstream datoteka ("naloga2.txt");
	
	if (datoteka.is_open())
	{
	while (!datoteka.eof())
	getline(datoteka,vrstica);
	{	
	while (vrstica[stZnakov]!=' ')
		    stZnakov--;
			temp=stZnakov;
			{for (i;i<stZnakov;i++)
			   cout<<vrstica[i];}
			cout<<endl;
			stZnakov=stZnakov+Skoz;
			i=temp;
	}
	datoteka.close();
	}
	else cout<<"Ne morem odpreti datoteko"<<endl;
	system("PAUSE");
return 0;	
}

Zgodovina sprememb…

  • spremenil: Dr_S ()

Gundolf ::

Najprej: cout<<"Ne morem odpreti datoteko"<<endl; Na živce mi gre kadar ljudje ne znajo uporabit tožilnika. :P

Ok, zdaj ko sem dal to iz sebe pa k nalogi. Po moje sta problema vsaj dva.

Prvi: spremenljivko i initializiraš le enkrat uporabljaš pa jo mnogokrat (in vsakič računaš na to, da je na začetku 0, pa ni). Torej prvi nasvet je, da ne našteješ vseh spremenljivk na začetku funkcije ampak točno tam, kjer jih rabiš. Torej spremenljivko i definiraš kar znotraj for zanke, in tudi začetno vrednost 0 ji daš tam. Spremenljivko temp definiraš tudi tam, kjer jo prvič uporabiš torej takole: int temp=stZnakov; In tako dalje z vsemi spremenljivkami.

Naslednji problem pa se nanaša na tvoj način definicije 'scopa' za for in while zanko, Ti si napisal {for(...) naredi_nekaj;} kar ni tisto kar hočeš napisat ampak v tem primeru slučajno deluje. V primeru while zanke pa niti približno ne deluje. Kar ti hočeš napisat je tole: for(...) {naredi nekaj; naredi_se_nekaj; pa_se_nekaj;}. Isto za while zanko. Oziroma isti sistem kot ga pravilno uporabljaš v if stavku: if (...) {naredi_nekaj; pa_se_nekaj;}

bozjak ::

ok, ti bom jst pa še mal za tretjo namignu:

rabš dinamični seznam... Če ti ta dela probleme mal pobrskej po forumu, je temu namenjen najmanj en zlo obsežen topik.

potem moraš sestavt še 2 strukturi, torej trgovina in trgovinski center, s tem da (vsaj kokr sm jst razumel nalogo, mora imeti trgovinski center vklučen dinamičen seznam trgovin...

funkcija selitev pa mora narediti samo to, da v dinamičnem seznamu premakne eno trgovino v drug dinamičen seznam, oziroma jo vrine nekam drugam v istem seznamu... Če ti dela premikanje in zastavljanje seznamov probleme, si najprej napiši z omejenimi vrednostmi, in ko bo delal tako da boš meu npr. 20 trgovinskih centrov in vsak ima lahko npr 20 trgovin (pač kerokol omejeno število) in boš potem že "prepisal" s pomočjo dinamičnih seznamov...

Lp

ziga321 ::

za drugo nalogo sem malo napačno razumel...

V bistvu imam rešitev že rešeno, me pa zanima kako bi drugi to nalogo rešili, tak da dejte prosim povedat:)

Zgodovina sprememb…

  • spremenil: ziga321 ()

Gundolf ::

:D Dober prijem ziga, ni kaj.

ziga321 ::

hehe, menda ne misliš da bom izdal svojo skrivnost na katero sem še posebej ponosen :D ?

ok naj vam bo:

stvar sem rešil s kazalci. Enega sem postavil na začetek vrstice drugi kaže na zadnji space v trenutni vrstici tretji pa bere dejansko iz datoteke in je na zadnjem mestu.. Funkcija oz. bolje rečeno for zanka se zaključi ko pride do največjega števila znakov ki jih hočeš izpisati ali do newline karakterja..

stvar se potem izpiše od začetnega do drugega kazalca - torej tisti ki kaže na space..

Samo da prosim slišim še vaša mnenja kak bi sami stvar rešili..

Gundolf ::

No sej to je to ziga, dosti bolje od tega ne gre. Kvaliteta rešitve je potem odvisna le še od tega kako najdeš tisti zadnji presledek v vrstici in kaj narediš s posebnimi primeri (recimo, ko je beseda (npr. URL) daljša od max dolžine vrstice).

Dr_S ::

A potem bi bilo bolše da to nalogo rešim s kazalci?

Drugače sem mislil, če se da datoteko kako "prepisati" v polje in bi potem kar po polju pač gledal koliko črk oz znakov moram izpisati in kje je presledk.

Drugače sem pa i dal na začetku na 0, ker je to pač začetek datoteke, i pa potem dobi vrednost temp, ki pa je na zadnjem presledku, ki ga še napišemo v eno vrstico.
Potem pa sem mislil da pač z for zanko izpisuje znake, vse do konca datoteke.

Vse kar naredi program pa je da napiše eno vrstico znakov ki jo določi uporabnik, potem pa konča :\

Bom se še mal ukvarjal, kaj pa kako.

Hvala za enkrat

Gundolf ::

> A potem bi bilo bolše da to nalogo rešim s kazalci?
Ne, kazalci nimajo prav nič pri tem. Ali si s kazalcem zapomniš kje je zadnji presledek - kot ziga ali pa z indexom - kot delaš ti . Je čisto isto. Tudi ni razlike (morda je le razlika v hitrosti izpisovanja v konzoli) ali izpisuješ sproti besedo po besedo kot ti delaš ali pa izpišeš eno vrstico naenkrat. Pri tebi je le problem ker ne pišeš pravilno zank. Ja tisto z i-jem - moja napaka, je pravilno (v primeru da zanke popraviš). Prej nisem dovolj pozorno pogledal. Sem že preveč navajen 'običajne' rabe zank in indexov v njih pa mi možgani takoj ko ne prepoznajo standardnega vzorca rečejo "tole je pa narobe" :D

Dr_S ::

No zdej sem z eno salamonsko rešitvijo uspel da mi izpisuje vse dokler ni stZnakov večji od vseh znakov v datoteki.
tale pogoj morm mal drugač nastavit pomoje:

while (vrstica[stZnakov]!=' ')

Ve kdo rešitev?

Zgodovina sprememb…

  • spremenil: Dr_S ()

ziga321 ::

No sej to je to ziga, dosti bolje od tega ne gre. Kvaliteta rešitve je potem odvisna le še od tega kako najdeš tisti zadnji presledek v vrstici in kaj narediš s posebnimi primeri (recimo, ko je beseda (npr. URL) daljša od max dolžine vrstice).
-------------------------------------------
brez problema bi ti poslal celotno rešitev če ne bi bil vezan na službo kjer sem konec koncev to stvar na isti način rešil zato bi bil tudi vesel če bi kdo najdel še kako bolj preprosto rešitev. Brez problema pa lahko povem:Tiste presledke iščeš enostavno z zadnjim kazalcem(npr.da mu rečemo kazalec s št.3) ki edini išče po nizu posamezne znake. Ko pride do presledka kazalec št.2 enostavno postaviš na njegovo mesto in to je to. Kazalec št. 3 gre potem naprej.

Če je beseda daljša od max.dolžine se da to enostavno rešiti z if stavkom:

if(k_string2 == k_string1) // kazalec št.2 se v tem primeru enostavno ne premakne
k_string2 = k_string3;

in potem stvar posnamemo normalno od k_string1 do k_string2
Še en primer je lahko: Npr. da bi imel eno zelo kratko besedo in eno zelo dolgo. V tem primeru bi se ti kratka izpisala v eni vrstici in dolga v drugi kar bi bilo na račun izredno veliko praznega prostora. Nič lažjega.

if(k_string2 - k_string1 < n) //k_string2 je v tem primeru še bolj pri začetku
k_string2=k_string3;
n je lahko neko poljubno število.. npr.5
kar sem še pozabil...

Zgodovina sprememb…

  • spremenil: ziga321 ()

ziga321 ::

no še nekaj sem pozabil. V tem primeru ki sem ga napisal zgoraj ti besedo(URL) enostavno prereže na dva dela. Vendar je definitivno tole s kazalci ena najbolj preprostih rešitev.

Gundolf ::

Dr_S, dodaj pogoj da mora biti stZnakov > 0. In potem ko izpisuješ poglej če je stZnakov > 0, potem izpiši toliko kolikor si jih naštel, če je pa stZnakov 0, potem pa obdelaj ta primer kakor ti paše.

> brez problema bi ti poslal celotno rešitev
Sej si dobro povedal kako ti deluje. Jaz rešitve tudi ne rabim, če te bo pa kdo drug prosil pa po želji.

Dr_S ::

No sedaj sem naredil še nalogo s strukturami.

Dela mi celoten program (vpis podatkov, izpis vsega seznama, izpis določenega elemnta v seznamu ...)

Vendar pri brisanju določenega elementa (to je vhodni podatek) se mi malce zatakne :\

Ko kličem funkcijo izbris elementa, mi pregleda cel seznam, izbriše iskani element, preveže vse med seboj (vsaj upam), potem pa ko po končani funkciji, pokličem funkcijo za Izpis celega seznama ( kar je še ostalo ) pa mi v debugerju pokaže da je kar prazen seznam in seveda pol štekne izvedba.

Tule je funkcija, pa mi povejte če je kaj narobe nastavljeno, jst ne vidim rešitve :'(

void IzbrisAvta(tipAvta* prvi)
{	tipAvta *temp, *pom;
	int st;
	cout<<"Izbrisem avto, ki ima koliko sedezev:  "; //pogoj za brisanje 
	cin>>st;

        while (prvi!=NULL) //dokler ni konec seznama
        {
		
	if (prvi->stevilo_sedezev==st)  // ce je iskani element na zacetku seznama
	{
	     pom=prvi->nasl;
	     delete(prvi);
	     prvi=pom;
	}
			
	if ((prvi->nasl==NULL)&&(prvi->stevilo_sedezev==st)) // na koncu seznama
	{
	    while (pom->nasl!=prvi)
	    pom=pom->nasl;
	    delete(prvi);
	    pom->nasl=NULL;
	}
			
	if (prvi->nasl!=NULL)&&(prvi->stevilo_sedezev==st)) // ce je nekje vmes
	{
	   while (pom->nasl!=prvi)
	   pom=pom->nasl;
	   pom->nasl=prvi->nasl;
	   delete(prvi);
	   prvi=pom->nasl;
	}
      prvi=prvi->nasl;
     }
}


Torej, pri debug-anju mi lepo pregleda cel seznam, vendar potem ko pokličem funkcijo za izpis celega seznama, je kao seznam prazen.
Ne vem kaj narest da bo po klicu funkcije za izpis kazalec na začetku seznama, ki je še ostal po brisanju določenega elementa.

Lp

Zgodovina sprememb…

  • spremenil: Dr_S ()

bozjak ::

hmm ne vem ce je to krivo (sm sam na hitr preletu kodo) ampak za vsmi while-i ti mankajo bloki... In pol while izvaja samo prvo vrstico dokler je pogoj true...

Drugač pa se mi zdi da si tole fuuul preveč zakomplicirov... Ce bom meu zvecer cajt bom napisov kej bl simple...

Lp

krneki0001 ::

Imam narejene vse tri programe, če rabiš pošlji zasebno sporočilo, pa ti pošljem po mailu. Vse to smo delal na feriju pri predmetu programiranje 1.

A se slučajno učiš za ta predmet?

Gundolf ::

Kot je ze Bozjak reku, tole je očitno preveč komplicirano.
Poleg tega je ena napaka očitna: pomisli kaj se zgodi, če prvi avto v seznamu ustreza pogoju za brisanje - ti ga izbrišeš, ampak izven funkcije ti pa začetek seznama še kar naprej kaže nanj. Kot imaš trenutno definirano funkcijo (da po vrednosti vzame prvi element seznama), z njo nikakor ne moreš spremeniti (recimo ga zbrisati in da potem nek drug element zasede prvo mesto) prvega elementa.
void IzbrisAvtaPoStSedezev(tipAvta*& prvi, int st) { 
// branje stevilke sedezev sem vrgel ven iz funkcije,
// iz imena funkcije naj pa se vidi kaj tocno dela
// 'prvi' je popravljen tako, da mu lahko varno popraviš vrednost
   tipAvta start;     // ustvari se 'lokalni' seznam, ki bo imel en element vec in sicer na zacetku
   start.nasl = prvi; // prvi element podanega seznama bo postal drugi element lokalnega seznama

   // sprehodis se po lokalnem seznamu od drugega elementa do konca
   for (tipAvta *temp = prvi, *prejsnji = &start; temp != NULL; temp = temp->nasl) {
      if (temp->stevilo_sedezev == st) {
         // prvi je vedno veljaven ker se je zanka zacela pri drugem elementu
         prejsnji->naslednji = temp->naslednji;
         delete(temp);
         temp = prejsnji; // na koncu zanke (pred naslednjo iteracijo mora temp kazati na veljaven
                          // element, ki ne izpolnjuje pogoja za brisanje, in to je 'prejsnji')
      }
      prejsnji = temp; // tole sem prej pozabil in je zelo pomeembno :)
   }
   prvi = start.nasl; // pravi prvi element je drugi element lokalnega seznama, za vsak slucaj 
                      // mu na novo nastavis (ce je bil prejsnji prvi izbrisan)
}

Tako nekako bi lahko izgledala koda (tole sem na pamet spisal, tako da ne zaupam čisto kodi).

[edit: prejsnji = temp; <- tole vrstico sem pozabil ko sem pisal program (ni nujno da je to edina napaka)]

Zgodovina sprememb…

  • spremenil: Gundolf ()

Dr_S ::

@NEBIVEDU Imaš zasebno sporočilo. Hvala. Se učim za isti predmet. ;((


@bozjak

Za vsemi while sem dal namerno brez {} ker ta while je zato da premika pom1 kazalec, ko iščem iskani element, da potem prevežem seznam med samo, ko izbrišem element.

@Gundolf

Tvojo rešitev bom še pregledal. Vem da je napaka če je v seznamu samo en element in ta ustreza pogoju za brisanje. Sam to sem rekel bom pol reševal, ko mi bo izpisalo preostanek seznama :)

'FireSTORM' ::

Pri drugi pa imam problem, ker mi noče ponavljati zanke oz ne gre do konca datoteke.


while (!eof(datoteka)) { bla }


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[C++] Naloge

Oddelek: Programiranje
273850 (2181) LordiBoy
»

Naloga iz Putka - UPM

Oddelek: Programiranje
242058 (1394) NejcSSD
»

[C] Vsota števil v polju

Oddelek: Programiranje
51182 (1120) Cvenemir
»

[C++] Brisanje znaka iz stringa

Oddelek: Programiranje
5910 (813) mm1992
»

[C++][Naloga_polja]MIN in MAX polja, izpis za x.100 stevil

Oddelek: Programiranje
222823 (2634) snow

Več podobnih tem