Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Ify na tablicy char

Ostatnio zmodyfikowano 2016-12-03 17:28
Autor Wiadomość
kilopierogow
Temat założony przez niniejszego użytkownika
[C++] Ify na tablicy char
» 2016-12-03 01:33:29
Witam ponownie,
To jeden z algorytmów nad którym pracuję. Użytkownik wpisuje wielokrotność 4 znakowej komendy w postaci [1-5][1-5]![litera(tu w)]
Oczywiście po poprawnym wpisaniu powinien wyświetlić się komunikat, co jeszcze mi się nie zdarzyło. Jakieś sugestie?
Pozdrawiam.
C/C++
#include <iostream>
#include <iomanip>
#include <cstdlib>

using namespace std;

int main()
{
    int wielkosc = 7;
    char komenda[ 6 ];
   
    for( int i = 0; i < 6; i++ )
         komenda[ i ] = '0';
   
    cin.clear();
    cin.getline( komenda, 6 );
   
    for( int i = 0; i < 6 && komenda[ i ] != '\0'; i++ )
    {
        int dobrze = 0;
       
        if( komenda[ i ] == 'w' || komenda[ i ] == 'W' )
        {
            if( komenda[ i - 1 ] == '!' )
            {
                char wspolrzedna = komenda[ i - 2 ];
                int wsp = wspolrzedna - '0';
               
                if( wsp > 0 && wsp <( wielkosc - 1 ) )
                {
                    char wspolrzedna2 = komenda[ i - 3 ];
                    int wsp2 = wspolrzedna2 - '0';
                    if( wsp2 > 0 && wsp2 <( wielkosc - 1 ) )
                    {
                        if( komenda[ i - 4 ] == ' ' || komenda[ i - 4 ] == '/0' )
                        {
                            cout << "spelnione";
                            dobrze = 1;
                        }
                    }
                }
            }
        }
    }
   
    return 0;
}
P-154429
carlosmay
» 2016-12-03 08:40:10
C/C++
if( komenda[ i - 1 ] == '!' )
Tutaj masz wyjście poza tablicę dla i == 0 i w każdym zagnieżdżeniu instrukcji
if
 jest coraz gorzej.

Zamiast męczyć się z tablicą
char
 zastosuj
std::string
 lub kontener
std::vector
.

Użytkownik wpisuje wielokrotność 4 znakowej komendy w postaci [1-5][1-5]![litera(tu w)]
Rozwiń to. Podaj przykład, jakie dane wpisujesz.
Jeśli w kodzie jest aż tyle zagnieżdżeń instrukcji
if
, kod wymaga przemyślenia.
Ogólnie drugie zagnieżdżenie jest już słabo czytelne, a co dopiero pięć.

Sprawdzeniem poprawności współrzędnych (komendy) powinna zająć się osobna funkcja.

int dobrze = 0;
zamień na
bool czyDobrze = false;
.
To jest dużo czytelniejsze.
P-154430
mokrowski
» 2016-12-03 13:07:01
Jeśli już chcesz _koniecznie_ robić to na tablicy znaków, proponuję for(...) realizować od ostatniego znaku komendy i w pętli sprawdzić czy: (ostatni znak to 'w' lub 'W') oraz (przed_ostatni znak to '!'). Pobranie współrzędnych będzie wtedy związane wyłącznie z przetworzeniem znaków na wartość int.
Jeśli jednak nie chcesz popełniać błędów jakie masz w tym kodzie (wyjście poza tablicę), możesz to zrobić tak... taki kod "na szybko" ...
C/C++
#include <string>
#include <iostream>

using namespace std;

string czytaj_komende()
{
    string komenda;
    cin >> komenda;
    return komenda;
}

bool to_komenda_w( const string & komenda )
{
    if( komenda.size() < 4 )
    {
        cerr << "Komenda ma nieodpowiednią długość!" << endl;
        return false;
    }
   
    auto komenda_riter = komenda.rbegin();
    auto ostatni_znak = * komenda_riter;
    auto przed_ostatni_znak = *( ++komenda_riter );
    return(( ostatni_znak == 'w' ) or( ostatni_znak == 'W' ) ) and( przed_ostatni_znak == '!' );
}

using wspolrzedne_t = pair < int, int >;

wspolrzedne_t daj_wspolrzedne( const string & komenda )
{
    // A tak nietypowo :-) Konwersja do liczby i wyłuskanie 2 współrzędnych...
    auto wartosc = stoi( komenda );
    return make_pair( wartosc / 10, wartosc % 10 );
}

bool spelnia_warunek_w( const wspolrzedne_t & wspolrzedne )
{
    // FIXME: Nie wiem czy chodziło Ci o wyłącznie sprawdzenie czy 2 liczby są z zakresu [1-5]?
    return( wspolrzedne.first <= 5 ) and( wspolrzedne.first >= 1 )
    and( wspolrzedne.second <= 5 ) and( wspolrzedne.second >= 1 );
}

int main()
{
    auto komenda = czytaj_komende();
    if( to_komenda_w( komenda ) ) {
        if( spelnia_warunek_w( daj_wspolrzedne( komenda ) ) )
             cout << "spełnione" << endl;
       
    }
}
P-154438
kilopierogow
Temat założony przez niniejszego użytkownika
» 2016-12-03 14:51:09
Przykłady komend :
13!d 25!A 32!s
itd.
4 znak to litery "wWaAsSdD", komendy użytkownik rozdziela pojedynczą spacją.
1-5 akurat w tym przypadku, ale wcześniej wielkosc=7 jest zmienną (ograniczyłem to na potrzeby fragmentu). Ogólny wzór to cyfry mają być z przedziału od zera(bez zera) do wielkosc-1(bez tej wartosci). Dla wielkosc=7 jest to 1-5.

Co do odp. od mokrowski, nie mogę posługiwać się "auto" (podstawowy Code Blocks bez C++11), chociaż kod mi się podoba (ale wywala error przy kompilacji 'stoi' was not declared in this scope (?)).
Dzięki za odpowiedzi.
Pozdrawiam.
P-154444
mokrowski
» 2016-12-03 16:05:44
Oj tam.. mówisz i masz.. zgodne z kompilatorami "przed c++11"
C/C++
#include <string>
#include <iterator>
#include <iostream>

using namespace std;

string czytaj_komende()
{
    string komenda;
    cin >> komenda;
    return komenda;
}

bool to_komenda_w( const string & komenda )
{
    if( komenda.size() < 4 )
    {
        cerr << "Komenda ma nieodpowiednią długość!" << endl;
        return false;
    }
   
    string::const_reverse_iterator komenda_riter = komenda.rbegin();
    char ostatni_znak = * komenda_riter;
    char przed_ostatni_znak = *( ++komenda_riter );
    return(( ostatni_znak == 'w' ) or( ostatni_znak == 'W' ) ) and( przed_ostatni_znak == '!' );
}

typedef pair < int, int > wspolrzedne_t;

wspolrzedne_t daj_wspolrzedne( const string & komenda )
{
    // A tak nietypowo :-) Konwersja do liczby i wyłuskanie 2 współrzędnych...
    int wartosc = atoi( komenda.c_str() );
    return make_pair( wartosc / 10, wartosc % 10 );
}

bool spelnia_warunek_w( const wspolrzedne_t & wspolrzedne )
{
    // FIXME: Nie wiem czy chodziło Ci o wyłącznie sprawdzenie czy 2 liczby są z zakresu [1-5]?
    return( wspolrzedne.first <= 5 ) and( wspolrzedne.first >= 1 )
    and( wspolrzedne.second <= 5 ) and( wspolrzedne.second >= 1 );
}

int main()
{
    string komenda = czytaj_komende();
    if( to_komenda_w( komenda ) ) {
        if( spelnia_warunek_w( daj_wspolrzedne( komenda ) ) )
             cout << "spełnione" << endl;
       
    }
}
P-154445
kilopierogow
Temat założony przez niniejszego użytkownika
» 2016-12-03 16:21:24
Nie wiem o co chodzi ale tak jak w twojej pierwszej wersji wywalało mi stoi was not declared, tak teraz wywala mi atoi was not declared.
Kompiluje ci się to normalnie?
P-154446
jankowalski25
» 2016-12-03 16:37:11
» standard Catoi
Brakuje
#include <cstdlib>
.
Ewentualnie:
C/C++
#include <sstream>

int atoi( const char * str )
{
    std::istringstream in( str );
    int i = 0;
    in >> i;
    return i;
}
P-154447
mokrowski
» 2016-12-03 16:43:27
No nic... nie ma to nie ma. Dołącz <cstdlib>. Jak dalej problem to  .. proszę oto naiwne (ale skuteczne) obejście .. :-/
C/C++
wspolrzedne_t daj_wspolrzedne( const string & komenda )
{
    /*
        // A tak nietypowo :-) Konwersja do liczby i wyłuskanie 2 współrzędnych...
        int wartosc = atoi(komenda.c_str());
        return make_pair(wartosc / 10, wartosc % 10);
        */
    // Eh.. czasem nie ma wyjścia bo nie ma atoi() bo dostawca kompilatora ... nie dał... :-/
    return make_pair( komenda.c_str()[ 0 ] - '0', komenda.c_str()[ 1 ] - '0' );
}
P-154448
« 1 » 2
  Strona 1 z 2 Następna strona