Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

C++ - Rozszerzanie tablicy w funkcji

JimmyB 18 Jan 2014 20:59 2352 8
  • #1
    JimmyB
    Level 11  
    Witam,
    Mam do napisania funkcję, która by zamieniała w tekście zadane słowa na inne. Tak to ma wygladać (funkcja ma zamieniać stary wzorzec na nowy):

    void str_zamien( char* tekst, char* stary_wzorzec, char* nowy_wzorzec);

    <tekst> == "ala ma kota a ola ma asa"
    <stary_wzorzec> == "ma"
    <nowy_wzorzec> == "miala"
    rezultat zamiany: "ala miala kota a ola miala asa"

    Moje pytanie brzmi, jak "rozsunąć" tę tablicę, gdy nowy wzorzec jest dłuższy (większa ilość znaków) niż stary?

    Proszę o pomoc.
  • #2
    krru
    Level 33  
    Statycznie zadeklarowanej tablicy nie da się rozciągnąć. Od razu musiałaby być zadeklarowana z zapasem.

    Można zmienić rozmiar tablicy allokowanej dynamicznie (malloc - nie new). Czasem reallokacja może zmienić adres - jest to wtedy realizowane przez utworzenie nowej tablicy i skopiowanie starej zawartości. Trzeba być na to przygotowanym - podany nagłówek funkcji jest niewłaściwy dla takiego przypadku. Z resztą ten nagłówek nie jest 'w stylu C' - tam zawsze podaje się dopuszczalną długość wyniku. Stare funkcje, które tego nie mają, przez nowe kompilatory traktowane są jako 'obsolete'/'not safe' i posiadają odpowiedniki z podaniem długości (strcpy=>strncpy itp).

    Skoro to piszesz w C++ to dlaczego nie używasz std::string?
  • #3
    JimmyB
    Level 11  
    Nie używam cstringów, gdyż takie mam polecenie. Jestem dopiero początkującym programistą i wiele ćwiczeń ma mi zapewne pokazać, jak te funkcje działają w środku. Z tego, co wiem, to pamięć new też można poszerzyć po prostu dodając potrzebną ilość do wartości zmiennej rozmiaru.

    Nie da się jakoś obejść wczytywania rozmiaru (z polecenia wynika, że powinna być taka możliwość)? Oczywiście dalej chodzi o poszerzenie tablicy.
  • #4
    krru
    Level 33  
    Może napisze jaśniej:

    Code: c
    Log in, to see the code


    Taki nagłówek funkcji umożliwia jedynie napisanie funkcji, która zakłada że nowy tekst zmieści się w aktualnym miejscu. Nie oznacza to, że musi być krótszy - tylko że tablica tekst jest dostatecznie długa. Niestety funkcja taka nawet nie ma tego jak sprawdzić. Albo zrobi swoje, albo program się wywali. Dodanie parametry maksymalnej długości:

    Code: c
    Log in, to see the code


    umożliwi sprawdzenie - czyli funkcja się nie wywali, aczkolwiek nie poda, czy się udało.
    (Dodałem consty gdzie powinny być)

    Jeśli potrzeba dynamicznego powiększenia obszaru to funkcja musi mieć możliwość zwrócenia nowego adresu pod którym znajduje się wynik:

    Code: c
    Log in, to see the code


    albo:

    Code: c
    Log in, to see the code
  • #5
    kajbrz
    Level 2  
    Chyba jesteśmy na tym samym kierunku i mam z tym problem z natury merytorycznej.

    Ale pokażę ci mój kod.

    Code: cpp
    Log in, to see the code


    @edit
    Mój problem polegał na tym, że nie wiem co się dzieje powiedzmy w funkcji
    Code:
    char *strupr(char *str);


    kiedy ją zwracamy bezpośrednio powiedzmy do std::cout:

    Code:
    std::cout << strupr("MoJa MaMa");


    To wtedy mamy śmieci w pamięci, czy kompilator to automatycznie usuwa?

    A co do samego rozsuwania:
    Poza tym masz dwa podejścia, żeby to rozwiązać.
    1) Wyszukujesz w tekście miejsce gdzie znajduje się wzorzec, kopiujesz wszystko do dynamicznej tablicy pomocniczej, starą usuwasz i alokujesz na nowo większą o (nowy_wzorzec-stary_wzorzec), aż do napotkania znaku.

    2) druga wersja (ja z niej korzystałem) , wyszukujesz miejsca gdzie znajduja sie wzorce, zapisujesz je do dynamicznej tablicy indeksow, a potem tworzysz nowy tekst o dlugosci
    Code:
       int dlugosc_nowyTekst = dlugosc_tekst+((dlugosc_nowy-dlugosc_stary)*k); / 
    i potem po prostu przepisujesz, a tam gdzie napotkasz indeks równy wystapieniu[k] to wstawiasz nowy wzorzec. Reszte powineneś z kodu wyczytać.
  • #6
    JimmyB
    Level 11  
    Problem w tym, że tworząc nową tablicę, nie operuję już na starej. Ta funkcja ma być zdaje się uniwersalna i ma zmieniać oryginalną tablicę, żeby można było coś jeszcze z nią potem robić. Chyba, że się mylę...

    Ja zdecydowałem, że założę, że miejsca wystarczy.
  • #7
    kajbrz
    Level 2  
    Nie można operować na
    Code:
     char* tekst = "cos tam cos tam"; 

    bo jest to wskaźnik na stos gdzie znajduje się STAŁY tekst "cos tam cos tam", więc jeśli chcemy cokolwiek zmienić, to trzeba właśnie albo zaalokować pamięć na wskaźniku, który podajemy, albo utworzyć nową dynamiczną tablicę i zwrócić wskaźnik.
  • #8
    the_fifth_horseman
    Level 32  
    JimmyB wrote:
    Problem w tym, że tworząc nową tablicę, nie operuję już na starej. Ta funkcja ma być zdaje się uniwersalna i ma zmieniać oryginalną tablicę, żeby można było coś jeszcze z nią potem robić. Chyba, że się mylę...

    Ja zdecydowałem, że założę, że miejsca wystarczy.

    Przekazuj do funkcji nie adres do oryginalnej tablicy tylko wskaźnik na wskaźnik do niej. Wtedy możesz w funkcji zmienić jego wartość. :D

    Coś na ten wzór:
    Code: cpp
    Log in, to see the code
  • #9
    JimmyB
    Level 11  
    Dobra, dzięki za odpowiedzi. Coś pomyślę.