funkcja zwracająca mapę, co jest źle ?

0

funkcja ta ma zwrócić mapę typu row1, row2, lub row3 (row4 to tylko zmienna zdeklarowana, na wypadek jesli wcisniemy zly klawisz)
row1 itd zawieraja klawisz i dźwięk (klasa to_speaker).

 map<char, to_speaker > bito_blaster::gdzieTenKlawisz(char key){
	string tablica[3] = { "QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM" };
	if( tablica[0].find(key) < tablica[0].length() ){
		tekst->SetLabel("zwracam rząd 1 ");
		czy_dostepny = true;
		return row1;
	}
	else if( tablica[1].find(key) < tablica[1].length()){
		tekst->SetLabel("zwracam rząd 2 ");
		czy_dostepny = true;
		return row2;
	}
	else if( tablica[2].find(key) < tablica[2].length()){
		tekst->SetLabel("zwracam rząd 3 ");
		czy_dostepny = true;
		return row3;
	}
	else{
		tekst->SetLabel("UWAZAJ TEN KLAWISZ NIE JEST DOSTĘPNY !!! " );
		czy_dostepny = false;
		return row4;
	}
}

w innym miejscu programu w tej samej klasie napisałem funkcję, która jest podłączona z naciśnięciem klawisza .

void bito_blaster::onKeyDown(wxKeyEvent& event)
{	
	map< char, to_speaker > rowX = gdzieTenKlawisz( event.GetUnicodeKey() );
	rowX [ event.GetUnicodeKey() ].playIt();
}
 

Funkcja działa o tyle wadliwie, że odtwarza tylko dźwięki z row1, naciskajac klawisz z row2 lub 3 widać, że "gdzieTenKlawisz" zwraca row2 lub 3, bo ustawiłem w tej funkcji informacje do logowania jak widzicie. Natomiast odtwarzają się tylko klawisze z row1.
Jeśli w onKeyDown wpisałem row2[ event....].playIt() to grało mi normalnie dźwięki z row2.
Co robię źle?

0

Find zwraca -1 jeśli nie znajdzie znaku, więc Twój warunek z if() jest błędny. Powinno być:

if( tablica[0].find( key ) != -1 )
{
//reszta kodu
}
3
Hostel napisał(a):

Find zwraca -1 jeśli nie znajdzie znaku, więc Twój warunek z if() jest błędny. Powinno być:

if( tablica[0].find( key ) != -1 )
{
//reszta kodu
}

Mieszasz. std::string::find w przypadku niepowodzenia zwraca std::string::npos. I tego się używa. Jest to największa możliwa wartość dla typu std::size_t, który jest typem bez znaku. Podczas porównania, wartość signed zostanie skonwertowana na unsigned i skończy się tylko na ostrzeżeniu, ale taki kod jest zły.

Dodatkowo w kodzie OP to ma ogromne znaczenie. Ponieważ npos to nie jest -1 tylko jakaś bardzo duża liczba bez znaku, warunki są poprawne.

0

@Endrju Ty w ogóle upewniasz się czy inni dobrze piszą czy walisz minusy bo wiesz że dzwoni i uważasz że masz jedyną rację? Przeczytaj to:
http://www.cplusplus.com/reference/string/string/npos/

Napisz sobie jeszcze program i sprawdź czy npos == -1

2
Hostel napisał(a):

@Endrju Ty w ogóle upewniasz się czy inni dobrze piszą czy walisz minusy bo wiesz że dzwoni i uważasz że masz jedyną rację? Przeczytaj to:
http://www.cplusplus.com/reference/string/string/npos/

Napisz sobie jeszcze program i sprawdź czy npos == -1

Problem polega na tym, że Ty nie umiesz czytać. Co to jest std::size_t? To jest TYP BEZ ZNAKU jego wartość NIGDY NIE MOŻE BYĆ RÓWNA -1 Funkcja find NIE MOŻE ZWRACAĆ -1, BO ZWRACA TYP BEZ ZNAKU. Wyraźnie też napisałem co się dzieje podczas porównania i dlaczego to działa. Tak czy siak ten kod nie jest dobrym kodem C++, on co najwyżej działa, chociaż nie masz pojęcia jak (co udowodniłeś wyżej).

0

@Endrju przeczytałeś link, który podałem? npos jest stałą -1, którą nawet definiuje standard, tak więc find owszem zwraca npos ale przy porównaniu można ją zestawić z -1.

4
Hostel napisał(a):

@Endrju przeczytałeś link, który podałem? npos jest stałą -1, którą nawet definiuje standard, tak więc find owszem zwraca npos ale przy porównaniu można ją zestawić z -1.

Naucz się C++. Proszę!

Co się dzieję, kiedy napiszę:

unsigned int x = -1;

Czy x ma wartość -1? (Czy x jest stałą -1? Jak napisałeś) Problem polega na tym, że nie rozumiesz co robi ten kod tylko widzisz -1 i się uparłeś. Przemyśl to na spokojnie. Zdejmę Ci te minusy (słuszne, bo mieszasz i wprowadzasz w bląd), bo zachowujesz się jak dzieciak, który nie ma racji ale idzie w zaparte. Ochłoń i zastanów się co robi ten kod oraz kod OP.

OP nie ma takiego problemu właśnie dlatego, że to nie jest -1. Jego warunki są poprawne (chociaż troszkę dziwne) i działają. Nawet napisał w poście, że zwraca poprawnie.

0

@Endrju ma rację. W C# dałoby to inny wynik niż w C++ (automatyczna konwersja do long long int-a jeśli porównujesz signed int z unsigned int)

0

Dobra, ale co proponujecie w zamian w takim razie??
Dodam jeszcze, że skoro błąd jest w tym co mówicie, to czemu program na pozór poprawnie przeskakiwał po warunkach?
Podczas naciskania przycisku z każdego rzędu na ekranie wypisywał dobre napisy: "zwracam rząd 1, 2, 3 / błędny klawisz "

0
nikhatlak napisał(a):

Dobra, ale co proponujecie w zamian w takim razie??
Dodam jeszcze, że skoro błąd jest w tym co mówicie, to czemu program na pozór poprawnie przeskakiwał po warunkach?
Podczas naciskania przycisku z każdego rzędu na ekranie wypisywał dobre napisy: "zwracam rząd 1, 2, 3 / błędny klawisz "

Dlaczego literki nie są w jednej mapie? Nie widzę, żebyś wykorzystywał informację, który to rząd klawiszy. Doprecyzuj to.

To nie my mówimy tylko @Hostel i nie ma tam żadnego błędu - warunki są poprawne (dlaczego - napisałem wyżej). Z resztą sam widzisz, że są ok - zwracana wartość jest dobra. Skoro zwraca co ma zwracać, a coś się nie odtwarza, to problem tkwi w odtwarzaniu a nie tej funkcji.

0

Literki nie są w jednej mapie, ponieważ przy rozwijaniu programu mam zamiar uniezależnić te 3 rzędy literek od siebie.
funkcja "doprecyzowująca" to zapewne ta poniżej. Jest wykonywana w konstruktorze zawsze na początku programu - przyporządkowuje wszystkim klawiszom taki sam dźwięk.

 void bito_blaster::setDefaultSounds(){
	string klawisze = "QWERTYUIOP";
	for(int i=0; i<klawisze.length(); i++){
		row1[klawisze[i]] = to_speaker(char(klawisze[i]));
	}
	string klawisze2 = "ASDFGHJKL";
	for(int i=0; i<klawisze2.length(); i++){
		row2[klawisze[i]] = to_speaker(char(klawisze2[i]));
	}
	string klawisze3 = "ZXCVBNM";
	for(int i=0; i<klawisze3.length(); i++){
		row3[klawisze[i]] = to_speaker(char(klawisze3[i]));
	}
}

Informacje który to rząd klawiszy (został naciśnięty) wykorzystuję chociażby w wywołaniu funkcji "playIt" - wywoływuję ją na składniku takiej mapy którą zwraca f. "gdzieTenKlawisz()"

 map< char, to_speaker >
 rowX = gdzieTenKlawisz( event.GetUnicodeKey() );
rowX [ event.GetUnicodeKey() ].playIt();

a czy te dwie linijki same w sobie są poprawne?

1

W tej funkcji jest błąd. Zobacz drugą oraz trzecią pętlę:

row2[klawisze[i]] = to_speaker(char(klawisze2[i]));

Powinno być:

row2[klawisze2[i]] = to_speaker(char(klawisze2[i]));

Analogicznie w trzeciej.

Jeżeli będziesz mieć jedną mapę na wszystkie klawisze to przecież będziesz mógł tak samo przyporządkować każdemu klawiszowi inny dźwięk a kod będzie prostszy. Poza tym jak to teraz są to te same dźwięki? to_speaker ma zawsze inny argument.

0

Proponuję przeczytać ze zrozumieniem to co napisali na stronce z podanego linka:

This constant is defined with a value of -1, which because size_t is an unsigned integral type, it is the largest possible representable value for this type.

npos rzeczywiście inicjalizowany jest na -1, ale nie ma tej wartości. Nie może mieć tej wartości, bo -1 jest spoza zakresu typu size_t.
Przypisanie -1 do zmiennej bez znaku powoduje wpisanie tam jakiejś wielkiej liczby, zazwyczaj 4294967295, choć zależnie od kompilatora może być np. 65535 albo 18446744073709551615.

0

Endrju dzieki

1 użytkowników online, w tym zalogowanych: 0, gości: 1