Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[C++] Cannot convert 'char' to 'char *'

pol102 10 Sty 2011 01:48 3166 12
  • #1 10 Sty 2011 01:48
    pol102
    VIP Zasłużony dla elektroda

    Witam! To, że jestem moderatorem optoelektroniki nic nie znaczy :)
    Jestem w trakcie uczenia się programowania i za cel postawiłem sobie przeszukiwanie tablicy o stałym rozmiarze, wypełnionej dowolnym wyrazem, i wyświetlanie ile razy dany wyraz w niej występuje.

    Problemy, których nie umiem przeskoczyć:
    - zdefiniowanie tak tablicy oraz zmiennej 'szukana' by mogły przechowywać więcej niż jedną literę (char to raczej złe rozwiązanie)
    - jeśli program znajdzie zdefiniowaną zmienną ma wyświetlić cały wiersz (nie mam pomysłu jak można to zrealizować)
    - co oznacza błąd z tytułu?

    Wskazówki czego nie robić w kodzie też mile widziane.

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0 12
  • Pomocny post
    #2 10 Sty 2011 07:36
    Terminator
    Poziom 23  

    Kod: cpp
    Zaloguj się, aby zobaczyć kod
    zamień na
    Kod: cpp
    Zaloguj się, aby zobaczyć kod
    dla pojedyńczych znaków.

    Cytat:
    zdefiniowanie tak tablicy oraz zmiennej 'szukana' by mogły przechowywać więcej niż jedną literę (char to raczej złe rozwiązanie)

    to zainteresuj się tablicą tablic znaków :) np tutaj mały tutorial
    Do porównywania ciągów znaków możesz wykorzystać strcmp albo napisać swoją.

    0
  • #3 10 Sty 2011 12:41
    szelus
    Specjalista - Mikrokontrolery

    pol102 napisał:

    - zdefiniowanie tak tablicy oraz zmiennej 'szukana' by mogły przechowywać więcej niż jedną literę (char to raczej złe rozwiązanie)

    To podobno C++ - bardziej interesująca (od propozycji Terminatora) będzie klasa string - http://www.cplusplus.com/reference/string/string/
    Cytat:

    - co oznacza błąd z tytułu?

    Typy char i char* (wskaźnik na char, używany również w C do napisów) nie są ze sobą bezpośrednio kompatybilne. Tutaj
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    usiłujesz je porównać bezpośrednio. Przez == możesz porównać dwa znaki, przez funkcję strcmp() i jej odmiany - dwa napisy. Porównywanie pojedynczego znaku z napisem jest raczej bez sensu - chyba, że chcesz porównać konkretną literę z napisu. Z tym, że jeżeli użyjesz klasy string, to strcmp() nie będzie Ci potrzebne.

    0
  • Pomocny post
    #4 14 Sty 2011 03:13
    wlw_wl
    Poziom 38  

    Jeżeli jest to program na komputer ogólnie pojętej klasy PC, użyj string j/w.

    Jeżeli to program na mikrokontroler 8bitowy to zostań przy char'ach. :)

    Twoja tablica tab wygląda tak:
    tab[0] - dwie liczby (znaki) (tab[0][0] i tab[0][1])
    tab[1] - dwie liczby

    Wyraz w zmiennej typu char możesz zapisać na dwa sposoby.

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Inaczej się możesz do nich odwołać:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Ta gwiazdka to operator wyłuskania, czyli "wyciągnięcia" tego, co się kryje pod adresem, na który wskazuje (tablica + 2), czyli literka "l". Jest to dokładnie to samo, co tablica[2].

    Co Ci to daje? Prostsza pętla:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Pytanie: po co w ogóle te wskaźniki?
    Ano dzięki nim możemy sobie w prosty sposób zapisać zdanie jako wyrazy i mieć do nich dostęp "w całości":
    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Więc do rzeczy - jak porównywać wyrazy? Tak:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Wynik:
    Code:
    Nasze zdanie to: 'Budujemy zdanie bardzo ale to bardzo ciekawe'.
    

    Szukam w nim wyrazu 'bardzo'.

    Znalazlem wyraz 'bardzo' na pozycji nr. 3

    Znalazlem wyraz 'bardzo' na pozycji nr. 6


    ed: dodałem const - pisałem to tak na szybko jako przykład tutaj ;)

    0
  • Pomocny post
    #5 14 Sty 2011 03:21
    azra
    Poziom 16  

    Cytat:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Raczej:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod
    W C++ string literals ("costam") są typu const char[n], a próba ich modyfikacji (np przez wskaźnik do nich) wykopie nas do świata niezdefiniowanego zachowania, nie mówiąc już o tym, że na nowszych kompilatorach nareszcie dostaje się przynajmniej ostrzeżenie za taki kod, więc... Po prostu dodaj const. ;)

    Ponieważ C również ma już "const" tam też powinno się je dodawać. Nawet pomimo, że nie ma obowiązku, bo literały mają typ char[n]... To jednak próba ich modyfikacji wyrzuci nas w to samo miejsce co w C++. ;)

    0
  • #6 15 Sty 2011 02:20
    pol102
    VIP Zasłużony dla elektroda

    Zasadniczo gotowca nie oczekiwałem ale mimo wszystko tak wyjaśniona sprawa rozwiewa wątpliwości :)
    Wrzuciłem w Bulidera2009, skompilowałem bez błędów ale jest tak zwane zdarzenie nieoczekiwane.
    [C++] Cannot convert 'char' to 'char *'

    Czyli nie wykonuje drugiej pętli. Pytanie dlaczego? Wskaźnik i jest zerowany więc powinno inkrementować wartość i sprawdzać...

    0
  • #7 15 Sty 2011 04:58
    azra
    Poziom 16  

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    możesz uprościć do
    Kod: cpp
    Zaloguj się, aby zobaczyć kod
    (położenie * nie ma większego znaczenia, ja daję przy typie, ponieważ myślę raczej w kategoriach "silnych" typów C++, Tutaj możesz o tym poczytać.) i w odpowiednich miejscach opuścić operator dereferencji. ;)

    Co do samego problemu, jest on dość oczywisty, c-stringi (ich zawartość) porównuje się za pomocą strcmp() i rodzinki, to co teraz robisz, to porównywanie wskaźników - co jak się domyślasz w tym przypadku nie ma sensu. :)

    edit: Swoją drogą, te kody to wyglądają raczej jak C niż C++. Czy Borland w swoim Studio ma jeszcze kompilator C? Czy kompilowałeś po prostu jako C++?

    0
  • #8 15 Sty 2011 12:40
    wlw_wl
    Poziom 38  

    Czemu nie wszedł w drugą pętlę?
    Widocznie *(zdanie+i) było równe zero.
    Dlaczego? Nie wiem. Jakiś psikus kompilatora.
    Chwilę wcześniej w takiej samej pętli wypisuje całe zdanie i problemu nie ma.

    Ja * daję przy nazwie zmiennej, bo bardziej spójnie i zrozumiale wygląda przy deklaracji wielu zmiennych:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Żeby nie było wątpliwości, program ten sam, ale przy użyciu strcmp():
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Ja to kompiluję na dev-cpp, alternatywą jest VS2008, wolałem go do tego nie mieszać ;)

    0
  • #9 15 Sty 2011 16:12
    pol102
    VIP Zasłużony dla elektroda

    Założyłem, że chociażby przez podobieństwo powinno działać - skompilowane jako C++.

    Czyli można by to zrobić tak:

    w pętli while inkrementować wskaźnik 'i'
    w wyrażeniu warunkowym sprawdzać co zwraca funkcja strcmp
    jeśli zwraca zero to wyświetlić napis i podbić ponownie 'i' o jeden(?)

    Z tym pisaniem w C++ trzymając się zachowań z czystego C, jest tak, że teraz muszę nauczyć się i zaliczyć 1 semestr, a C wchodzi od 2 i nie chcę się "skrzywić" ;)

    Na czym polega wyższość printf nad cout?

    0
  • #10 15 Sty 2011 19:55
    wlw_wl
    Poziom 38  

    strcmp zwraca 0 kiedy oba stringi są takie same.
    Indeks i jest używany tutaj do odliczania kolejnych elementów w tablicy, w naszym wypadku kolejnych wyrazów.
    W moim przykładzie program wypisuje gdzie znalazł, równie dobrze może liczyć ile razy znalazł, ale wtedy potrzebujesz osobną zmienną do zliczania. Wtedy zamiast wypisywania zwiększasz tę zmienną.

    Trudno mówić o wyższości cout nad printf.
    cout jest obiektem klasy ostream i reprezentuje strumień wyjścia standardowego. Strumienie to całkiem osobna historia.
    Z Twojego punktu widzenia upraszcza to kod programu, bo nie musisz się troszczyć o to, jakiego typu zmienną wypisujesz. W ogólności strumieniem wyjściowym może być konsola, ale może też równie dobrze być nim plik, i w taki sam sposób będziesz pisał do pliku.
    Można powiedzieć, że printf to bardziej C, a cout to bardziej C++ ;)

    0
  • #12 16 Sty 2011 03:15
    wlw_wl
    Poziom 38  

    I tak jak tam dostałeś odpowiedź - zależy.
    Wiadomo, jak z każdym benchmarkiem, odpowiednio przygotowany test zawsze pokaże wyższość tego, co chcemy. Sam to w zasadzie udowodniłeś swoimi testami.

    0
  • Pomocny post
    #13 16 Sty 2011 17:55
    Dariusz Bismor
    Poziom 17  

    Oj, szkoda, że tu nie zaglądałem od pewnego czasu.
    Kolego Moderatorze pol102 (nigdzie nie znalazłem imienia)!
    Przede wszystkim musisz zdecydować, jakiego stylu programowania chcesz się uczyć.

    Jeżeli jest Ci potrzebne programowanie blisko sprzętu (sterowniki dedykowane, mikrokontrolery, moduły jądra), z dwóch powodów doradzam programowanie proceduralne w języku C. Po pierwsze, do urządzeń niskiego poziomu często nie ma bibliotek języka C++. Po drugie C i programowanie proceduralne pozwala na pisanie bardziej optymalnego kodu, gdzie mamy nad wszystkim większą kontrolę. Oczywiście, możesz to dalej kompilować kompilatorem C++ i używać cout zamiast printf, ale po co? Jedyną chyba przewagą printf nad cout jest szybkość (trudno znaleźć przykład gdzie cout jest szybsze od printf).

    Jeżeli idziesz bardziej w programowanie wysokiego poziomu, np pisanie aplikacji okienkowych w Win, Qt, czy czym tam jeszcze, lub nawet aplikacji terminalowych, ale przetwarzających jakieś obiekty, wybierz styl orientowany obiektowo - złap się go mocno, trzymaj, nie puszczaj, i wyrzuć szybko do kosza wszystkie te fragmenty kodu, gdzie masz char*, czy jakikolwiek inny wskaźnik. Na wskaźniki przyjdzie czas, ale później. A teraz ćwicz obiekty: pojemniki standardowe, string-i, algorytmy standardowe, itd. Nie ulegaj pokusie nauki obydwu stylów na raz! Jednak przestrzegam: styl o.o. jest trudniejszy, często nie do przejścia bez mentora. Niemniej moim zdaniem warto.

    Ach, i jeszcze o przewadze cout: jest nią bezpieczeństwo typów. printf to funkcja o zmiennej liczbie argumentów, więc kompilator nie jest w stanie sprawdzić, czy jej wywołanie jest poprawne (dzieje się to dopiero podczas wykonania programu). Użycie cout pozwala sprawdzić już podczas kompilacji, czy użyto właściwych typów. Ponadto możliwe jest przeładowywanie funkcji operatora "<<" (wstawiania do strumienia) w celu dostosowania do swoich klas (typów), pisanie własnych manipulatorów, itd.

    HTH,
    Dariusz

    1