logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

C++ - Konwersja tablicy char do string w Visual Studio 2010 - śmieci w pamięci

Aris1414 24 Gru 2014 16:00 3327 10
  • #1 14252108
    Aris1414
    Poziom 10  
    Posty: 38
    Ocena: 11
    Witam serdecznie. Mam problem z konwersją tablic znaków do zmiennej klasy string. Mam powiedzmy zmienną char imie_nazwisko[40]; oraz zmienną klasy string imie_naz;

    Próbowałem następującej konwersji:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Konwersja niby działa, ale w zmiennej pojawiają się jakieś śmieci z pamięci.
    Ktoś wie jak się tego pozbyć?

    Piszę w Microsoft Visual Studio 2010[/code]
  • #2 14252126
    witoldwitoldowicz
    Poziom 28  
    Posty: 698
    Pomógł: 163
    Ocena: 60
    W jaki sposób wpisałeś do zmiennej imie_nazwisko?
  • #3 14252144
    Aris1414
    Poziom 10  
    Posty: 38
    Ocena: 11
    Użyłem konwersji w drugą stronę. Mam bowiem strukturę bazującą na zmiennych klasy string i drugą strukturę na tablicach znaków. Konwersję na char'y wykonuję by zapisać dane do pliku binarnego i móc je później odczytać. Po odczytaniu muszę te dane znów przekonwertować na stringi i zapisać je w liście jednokierunkowej, która operuje na stringach.

    Dane do stringa zapisuję przy użyciu getline, a konwersja na tablice char polega na przepisywaniu znak po znaku.
  • #4 14252161
    witoldwitoldowicz
    Poziom 28  
    Posty: 698
    Pomógł: 163
    Ocena: 60
    Dodałeś na koncu 0 (Zero)?
  • #5 14252217
    Aris1414
    Poziom 10  
    Posty: 38
    Ocena: 11
    W którym miejscu mam to zero uwzględnić? Wiem że tablica char na ostatnim miejscu przyjmuje '\0', ale jak to się ma do mojego problemu?
  • #6 14252750
    mcvsama
    Poziom 16  
    Posty: 94
    Pomógł: 23
    Jeśli wiesz ile bajtów wczytałeś, to nie musisz dodawać 0, ale zamiast tego użyj:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Zakładam, że imie_nazwisko jest typu char*.

    Tak czy owak, jeśli używasz .c_str() przed zapisem, to na końcu jest znak \0 już dodany. Więc gdy kopiujesz dane z .c_str() do tablicy, to skopiuj o 1 znak więcej, żeby do pliku dopisało się również 0.
  • #7 14278828
    Aris1414
    Poziom 10  
    Posty: 38
    Ocena: 11
    mcvsama napisał:
    Jeśli wiesz ile bajtów wczytałeś, to nie musisz dodawać 0, ale zamiast tego użyj:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Zakładam, że imie_nazwisko jest typu char*.

    Tak czy owak, jeśli używasz .c_str() przed zapisem, to na końcu jest znak \0 już dodany. Więc gdy kopiujesz dane z .c_str() do tablicy, to skopiuj o 1 znak więcej, żeby do pliku dopisało się również 0.


    Wydaje mi się, że zrobiłem tak jak mówiłeś. Poniżej podaję kod mojej funkcji konwertującej:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Efekt działania tego jest taki, że wprowadzam następujące dane:
    C++ - Konwersja tablicy char do string w Visual Studio 2010 - śmieci w pamięci

    Przy powyższym kodzie i zastosowaniu polecenia sizeof, konwersja daje taki efekt:
    C++ - Konwersja tablicy char do string w Visual Studio 2010 - śmieci w pamięci

    A bez zastosowania polecenia sizeof wychodzi coś takiego

    C++ - Konwersja tablicy char do string w Visual Studio 2010 - śmieci w pamięci

    Dodam tylko że typ "dane" operuje na stringach, a "dane_conv" na tablicach znaków.

    Ma ktoś jakiś pomysł na to?


    Pozdrawiam
  • Pomocny post
    #8 14278890
    mcvsama
    Poziom 16  
    Posty: 94
    Pomógł: 23
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Prawdopodobnie chciałeś stworzyć nowe stringi, ale tego tak się nie robi. Użyłeś właśnie operatora „przecinka” (nawet mimo tego, że są tam nawiasy). To co jest powyżej ma taki sens:
    do element.imie_nazwisko przypisz rozmiar wskaźnika (czyli 4 w przypadku 32-bitowego adresu, 8 w przypadku 64-bitów).

    Jeśli element.imie_nazwisko jest typu std::string, to został wywołany std::string::operator=(const char*) i zrobiona była niejawna konwersja z size_t (zwracanego przez sizeof()) do wskaźnika. (To jest jedna z wad C++, takie niejawne konwersje.)

    Zarówno w C jak i w C++ operator , (przecinek) wykonuje to co jest po lewej stronie, potem po prawej stronie i zwraca to co zwróciło wyrażenie po prawej stronie.
    Napis:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    wywoła funkcję f(), następnie g() i przypisze do "a" to co zwróciła funkcja g. (Oczywiście zależy od kontekstu - przy wywołaniu funkcji przecinek rozdzieli argumenty, ale jeśli całą listę umieścisz w dodatkowych nawiasach, to wtedy właśnie zadziała operator przecinka). Podobny właśnie jest efekt w Twoim kodzie.

    Masz następujące opcje:
    1. skonstruować i skopiować obiekt std::string():
    Kod: text
    Zaloguj się, aby zobaczyć kod


    2. Użyć metody assign() na stringu, który już istnieje w Twojej strukturze:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    3. Użyć inicjalizatora z C++11 - nawiasów klamrowych:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    -----

    Edit: acha, jeszcze jeden błąd: sizeof() zwróci rozmiar wskaźnika, nie długość C-łańcucha (to jest taka pseudofunkcja wykonywana w czasie kompilacji programu, nie w czasie jego działania). sizeof() może przyjąć różne wyrażenia, ale one nigdy nie są wykonywane. To czego potrzebujesz, to funkcja strlen().

    Edit2: Jeszcze taka ciekawostka - w C łańcuchy nie mogą zawierać znaków NUL (\0), bo on oznacza ich koniec. Natomiast std::string() może zawierać dowolną ich liczbę, dlatego łańcuchy z C można trzymać w std::string(), ale nie wszystkie łańcuchy z std::string() dadzą się przedstawić w postaci C-stringów. ;-)
  • #9 14279959
    Aris1414
    Poziom 10  
    Posty: 38
    Ocena: 11
    Wykorzystałem zarówno metodę assign klasy string jak i tworzenie obiektu klasy string. Jest lepiej, ale nadal diabli wiedzą skąd, pojawiają się krzaki.

    C++ - Konwersja tablicy char do string w Visual Studio 2010 - śmieci w pamięci

    Sprawdzałem już na każdym etapie zapisu do pliku i jestem pewien że do pliku binarnego są przesyłane właściwe dane bez żadnych niechcianych "atrakcji".


    Mam jeszcze jedno pytanie. Otóż odczyt z pliku wykonuję w pętli while aż do spełnienia warunku feof(*FILE). Teoretycznie gdy zapiszę jeden element do pliku, jeden element powinien zostać odczytany. Natomiast u mnie, przy zapisaniu w pliku jednego elementu typu "dane", do listy jednokierunkowej na której operuje program są zapisywane te dane z krzakami (na zrzucie powyżej) oraz drugi element który zawiera dokładnie te same krzaki co na zrzucie bez właściwych danych.
  • Pomocny post
    #10 14283275
    mcvsama
    Poziom 16  
    Posty: 94
    Pomógł: 23
    Teoretycznie, jeśli zapiszesz jedną strukturę, to powinieneś też odczytać jedną strukturę. Pytanie czy zapisujesz poprawnie.
  • #11 14283643
    Aris1414
    Poziom 10  
    Posty: 38
    Ocena: 11
    Dane w trakcie wykonywania operacji na nich są przechowywane w liście jednokierunkowej opartej na STL'u (plik nagłówkowy "list"). Lista operuje na typie strukturalnym "dane". Ciągi znakowe zapisuje przy użyciu polecenia

    Kod: text
    Zaloguj się, aby zobaczyć kod


    i przekazuję dane do listy poleceniem nazwa_listy.push_back(element).

    Gdy już chcę zapisać dane do pliku, tworzę sobie zmienną typu dane_conv, "zeruję" ją żeby mieć pewność, że nie ma tam żadnych śmieci. Następnie przechodzę przez całą listę z wykorzystaniem iteratora i przesyłam do funkcji konwertującej stringi na tablice znaków element listy na który wskazuje iterator oraz stworzoną wcześniej zmienną typu dane_conv i ostatecznie używając polecenia
    Kod: text
    Zaloguj się, aby zobaczyć kod

    przesyłam dane do pliku.

Podsumowanie tematu

LABEL_AI_GENERATED
Użytkownik ma problem z konwersją tablicy znaków (char) do zmiennej typu string w C++ w Visual Studio 2010, gdzie po konwersji pojawiają się niechciane "śmieci" w pamięci. W odpowiedziach zasugerowano, aby upewnić się, że tablica char kończy się znakiem null ('') oraz aby używać odpowiednich metod konwersji, takich jak std::string imie_naz2(imie_nazwisko, liczba_bajtów). Użytkownik próbował różnych metod, w tym użycia operatora przypisania i funkcji assign, ale nadal napotykał problemy z nieprawidłowymi danymi. Dodatkowo, podczas zapisu i odczytu danych z pliku binarnego, pojawiały się problemy z niepoprawnym odczytem struktur danych.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA