Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C: Merkkijonon kääntäminen pointerin avulla

AbuRamal [19.03.2021 16:01:00]

#

#include <stdio.h>

void reverse(char *pointer, int string_length);

int main (void)
{
    char hello_string[] = "Hello World!";
    printf("%s\n", hello_string);

    reverse(hello_string, sizeof(hello_string)/sizeof(hello_string[0]));

    printf("%s\n", hello_string);
    return 0;
}

void reverse(char *pointer, int string_length){
    int alku = 0;
    int loppu = string_length -1;
    char merkki;
    for(int i = 0; i < string_length; i++){

        merkki = pointer[loppu];
        pointer[loppu] = pointer[alku];
        pointer[alku] = merkki;

        loppu--;

        alku = i;

        if(i == (string_length / 2)){
            break;
        }
    }
}

Opettelen C-kieltä ja eteen tuli tehtävä, jossa täytyy kääntää(reverse) merkkijono käyttäen pointereita(reverse-funktion toteutus). Yllä oleva koodi toimii... melkein.

Ongelma on siinä, että ensimmäinen(tai viimeinen) kirjain jää pois lopputuloksesta. Ilmeisesti tämä johtuu siitä, että koodi käy kaksi kertaa nollannen indeksin läpi. Itse epäselvyys on se, ettei koodi tulosta mitään jos asetan i:n arvoksi 1 for-silmukan määrittelyssä.

Miksi näin taphatuu? Mistä ilmiö johtuu? Miten saan koodin "toimimaan"? Vinkkejä ja vihjeitä aloittelevalle C-koodarille?

Metabolix [19.03.2021 16:49:27]

#

Ongelma on siinä, että taulukon koko (jonka myös sizeof antaa) on yhden suurempi kuin tekstin merkkien määrä, koska tekstin lopussa on nollatavu lopetuksen merkkinä. Kääntö ei voi toimia järkevästi, kun tekstin pituus on väärin. Käytä sizeof-kikkojen sijaan strlen-funktiota pituuden selvittämiseen.

Ja tosiaan silmukassa pitäisi korottaa alku-muuttujaa, ei sijoittaa i:tä siihen. Nollaindeksin käsittely kahteen kertaan aiheuttaa kuvaamasi virheen, että yksittäinen merkki putoaa pois; tuurilla se myös ”korjaa” sen virheen, jossa kopioit lopetusmerkin ensimmäiseksi ja merkkijono näyttää tyhjältä.

Selvempi muoto silmukalle olisi:

while (alku < loppu) {
  // ...
  alku++;
  loppu--;
}

Tai sitten jätä alku ja loppu pois ja käytä for-silmukassasi vain indeksejä i ja pituus-i-1.

AbuRamal [19.03.2021 18:13:13]

#

Metabolix kirjoitti:

(19.03.2021 16:49:27): Ongelma on siinä, että taulukon koko (jonka...

Taisin ensimmäisessä viestissä ilmaista asian hieman epäselvästi, mutta tosiaan tehtävässä ei saa/voi main-metodia muokata. Itsekkin ihmettelin tuota sizeof kikkailua. Pitää ilmeisesti jotain tähän vielä kehitellä.

peran [19.03.2021 18:22:11]

#

Voithan strlen:n avulla laskea merkkijonon pituuden.

Metabolix [19.03.2021 18:22:58]

#

AbuRamal kirjoitti:

tehtävässä ei saa/voi main-metodia muokata.

Silloin voit tietenkin (a) käyttää funktiossasi strnlen-funktiota* todellisen pituuden selvittämiseen, tai (b) vähentää annetusta pituudesta yhden sillä oletuksella, että parametri on säännöllisesti annettu juuri tuolla tavalla väärin.

*) Funktio strnlen huomioi myös annetun maksimipituuden, jotta ei tule ylivuotoa, vaikka parametri olisi virheellisesti muu kuin nollatavuun loppuva merkkijono. Harjoitustehtävässä sopii varmasti myös strlen, mutta tosielämässä on syytä olla tarkkana, ettei tule vaarallisia bugeja tästä asiasta.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta