• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

C - błąd w odwracaniu stringa - ciekawy przypadek

0 głosów
307 wizyt
pytanie zadane 18 grudnia 2015 w C i C++ przez Int_main Bywalec (2,850 p.)

Witam. Niedawno pisałem sobie funkcję w C odwracającą podany łańcuch znaków, funkcja odwraca dobrze, ale przy niektórych wyrazach dodaje jakieś dziwne znaki.
dobrym przykładem jest input: kowalski. output sprawdźcie sami, bo za każdym razem wyrzuca inne dziwne symbole. jeśli dla kowalskiego zadziałą popróbujcie inne losowe ciągi.

#include <stdio.h>
#include <stdlib.h>
#define MAX 1000

void reverse(char string[]);

int main()
{
    char lancuch[MAX];
    printf("Podaj lancuch do odwrocenia.\n");
    scanf("%s", lancuch);
    reverse(lancuch);
    return 0;
}

void reverse(char string[])
{
    char *newstring;
    char tablica[MAX];
    //zmienna zliczaj¹ca litery
    int i=0;
    //zliczam litery
    while(string[i]!='\0')
        i++;
    printf("Liczba liter wynosi: %d\n", i);
    i-=1;
    newstring = (char*)malloc(i * sizeof(*newstring));
    int j=0, k=0;
    for(j=i; j>=0; j--)
    {
        newstring[k]=string[j];
        ++k;
    }
    printf("Po odwroceniu wyraz ma postac: %s\n", newstring);
}


 

1 odpowiedź

+1 głos
odpowiedź 18 grudnia 2015 przez Krawiec91 Pasjonat (19,600 p.)
wybrane 18 grudnia 2015 przez Int_main
 
Najlepsza

Wygląda na to, że nie kończysz odwróconego stringa nullem. Zaczynasz kopiować ze starego stringa od przedostatniego znaku, po skopiowaniu wszystkich liter nie kończysz nowego stringa nullem. W wyniku tego wypisuje Ci wszystko od początku stringa do pierwszego spotkanego nulla, który znajduje się poza tablicą i dlatego te kwiatki się wyświetlają.
 

void reverse(char string[])
{
    char *newstring;
    //char tablica[MAX];
    //zmienna zliczajaca litery
    int i=0;
    //zliczam litery
    while(string[i]!='\0')
        i++;
    printf("Liczba liter wynosi: %d\n", i);

    newstring = (char*)malloc((i+1)* sizeof(char));
    i--;
    int j=0, k=0;
    for(j=i; j>=0; j--)
    {
        newstring[k]=string[j];
        ++k;
    }
    newstring[++i]='\0';
    printf("Po odwroceniu wyraz ma postac: %s\n", newstring);
}

A tak poza tym:
- jeśli w wyrazie "kowalski" jest 8 liter, to za pomocą malloc() musisz przydzielić pamięć na 9 znaków (8 liter + NULL).

komentarz 18 grudnia 2015 przez Int_main Bywalec (2,850 p.)
edycja 18 grudnia 2015 przez Int_main

Dzięki za pomoc, tak mi właśnie świtało, że musi to być coś z nullem, ale nie wiedziałem, że w mallocu go pominąłem. Dzięki za dokładne objaśnienie.
Swoją drogą czytałem, że bezpieczniej jest alokować pamięć:
 

newstring = (char*)malloc((i+1) * sizeof(*newstring));

 

Nie uważasz, że
 

newstring[++i]='\0';

można zamienić na:

newstring[k]='\0';

wydaje mi się jaśniejsze.

komentarz 18 grudnia 2015 przez Krawiec91 Pasjonat (19,600 p.)
Nie wiem w jakim sensie bezpieczniej... Wzoruje się na zapisie z "Język C. Szkoła Programowania" Praty. To już najmniejszy problem.
Nulla nie uwzględniłeś przy alokowaniu pamięci to raz, a dwa, że nie dodawałeś go do odwróconego stringa.
Co do indeksu, to tak go prosto z marszu wstawiłem, jak sprawdzałem czy program chodzi. Żadnej większej ideologii do tego nie ma co dopisywać.;). Faktycznie dość niefortunnie wybrałem zmienną do tego.;)
komentarz 19 grudnia 2015 przez Int_main Bywalec (2,850 p.)
Nie dodałem nulla do odwróconego stringa, bo sądziłem, że to się dzieje domyślnie.
Zatem w przypadku, gdy stringa przepisywałbym do newstring[10], to wtedy null znajduje się na 10 pozycji i przy załozeniu, że string jest krótszy niż 10 znaków, to nulla nie musiałbym dopisywać sam, bo byłby domyślnie?

A co do tego indeksu k to po zastanowieniu faktycznie i++ też jest na pewno poprawny i zrozumiały. ;)
komentarz 19 grudnia 2015 przez Krawiec91 Pasjonat (19,600 p.)
Null nie zostanie domyślnie dopisany przy kopiowaniu. Nie kopiujesz stringa jako całości na raz, tylko kopiujesz litera po literze. więc jeśli nie skopiujesz nulla to go tam nie będzie.
Co innego w przypadku wczytywania danych z klawiatury (scanf,gets,fgets), tam string jest kończony nullem z automatu.

Podobne pytania

0 głosów
0 odpowiedzi 267 wizyt
pytanie zadane 27 lutego 2020 w Bezpieczeństwo, hacking przez konradw Nowicjusz (190 p.)
0 głosów
0 odpowiedzi 161 wizyt
pytanie zadane 21 maja 2016 w C i C++ przez Sinnley Stary wyjadacz (12,810 p.)
0 głosów
2 odpowiedzi 708 wizyt
pytanie zadane 17 lipca 2015 w C i C++ przez Bartos Użytkownik (610 p.)

93,720 zapytań

142,644 odpowiedzi

323,266 komentarzy

63,270 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...