Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno C++ - simulace obchodu na principu fronty

Ahoj! Tak jsme dostali zadání školního projektu, ze kterého nejsem moc chytrý :D Máme udělat simulaci obchodu na principu fronty, tj. mám zadán počet pokladen, počet zákazníků a max. počet položek, které můžou zákazníci koupit. Program má pak vypisovat u každého zákazníka "stav", tj. G"index""počet věcí co nakoupil" - po vygenerování, V"index""pokladna u které je nejkratší fronta - tam se zařadí""pořadí v té frontě", K"index""počet prvků co mu zbývá v košíku" - při každém průběhu hl. cyklu se za současného generování a zařazování nových zákazníků "odbaví" jedna položka z jeho nákupu. No a na závěr, po odbavení všech položek O"index""počet lidí, co zbývá ve frontě odkud zákazník odešel".

Myslím, že problém je v ukončovací podmínce hlavního cyklu, nebo u práce s hlavou fronty na konci programu - některé zákazníky mi to neodebírá a počítá s nimi dál, pak dochází k tomu, že se program ukončí předdčasně, aniž by všichni zákazníci odešli / jede do nekonečna / nevypisuje se nic (můj současný stav, ke kterému jsem po úpravách dospěl :D - to mě mate úplně, při krokování vidím, že program normálně pře výpisy jede, jen nic nevypisuje)...

Moc dík za veškeré rady, tady už fakt nevím :D

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

const int cashes = 5;
const int customers = 10;
const int max_items = 10;

struct cus{ //zakaznik
    int id;
    int items;
    cus *next;
};

struct queue{ //fronta
    cus *head, *tail;
    int size;
};

bool isEmpty(queue arr[]){ //kontrola pole, jestli je prazdne
    for(int i = 0; i < cashes; ++i){
       if(arr[i].size != 0){
            return false;
        }else{
            return true;
        }
    }
}

void init(queue arr[]){ //inicializace pole na zacatku

    for(int i = 0; i < cashes; ++i){
        arr[i].head = arr[i].tail = NULL;
        arr[i].size = 1;
    }

}

int main(){
    queue arr[cashes];
    init(arr);

    int total = 0; //poradi zakazniku

    srand(time(NULL)); //pro urceni nahodneho cisla nakupu

    while(isEmpty(arr) == false){

        //generovani noveho zakaznika
        if(total <= customers){
                cus *newC = new cus; //novy zakaznik
                newC->id = total;
                newC->items = rand() % (max_items + 1);

                cout << "G" << newC->id << "[" << newC->items << "]" << " ";

                ++total;


            //urceni nejkratsi fronty a zarazeni zakaznika
            int qMin = 0; //index nejkratsi fronty
            int lMin = arr[0].size; //delka nejkratsi fronty
            for(int i = 0; i < cashes; ++i){
                if(lMin > arr[i].size){
                    lMin = arr[i].size;
                    qMin = i;
                }
            }

            //zarazeni zakaznika na konec nejkratsi fronty
            cus *next_assist = new cus;

            if(arr[qMin].tail == NULL){
                arr[qMin].tail = newC;
            }else{
                arr[qMin].tail->next = newC;
            }

            //overim, jestli je head NULL
            if(arr[qMin].head == NULL){
                arr[qMin].head = arr[qMin].tail;
                arr[qMin].tail = NULL;
            }

            ++arr[qMin].size; //zvetsim velikost pole +1

            cout << "V" << newC->id << "[F" << qMin << "]" << " ";

        }

        //"odbaveni" zakaznika na pokladne
        for(int i = 0; i < cashes; ++i){ //prochazim pokladny a hledam, jestli je na headu hodnota - zakaznik
            if(arr[i].head != NULL){
                --arr[i].head->items; //odstranim polozku z kosiku
                if(arr[i].head->items >= 0){
                    cout << "K" << arr[i].head->id << "[" << arr[i].head->items << "] ";
                }/*else{
                    cout << "K" << arr[i].head->id << "[0] ";

                }*/
                    if((arr[i].head->items) == 0){
                        --arr[i].size;
                        cout << "O" << arr[i].head->id << "[F" << i << "]" << "[" << arr[i].size << "] ";

                       if (arr[i].head->next == NULL){
							arr[i].head = arr[i].head->next;
                        }
                    }
            }
        }
    }

    return 0;
}
Předmět Autor Datum
Opravdu nikdo neví? :D Trochu jsem to upravil a jsem ve stavu, že to probíhá, ale ne úplně - program…
Katsushiro 13.03.2013 16:30
Katsushiro
Ja momentalne nemam cas to studovat a neviem ci niekto na to najde cas, ale v prvom rade snad ked to…
MM.. 13.03.2013 17:22
MM..
Inac v C++ by som cakal triedy a OOP, a ne ze si v main testujes ci head je null, to je predsa zalez…
MM.. 13.03.2013 17:26
MM..
prvy bug if(arr[qMin].tail == NULL){ arr[qMin].tail = newC; }else{ arr[qMin].tail->next = newC; nec…
MM.. 13.03.2013 17:37
MM..
Jeden problem je v tomto if(arr[qMin].tail == NULL){ arr[qMin].tail = newC; }else{ arr[qMin].tail-…
MM.. 13.03.2013 17:47
MM..
A este toto je uplna hovadina cus *remove = new cus; remove = (cus *)&arr[i].head; naco robis no…
MM.. 13.03.2013 17:56
MM..
A este na zvysenie citatelnosti pouzivaj ++ a --, napr. arr[i].size = (arr[i].size - 1); je ar…
MM.. 13.03.2013 17:59
MM..
A este jeden problem tam vidim, a to ten ze ak vytvaras prve prvky v prazdnej fronte alebo ak ich ma…
MM.. 13.03.2013 18:08
MM..
... aby si mal predstavu tak ti to napisem, pri pridavani prvku musis nastavit vzdy aj next u kazdeh…
MM.. 13.03.2013 18:21
MM..
Strašně moc díky, už mi to funguje ;-) Jinak, původní kód jsem psal s asistencí jednoho známého, pro…
Katsushiro 15.03.2013 23:05
Katsushiro
OOP se tu nesmí používat He? Uz mi je asi jasne odkial MS bere tolkych ludi co potom robia ten dera…
MM.. 15.03.2013 23:19
MM..
Ono OOP přijde, ale zatím byl jenom zmíněn na přednášce, takže musíme projekt dělat jen s pomocí str…
Katsushiro 16.03.2013 00:30
Katsushiro
Ono sa to da urobit slusne aj so strukturami, mal si si urobit funkcie pridatprvok vymazatprvok tie…
MM.. 16.03.2013 01:09
MM..
Jo, tak to mě napadlo, až jsem měl napsanou většinu kódu a nechtělo se mi to měnit :D Tak mě napadá…
Katsushiro 17.03.2013 16:46
Katsushiro
Tak, tady je ten finální kód ;-) #include <iostream> #include <cstdlib> #include <ctime> using name… poslední
Katsushiro 21.03.2013 23:09
Katsushiro

Opravdu nikdo neví? :D Trochu jsem to upravil a jsem ve stavu, že to probíhá, ale ne úplně - program skončí a neodbaví všechny zákazníky...

#include <iostream>
//#include <stdio.h>
#include <cstdlib>
#include <ctime>

using namespace std;

const int cashes = 3;
const int customers = 5;
const int max_items = 3;

struct cus{ //zakaznik
	int id;
	int items;
	cus *next;
};

struct queue{ //fronta
	cus *head, *tail;
	int size;
};

bool isEmpty(queue arr[]){ //kontrola pole, jestli je prazdne
	for(int i = 0; i < cashes; ++i){
		if(arr[i].size == 0){
			return true;
		}else{
			return false;
		}
	}
}

void init(queue arr[]){ //inicializace pole na zacatku

	for(int i = 0; i < cashes; ++i){
		arr[i].head = arr[i].tail = NULL;
		arr[i].size = 0;
	}

}

int main(){
	queue *arr = new queue[cashes];
	init(arr);

	int total = 0; //poradi zakazniku

	srand(time(NULL)); //pro urceni nahodneho cisla nakupu

	do{

		//generovani noveho zakaznika
		if(total <= customers){
			cus *newC = new cus; //novy zakaznik
			newC->id = total;
			newC->items = rand() % (max_items + 1);

			cout << "G" << newC->id << "[" << newC->items << "]" << " ";

			++total;


			//urceni nejkratsi fronty a zarazeni zakaznika
			int qMin = 0; //index nejkratsi fronty
			int lMin = arr[0].size; //delka nejkratsi fronty
			for(int i = 0; i < cashes; ++i){
				if(lMin > arr[i].size){
					lMin = arr[i].size;
					qMin = i;
				}
			}

			//zarazeni zakaznika na konec nejkratsi fronty
			//cus *next_assist = new cus;

			if(arr[qMin].tail == NULL){
				arr[qMin].tail = newC;
			}else{
				arr[qMin].tail->next = newC;
				arr[qMin].tail = newC;
			}

			//overim, jestli je head NULL
			if(arr[qMin].head == NULL){
				arr[qMin].head = arr[qMin].tail;
				arr[qMin].tail = NULL;
			}

			arr[qMin].size+=1; //zvetsim velikost pole +1

			cout << "V" << newC->id << "[F" << qMin << "]" << " ";

		}

		//"odbaveni" zakaznika na pokladne
		for(int i = 0; i < cashes; ++i){ //prochazim pokladny a hledam, jestli je na headu hodnota - zakaznik
			if (arr != NULL && arr[i].head != NULL) {
				if (arr[i].head->items == 0){
				    cout << "O" << arr[i].head->id << "[" << arr[i].size -1 << "] ";
					cus *remove = new cus;
					remove = (cus *)&arr[i].head;
					arr[i].head = arr[i].head->next;
					delete remove;
					arr[i].size = (arr[i].size - 1);
				}else{
					arr[i].head->items = (arr[i].head->items - 1);
					cout << "K" << arr[i].head->id << "[" << arr[i].head->items << "] ";
				}
			}
		}
		//delete next_assist;
	}while(isEmpty(arr) == false);

	return 0;
}

Ja momentalne nemam cas to studovat a neviem ci niekto na to najde cas, ale v prvom rade snad ked to je tvoj program tak mas v hlave nejaky koncept ze co v ktorej premennej je a pri krokovani si snad pozeras tie premenne ze ci je v nich to co ocakavas a zistujes v ktorej neni to co ocakavas a nasledne sa zameras na to jak sa tam ta neocakavana hodnota dostala (pri dalsom krokovani od zaciatku, samozrejme pouzivas breakpointy a nekrokujes cely program po jednom riadku)

Ked ani sam nevies co kde ma byt tak bud si to nepisal ty, alebo program bez hlavy a paty (konceptu) mozes zmazat a zacat nanovo s nejakym konceptom v hlave alebo na papieri.
BTW. mimochodom u simulacii sa pocita aj s nahodnymi javmi (zakaznik sa nahodne rozhodne ze nejde do fronty najkratsej lebo je na druhom konci obchodu a vobec na nu nevidi) apod., neviem do akej miery po vas chcu v zadani nahodne javy apod.

Inac v C++ by som cakal triedy a OOP, a ne ze si v main testujes ci head je null, to je predsa zalezitost triedy fronta, ktora ma poskytovat metody "pridaj_prvok", "vyhod_prvok", apod., a ktora bude odladena tak aby tam nenastavali problemy. Tym si zancne zjednodusis main ktory bude logicky a prehladny a nebude problem tam najst chybu, atd. To je zakladny vyznam OOP.

prvy bug

if(arr[qMin].tail == NULL){
                arr[qMin].tail = newC;
            }else{
                arr[qMin].tail->next = newC;
nechces tu nastavit "tail" na ten novy prvok?
            }

P.S. jaj to uz si opravil v tom prispevku, takze odteraz pozeram len to co si sem dal v tom prispevku, ne v dotaze

Jeden problem je v tomto

			if(arr[qMin].tail == NULL){
				arr[qMin].tail = newC;
			}else{
				arr[qMin].tail->next = newC;
				arr[qMin].tail = newC;
			}

			//overim, jestli je head NULL
			if(arr[qMin].head == NULL){
				arr[qMin].head = arr[qMin].tail;
				arr[qMin].tail = NULL;
			}

a to ten ze ak si mal predtym head uz nastaveny a tail bol NULL, a pridavas tam prvok tak urobis len
arr[qMin].tail = newC;
a nenstavis head->next = newC, ak head neni null.
Cele to pridavanie prvku je chaoticky navrhnute, logicky rozmyslajuci clovek to snad napise od hlavy k pate, t.j.:

			// OD HLAVY
			if(arr[qMin].head == NULL){
				arr[qMin].head = newC;
			}else if(arr[qMin].tail == NULL){
				arr[qMin].tail = newC;
				arr[qMin].head->next = newC;
			}else{
			// K PATE :))
				arr[qMin].tail->next = newC;
				arr[qMin].tail = newC;
			}

A este toto je uplna hovadina

					cus *remove = new cus;
					remove = (cus *)&arr[i].head;

naco robis novy objekt pomocou new? A odkaz na neho si naveky prepises a teda ten novy objekt nikdy nezmazes? Testujes ze kedy ti dojde cela volna RAM? :)
A ten druhy riadok je tiez nezmysel, uvolnujes uplnu hovadinu. V head mas predsa pointer.

T.j. spravne ma byt

					cus *remove;
					remove = arr[i].head;

A este jeden problem tam vidim, a to ten ze ak vytvaras prve prvky v prazdnej fronte alebo ak ich mazes, tak nikde nenastavujes ->next=NULL, to ale musis robit, inac tam budes mat nahodne alebo neplatne adresy a program ti crashne s exception (program proved neplatnou operaci) v urcitych situaciach. To sa mi uz nechce teraz osetrovat to si urob sam.
Kazda operacia s frontou musi nastavovat vsetky premenne prvkov fronty spravne (tie ktore sa menia samozrejme), za kazdych okolnosti aj ked je to uz posledny prvok atd, preto som aj pisal ze je lepsie ak je to extra v triede s privatnymi head a tail a next, a ked robis tu triedu tak sa sakramentsky zamyslis nad tym aby si inicializoval a spravne nastavil vsetko za kazdej situacie.

... aby si mal predstavu tak ti to napisem, pri pridavani prvku musis nastavit vzdy aj next u kazdeho aj u noveho prvku

			if(arr[qMin].head == NULL){
				arr[qMin].head = newC;
				arr[qMin].head->next = NULL;
			}else if(arr[qMin].tail == NULL){
				arr[qMin].head->next = newC;
				arr[qMin].tail = newC;
				arr[qMin].tail->next = NULL;
			}else{
				arr[qMin].tail->next = newC;
				arr[qMin].tail = newC;
				arr[qMin].tail->next = NULL;
			}

- to sa dalo nastavit aj predtym raz ako newC->next=NULL, aby to tam potom nemuselo byt 3x :)
pri odstranovani tiez treba osetrit vsetky situacie

					cus *remove;
					remove = arr[i].head;
					arr[i].head = arr[i].head->next;
					delete remove;
					if(arr[i].head == arr[i].tail){
					    arr[i].tail = NULL;
					}
					arr[i].size--;

myslim ze som tym vystihol vsetky mozne siutuacie

Strašně moc díky, už mi to funguje ;-) Jinak, původní kód jsem psal s asistencí jednoho známého, protože ve škole se to tak nějak proletělo a pointery mi nebyly moc jasné... Jo a OOP se tu nesmí používat, fakt jenom struktury :D Jakmile bude pondělí, tak pokud to bude dobře, mrsknu tu celý kód, třeba to někomu pomůže :-)

Ono sa to da urobit slusne aj so strukturami, mal si si urobit funkcie pridatprvok vymazatprvok tie by sa zaoberali len tou FIFO frontou t.j. len tymi 3 premennymi v strukture takze pri tvorbe tych fcii sa clovek moze zamerat len na tie 3 premenne v strukture a urobit tie 2 funkcie dokonale. Potom samozrejme vo vacsom/zlozitejsom programe by boli tie funkcie volane aj viackrat, preto su nakoniec v zlozitom programe tie funkcie aj nutne. Hlavny program by bol prehladny (malo riadkov - len volania funkcii) a citatelny.

Ono OOP trieda neni nic ine len sada struktur a funkcii, len je to v OOP trochu syntakticky (opticky) uhladenejsie aby to bolo lepsie a jednoduchsie citatelne.

Tak, tady je ten finální kód ;-)

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

const int N = 3; //pocet pokladen
const int M = 2; //pocet zakazniku
const int P = 3; //max. pocet polozek v nakupu

struct cus{ //zakaznik
	int id;
	int items;
	cus *next;
};

struct queue{ //fronta
	cus *head, *tail;
	int size;
};

bool isEmpty(queue arr[]){ //kontrola pole, jestli je prazdne
	int sum = 0; //pocet prazdnych front
	for(int i = 0; i < N; ++i){
		if(arr[i].size == 0){
			sum++;
		}
	}
	if(sum == N){
		return true;
	}
	return false;
}

void init(queue arr[]){ //inicializace pole na zacatku

	for(int i = 0; i < N; ++i){
		arr[i].head = arr[i].tail = NULL;
		arr[i].size = 0;
	}

}

int main(){
	queue *arr = new queue[N];
	init(arr);

	int total = 1; //poradi zakazniku

	srand(time(NULL)); //pro urceni nahodneho cisla nakupu

	do{

		//generovani noveho zakaznika
		if(total <= M){
			cus *newC = new cus; //novy zakaznik
			newC->id = total;
			newC->items = rand() % P + 1;

			cout << "G" << newC->id << "[" << newC->items << "]" << " ";

			++total;


			//urceni nejkratsi fronty a zarazeni zakaznika
			int qMin = 0; //index nejkratsi fronty
			int lMin = arr[0].size; //delka nejkratsi fronty
			for(int i = 0; i < N; ++i){
				if(lMin > arr[i].size){
					lMin = arr[i].size;
					qMin = i;
				}
			}

			//zarazeni zakaznika na konec nejkratsi fronty
			if(arr[qMin].head == NULL){
				arr[qMin].head = newC;
				arr[qMin].head->next = NULL;
			}else if(arr[qMin].tail == NULL){
				arr[qMin].head->next = newC;
				arr[qMin].tail = newC;
				arr[qMin].tail->next = NULL;
			}else{
				arr[qMin].tail->next = newC;
				arr[qMin].tail = newC;
				arr[qMin].tail->next = NULL;
			}

			arr[qMin].size++; //zvetsim velikost pole +1

			cout << "V" << newC->id << "[F" << qMin << "]" << " ";
		}

		//"odbaveni" zakaznika na pokladne
		for(int i = 0; i < N; ++i){ //prochazim pokladny a hledam, jestli je na headu hodnota - zakaznik
			if (arr != NULL && arr[i].head != NULL) {
				if (arr[i].head->items == 0){

					cout << "O" << arr[i].head->id << "[" << arr[i].size -1 << "] ";

					arr[i].head = arr[i].head->next;
					if(arr[i].head == arr[i].tail){
					    arr[i].tail = NULL;
					}

					arr[i].size--;
				}else{
					arr[i].head->items--;
					cout << "K" << arr[i].head->id << "[" << arr[i].head->items << "] ";
				}
			}
		}
	}while(isEmpty(arr) == false);

	cout << endl;
	delete []arr;
	return 0;
}

Zpět do poradny Odpovědět na původní otázku Nahoru