char* a przypisanie?

0

Dzień dobry. Mam taki fragment kodu.

void odwroc(char *p) {
    char tmp;

    char *q = p;
    while(*(++q) ); //opusc petle gdy *q == /0, ++q - najpierw zwieksz, potem sprawdz
    q--;

    while(q!=p) {
        *q=*p;

        p++;
        q--;
    }
}

Pomińmy fakt, że fukcja nie zrobi dokładnie tego, czego od niej oczekuję, moim problemem jest linia: *q=*p;
W tym momencie program przerywa działanie. Długo zastanawiałem się, dlaczego to nie działa. Podczas eksperymentów udało mi się tylko zauważyć pewną prawidłowość. Oto przykładowy kod:

void f() {
     char *b;
     b++;
     *b = 'f';
}

Tutaj ładnie działa przypisanie. Wniosek jest więc prosty. Jeżeli zadeklarujemy pustą tablicę char*, możemy dowolnemu jej elementowi przypisać dowolną wartość. Jeśli jednak ta tablica jest czymś wypełniona, program przestanie działać, nie ma możliwości zmiany wybranego znaku.

Moje pytanie brzmi: dlaczego?

Z góry dziękuję za odpowiedź, pozdrawiam

0

Pętla

while(q!=p)

nigdy się nie zakończy dla parzystej długości stringa.
Poza tym co ta funkcja robi? Bo w tej chwili algorytm polega na zamianie
Ala ma kota
w coś w stylu
Ala mam alA
Pokaż wywołanie tej funkcji, i dokładnie CO podajesz jako parametr (wskaźnik czy tablicę, czy stałą, czy co).

0
#include <iostream>
#include <cstdlib>
using namespace std;

int dlugosc(const char *p) {
    int l=0;
    while(*p++) l++;
    return l;
}

void odwroc(char *p) {
    char tmp;

    char *q = p;
    while(*(++q) ); //opusc petle gdy *q == /0, ++q - najpierw zwieksz, potem sprawdz
    q--;
    cout << *p << endl << *q << endl;
    while(q!=p) {
        *q=*p;
        cout << *p << "  " << *q << "  "<<tmp <<endl;
        p++;
        q--;
    }
}

void f() {
     char *b;
     b++;
     *b = 'f';
}
int main()
{
      char* l="tekst";
      odwroc(l);

      system("PAUSE");
      return 0;
}

oto cały kod, ejstem świadomy niedoskonalosci, o których wspomniałeś i napisałem o tym w moim poście. algorytm nie jest tutaj problemem, jest nim jedynie linia, która generuje błąd.

0

Gadasz jakieś bzdury. Program wcale nie przerywa działania, o ile oczywiście przekazujesz jako argument C-stringa a nie tablicę znaków (tzn na koncu stringa masz znak '\0') i nie przekazujesz tam jakiegoś stałego napisu.
Poza tym z tego co piszesz wynika że zupełnie nie rozumiesz tego kodu.
Przypisanie
*q = *p
Znaczy tyle co: do pamięci na którą pokazuje wskaźnik q przypisz wartość na którą pokazuje wskaźnik p.
Początkowo p wskazuje na początek, q na koniec i potem sie do siebie zbliżają. Oczywiscie to nie odwróci ci stringa tylko przerobi go na śmieszny palindrom. Żeby odwrócic stringa musiałbyś napisać

char tmp = *q;
*q = *p;
*p = tmp;

Poza tym twój "przykładowy kod" woła o pomstę do nieba.
char* to WSKAŹNIK do pokazywania na char. Żadna tablica! Co więcej NIE WOLNO ci nic wpisać pod ten wskaźnik, bo nie wiesz gdzie on pokazuje. Że akurat ci to zadziałało to twoje szczęście, równie dobrze mógł polecieć segfault (i powinien...). Żeby przypisać coś pod wskaźnik musisz zaalokować pamięć (malloc() lub new).
Zresztą nic wspólnego nie ma to z kodem który podałeś, bo w twoim kodzie wskaźniki poruszają sie po twojej pamięci (bo poruszają sie po tablicy char).

Nie pokazałeś tego co istotne ale zgaduje że zrobiłeś coś takiego:

odwroc("ala ma kota");

I to faktycznie spowoduje wysypanie sie programu. Czemu? Bo napis "ala ma kota" znaduje sie w obszarze pamięci której nie wolno ci modyfikować i próba modyfikacji powoduje błąd (ale gcc pozwala kompilować program tak zeby takie napisy dało sie modyfikować). Czemu nie wolno tego modyfikować?
Bo kompilator moze sobie to tak poustawiać że masz np. napis
"ala ma kota"
i napis
"ala"
I zostanie to tak zrobione że w pamięci fizycznie będzie tylko napis "ala ma kota" (bo napis "ala" będzie po prostu odczytywany z tego samego miejsca w pamieci).

edit: tak jak myślałem wysyłasz do funkcji STAŁY napis, którego nie wolno ci modyfikować. Takie wywołanie:

char zmienna[]="ala ma kota";
odwroc(zmienna);

Wyeliminuje problem wysypywanie się programu, bo po tej pamieci wolno ci pisac.

0

Wiem co mam napisać, by odwrócić stringa. Napisałeś ogromnego posta o wszystkim tylko nie o tym o co pytam, ale cieszę się, że zwróciłes uwagę na to co zrobiłem w 'przykladowym kodzie'. Jednak to oświecenie nie rozwiązuje mojego głównego problemu. Piszesz, że w funkcji odwroc poruszam się po własnej pamięci i nie jest to pamięć chroniona. Dlaczego więc *p=*q wywala mi bląd? Sprobujmy na takim przykładzie, nie ma tu żadnego zamieniania, ejdynie ta problematyczna linijka.

#include <iostream>
#include <cstdlib>
using namespace std;

int f(char *a, char *b) {
    *b=*a;
}
int main()
{
      char *a = "tekst1";
      char *b = "tekst2";
      f(a,b);
      system("PAUSE");
      return 0;
}
0

Mój poprzedni post rozwiązuje twój problem, ale chyba był za długi i nie dałeś rady go przeczytać...
Proponuje opanować podstawy tego jak przechowywane w pamięci są dane...
Pisałem posta zanim napisałeś drugiego, gdybym pisał później to ominąłbym zbędne rzeczy. Ale wtedy jeszcze nie bylo wiadomo w czym problem.
No ale wracając do pytania. Zapis

char* napis = "tekst";

i

char napis[] = "tekst";

TO DWA RÓŻNE ZAPISY. Znaczą ZUPEŁNIE co innego.
Pierwszy zapis to : "wskaźnikowi napis przypisz adres gdzie w pamięci znajduje się stały napis "tekst"". To znaczy że kompilator w chwili kompilacji w pewnym segmencie pamięci przechowuje ten "tekst", ale w miejscu do którego nie wolno ci zapisysywać.
Drugi zapis to : "stwórz na stosie tablicę 6 elementową (dedukowane na podstawie długosci napisu) i wpisz do niej napis "tekst""

W przypadku drugim mamy do czynienia z pamięcią do której wolno ci pisać, dlatego nie wystąpi błąd przy zapisie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1