Dlaczego ten kawałek kodu wywołuje segmentation fault?

2011-08-09 21:49
0

Cześć,

Miałem za zadanie skopiowanie zawartości z jednej tablicy znaków do dwóch innych tak, żeby w jednej znajdowały się same wyrazy parzyste, a w drugiej same nieparzyste, po każdym zaś wyrazie miała być spacja. Z problemem już sobie poradziłem, jednakże ciągle zastanawia mnie, dlaczego ten kawałek kodu powodował segmentation fault oraz dlaczego instrukcja break nie wyskakiwała z tej pętli for, byłbym wdzięczny, gdyby ktoś mógłby mi to mógł wytłumaczyć.

#include <iostream>
void string_kopia(char zrodlo[], char parzyste[], char nieparzyste[]);
void wyswietl(char tabl[], int ile);
using namespace std;
const int rozmiar = 120;

int main(int argc, char** argv)
{
    char wypowiedz[rozmiar] = {"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eu."};
    char parz[rozmiar] = {};
    char nieparz[rozmiar] = {};
   string_kopia(wypowiedz, parz, nieparz);
    wyswietl(wypowiedz, 80);
    cout << endl;
    wyswietl(parz, 80);
    cout << endl;
    wyswietl(nieparz, 80);
    cout << endl;
   return 0;
}
void string_kopia(char zrodlo[], char parzyste[], char nieparzyste[])
{
    int ktory = 0, n =0, p = 0;
   for(int i = 0; i < rozmiar && zrodlo[i] != '0'; i++)
   {
       if(ktory % 2)
       {
           do{
           if(zrodlo[i] == '0') break;
           nieparzyste[n] = zrodlo[i];
           cout << "a teraz niep: " << nieparzyste[n] << endl;
           n++;
           }while(zrodlo[i++] != ' ' );
       }
       else
       {
           do{
            if(zrodlo[i] == '0') break;
           parzyste[p] = zrodlo[i];
           cout << "a teraz parz: " << parzyste[p] << endl;
           p++;
           }while(zrodlo[i++] != ' ');
       }
       if(zrodlo[i] == '0') break;
       ktory++;
       cout << "Zmienna ktory: " <<  ktory << endl;
   }
}
void wyswietl(char tabl[], int ile)
{
    for(int i = 0; i < ile; i++)
    {
        cout << tabl[i];
    }
}

Pozostało 580 znaków

2011-08-09 22:04

W tych warunkach powinno być raczej ... == '\0' - porównujesz ze znakiem końca stringu a nie za znakiem 0.


Pozostało 580 znaków

2011-08-09 22:11
0

Oczywiście, zgadzam się z Tobą, ale czy to nie jest tak, że jeżeli zainicjalizuję tablicę w ten sposób:

char tablica[8] = {"abcde" }

To tablica[6] i tablica[7] będą równe zero?

Pozostało 580 znaków

2011-08-09 22:17
0

Tu masz segfala bo inicjalizujesz tablicę charów tablicą tablic charów.


Ale, że gdzie jest ta tablica tablic?:| Że niby "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eu." to tablica tablic?:| Możesz troszkę jaśniej? - transient 2011-08-09 22:22
char tablica[] = &quot;abcd&quot;; == char tablica[] = {'a', 'b', 'c', 'd', '\0'}; Natomiast char tablica[][] = {&quot;abcd&quot;}; == char tablica[][] = {{'a', 'b', 'c', 'd', '\0'}}; - hauleth 2011-08-09 23:00

Pozostało 580 znaków

2011-08-09 22:17
0

Ogólnie masz wielki syf w kodzie...

  1. Tak jak napisał @byku_guzio musisz zmienić na '\0' lub na 0
  2. Tu masz poprawiony kod:
    
    #include <iostream>

using namespace std;

void string_kopia(char zrodlo[], char parzyste[], char nieparzyste[]);
const int rozmiar = 120;

int main()
{
char wypowiedz[rozmiar] = {"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eu."};
char parz[rozmiar];
char nieparz[rozmiar];

string_kopia(wypowiedz, parz, nieparz);
cout << "Wypowiedź: " << wypowiedz << "\nParzyste: " << parz << "\nNieparzyste: " << nieparz << endl;

return 0;

}
void string_kopia(char zrodlo[], char parzyste[], char nieparzyste[])
{
int ktory = 0, n = 0, p = 0;

for(int i = 0; ; i++)
{

   if(ktory % 2)
   {
       do{
           nieparzyste[n] = zrodlo[i];
           i++;
           n++;
       }while(zrodlo[i] != ' ' && zrodlo[i] != 0);

       nieparzyste[n++] = ' ';
   }

   else
   {
       do{
           parzyste[p] = zrodlo[i];
           i++;
           p++;
       }while(zrodlo[i] != ' ' && zrodlo[i] != 0);

           parzyste[p++] = ' ';
   }

   if(zrodlo[i] == 0) 
      break;

      ktory++;

}
}



Trochę jaśniej napisany ;)

3. Inne elementy będą zerami ale nie takimi: '0'. Ponieważ to '0' oznacza znak (zrzutuj go do int to wtedy zobaczysz że to nie jest znak o kodzie 0) a nam chodzi po prostu o null.
edytowany 3x, ostatnio: Szewy, 2011-08-09 22:21
Wiesz, ja nie chciałem, aby ktokolwiek poprawiał ten kod, bo wiem że jest beznadziejnie napisany, tylko żeby mi wytłumaczył, co tego seg faulta powodowało :) Bo problem rozwiązałem już wcześniej, w trochę inny sposób niż Ty, ale mimo wszystko dzięki :) - transient 2011-08-09 22:27

Pozostało 580 znaków

2011-08-09 22:58
0
  1. Inne elementy będą zerami ale nie takimi: '0'. Ponieważ to '0' oznacza znak (zrzutuj go do int to wtedy zobaczysz że to nie jest znak o kodzie 0) a nam chodzi po prostu o null.

No to ja już nie wiem, w takim wypadku ten cytat z symfonii to brednie, tak:

Symfonia 7.5: "(...)dlatego lepiej w nowych programach stosować zamiast niego z0 (zero), bo taki jest właśnie kod ASCII znaku null"
?

No i jeszcze jedna sprawa, co z taką inicjalizacją:

char zdanie[80] = { 'l', 'o', 't'} - czy to jest C-string czy nie? Bo Grębosz napisał, że tak (ponieważ reszta elementów zawierających się w tej tablicy będzie wypełniona zerami). Pogubiłem się ;|

EDIT: Dobra, już wiem - zarówno to, co Ty napisałeś, jak i to, co Grębosz napisał, to prawda. Nie widziałem tej subtelnej różnicy pomiędzy zrodlo[i] != 0 a zrodlo[i] != '0' (gdzie w pierwszym przypadku przyrównujemy do wartości zero, gdzie właśnie tak null jest kodowany, a w drugim do znaku 0).

Temat do zamknięcia :)

edytowany 1x, ostatnio: transient, 2011-08-09 23:01

Pozostało 580 znaków

2011-08-09 23:03
0

Bo '0' == 48 a '\0' == 0. O to Gręboszowi chyba chodziło.


Pozostało 580 znaków

Liczba odpowiedzi na stronę

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