tBane Temat założony przez niniejszego użytkownika |
» 2024-10-20 14:26:15 Na razie mam coś takiego ale to statyczne wczytywanie a nie dynamiczne for( int y = 0; y < 16; y++ ) { std::string tileLine; if( !std::getline( file, tileLine ) ) { break; } std::istringstream tileStream( tileLine ); int value; for( int x = 0; x < 16; x++ ) { tileStream >> tiles[ y * 16 + x ]; } }
|
|
pekfos |
» 2024-10-20 14:26:55 Nie wiem tylko jak sprawdzić czy faktycznie jest 16x16 wartości i jak następnie wczytać te tilesy (int'y) do tablicy Powinieneś mieć 16 linii pasujących do formatu 16 liczb oddzielonych spacjami, więc w pętli wczytaj linie i sparsuj linie. to zwykłe inty przecież, nie wiem po co pchać tu insugned long. Kwestia preferencji. Wersje dla C działają na long, a wziąłem unsigned ponieważ oczekujesz tu tylko nieujemnych liczb, ale możesz ujemne odrzucić potem ifem. Pamiętaj że stoi() wyrzuca wyjątek w przypadku błędu więc dobrze by było go jakkolwiek obsłużyć. std::vector < int > tiles; for( int i = 0; i < 256; i++ ) tiles.push_back( - 1 ); Zasadniczo jest konstruktor wektora który to robi std::vector < int > tiles( 256, - 1 );
Wtedy nie prościej było wypełnić wektor na start zerami? Chyba chcesz w tej pętli wczytać do 16 liczb do tablicy i wywalić błąd jeżeli coś zostanie w strumieniu. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-20 14:38:21 chwila, chwila. Bo skopiowałem bezmyślnie z ChatGpt. Teraz mam taki kod: std::vector < int > tiles;
for( int y = 0; y < 16; y++ ) { std::string tileLine; if( !std::getline( file, tileLine ) ) { break; } std::istringstream tileStream( tileLine ); int value; for( int x = 0; x < 16; x++ ) { tileStream >> value; tiles.push_back( value ); } }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-20 14:43:38 Dobra, chyba mam zaraz będę testował: std::vector < int > tiles( 256, 0 );
int y = 0;
while( y < 16 && std::getline( file, line ) && line[ 0 ] >= '0' && line[ 0 ] <= '9' ) { std::istringstream tileStream( line ); int value; int x = 0; while( tileStream >> value && x < 16 ) { tiles[ y * 16 + x ] = value; x += 1; } y += 1; }
for( int i = 0; i < tiles.size(); i++ ) { chunk->terrain->edit( i % 16, i / 16, tiles[ i ] ); }
Czy można jakoś przemieszczać się getlinem po liniach ? |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-20 16:57:34 Można przy pomocy file.tellg() oraz file.seekg(). I z tym sposobem udało mi się zrobić sprawdzanie poprawności danych. Tutaj Kod : if( objectType == "Chunk" ) { std::regex chunk_regex( R"(Chunk y=([0-9]+) x=([0-9]+))" ); std::smatch chunk_match; if( std::regex_search( line, chunk_match, chunk_regex ) ) { int chunk_y = std::stoi( chunk_match[ 1 ] ); int chunk_x = std::stoi( chunk_match[ 2 ] ); chunk = getChunk( chunk_x, chunk_y ); if( chunk == nullptr ) { chunk = new Chunk( chunk_x, chunk_y ); chunks.push_back( chunk ); } std::streampos pos = file.tellg(); bool correct_data = true; string _line; int y = 0; int x; while( std::getline( file, _line ) && _line[ 0 ] >= '0' && _line[ 0 ] <= '9' ) { std::istringstream iss( _line ); int val; x = 0; while( iss >> val ) x += 1; if( x != 16 ) { correct_data = false; } y += 1; }; if( y != 16 ) { correct_data = false; } std::vector < int > tiles( 256, 0 ); if( correct_data == true ) { file.seekg( pos ); int y = 0; while( y < 16 && std::getline( file, line ) ) { std::istringstream tileStream( line ); int value; int x = 0; while( tileStream >> value ) { tiles[ y * 16 + x ] = value; x += 1; } y += 1; } for( int i = 0; i < tiles.size(); i++ ) chunk->terrain->edit( i % 16, i / 16, tiles[ i ] ); } } }
|
|
pekfos |
» 2024-10-20 21:53:21 Po co ten podział? Byłoby prościej jakbyś sprawdzał poprawność w czasie parsowania. Nie byłoby potrzeby wczytywać danych 2 razy i cofać się w pliku. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-21 09:34:02 Ponieważ, gdyby dane były niepoprawne, wtedy program nie wczytywałby ich. To zamierzałem właśnie osiagnąć. |
|
pekfos |
» 2024-10-21 15:33:54 Przecież musisz je wczytać by to wiedzieć. To jest trochę bez sensu by najpierw jedna implementacja przetworzyła dane na niby, by potem druga implementacja mogła przetworzyć te dane i wypruć wynik już bez żadnych hamulców, bo "wszystkie możliwe błędy zostały wyłapane wcześniej". Wczytaj dane do tymczasowej lokalizacji i na koniec zdecyduj czy chcesz je zaaplikować. I tak to tak robisz gdy wczytujesz dane za drugim razem, powinno być tak: if( correct_data == true ) { for( int i = 0; i < tiles.size(); i++ ) chunk->terrain->edit( i % 16, i / 16, tiles[ i ] ); } Albo w ogóle nie powinno być tego w tym miejscu, bo na razie wiesz tylko czy ta macierz 16x16 jest poprawna. Dalsza część pliku może być błędna. Idealnie taki plik jest wczytywany w całości albo wcale. Od momentu gdy zdecydujesz się zaaplikować dane, do momentu poprawnego zakończenia, przerwanie z powodu błędu zostawia błędny stan. W tym przedziale powinno się dziać jak najmniej, najlepiej tylko przeniesienie nowych struktur danych w miejsce starych. Na pewno nie powinno być tam całej logiki realnego parsowania danych. |
|
1 « 2 » 3 |