C++ Zapis do pliku przy pomocy fstream czasem powoduje błędy


(kijek) #1

Witam. Z pewnego powodu potrzebuję napisać symulator pamięci EEPROM. Zacząłem więc od widoku hex i możliwości zapisu danych do pliku. Jak na razie cała zawartość pamięci jest po prostu generowana losowo. Jednakże już tak prosta funkcjonalność sprawia problemy. Otóż to co wyświetla mi konsola nie zawsze zgadza się z tym, co jest zaraz potem zapisywane do pliku. Oto kilka przykładów. Na ich podstawie możnaby wywnioskować, iż zawsze niepożądanym wpisem jest 0D. Jednak wcale tak nie jest - ot dziwna zbieżność. W każdym razie... w celu zapisu do pliku używam put. Z kolei w kodzie prezentuje się to następująco:

hexa.put((char)eeprom[(width*counter)+second_Counter]);

Najzabawniejsze jest to, że następna linijka wygląda tak:

cout << hex << eeprom[(width*counter)+second_Counter];

A jednak czasem występują różnice między oboma strumieniami. Czym może być to spowodowane?


(kostek135) #2

Możesz pokazać deklarację tablicy eeprom?


(kijek) #3

Ah... Teraz dopiero zauważyłem... Zawsze przed 0A pojawia się 0D. Deklaracja tablicy ma się następująco:

unsigned int eeprom[eeprom_Size*=100];

Co prawda powinno być mnożone przez 1000 ale zmieniłem nieco, by łatwiej było przedstawić problem.


(kostek135) #4

Więc jak na moje to robisz rzutowanie, które w jednym przypadku ucina 3 najbardziej znaczące bajty stąd różnice.


(kijek) #5

Dziękuję za cenną uwagę na temat rzutowania :slight_smile:

Niestety wygląda na to, że problem jest nieco inny. Otóż na początek postanowiłem sprawdzić, czy w generowanych plikach hex dla ATMegi znajduje się znak 0A. Gdyby go nie było, dodałbym do programu zwyczajne ignorowanie go. Jednak okazuje się, że 0A występuje stosunkowo często, a za każdym razem przed nim jest 0D. Sugerując się tabelą ASCII wychodzi na to, że 0A wymusza pojawienie się przed nim 0D.


(kostek135) #6

Tak. 0A to new line, a 0D to carriage return, na windowsie tak własnie kończy się linię pliku tekstowego, zapisywane symbolicznie "\r\n". Jednak nie rozumiem jak to ma się do przedstawionego przez ciebie problemu: "Otóż to co wyświetla mi konsola (rozumiem std::cout) nie zawsze zgadza się z tym, co jest zaraz potem zapisywane do pliku (rozumiem jakiś fstream).". Ta różnica bierze się z obcinania przez rzutowanie, i tyle. Jeśli chcesz sobie móc wypisać zawartość pamięci jako hex, niezależnie od tego jaki jest to typ strumienia, napisałbym taką funkcję:

void print_as_hex(std::ostream s, unsigned int v) {
    s  std::setw(8) std::hex std::setfill('0') v;
}

(kijek) #7

Problem polegał właśnie na występowaniu 0D przed 0A. Ponieważ na ekran wyrzucałem bezpośrednio zawartość tablicy, a do pliku szła zawartość tablicy plus z automatu 0D przed każdym 0A. Stąd wynikały niezgodności. Obecnie w identyczny sposób realizauję wypisywanie jako hex.