malloc()-ongelma

No niin, taas sitä ollaan täällä :) Pitäisi tehdä funktio joka kysyy merkkijonon pituutta eli kuinka monelle merkille varataan tilaa. Tämä annetaan funktioon parametrinä ja funktiossa pyydetään käyttäjää syöttämään maximissaan varatun tilan pituinen merkkijono. Funktio palauttaa kyseisen merkkijonon.

Eli miten tuo mallocin käyttö pitäisi tässä hoitaa? Eli siinähän pitäisi tarkistaa myös että onnistuiko tuo muistin varaus, mutta eihän se oikeen toimi jos tuo *luemj-funktio palauttaa -1:n(siksi kommentoin sen if-lauseen nyt toistaiseksi pois). Ja nyt muutenkaan ko. funktio ei toimi niinkuin pitäisi.. se ohittaa kokonaan tuon fgets()-funktion, joten *luemj funktio ei palauta mitään arvoa.

#include
#include

char *luemj(int max);

int main(void){

int n;
char *p;

printf("Anna merkkijonon maksimipituus (n merkkiä): ");
scanf("%d",&n);

p=luemj(n);

printf("\nLuettu merkkijono on %s\n",p);

free(p);

return 0;

}

char *luemj(int max){

char *mj;

mj = (char *)malloc( sizeof(char)*(max 2) );
/*if ( mj==NULL ){
printf("Muistinvaraus epäonnistui\n");
return -1;
}*/
printf("Syötä merkkijono (max %d merkkiä):",max);
fgets(mj,max 2,stdin);

return mj;
}
7428
Äänestä

Muut lukivat myös

Vastaukset 7

Vanhimmat

Aika lähellä oot lopputulosta. fflush -funktiota tarvitsee käytellä komentorivillä, jotta tietää varmuudella, että edellinen haku (scanf,fgets) on nielaissut kaikki merkit. Virhetilanteissa NULL eli 0 on parempi paluuarvo funktiosta. Tässä on tosin 'pielessä' se sama mikä viimeksi eli sallii vähän pitemmän lopputuloksen:

#include
#include

char *luemj(int max);

int main(void){

int n;
char *p;

printf("Anna merkkijonon maksimipituus (n merkkiä): ");
scanf("%d",&n);

p=luemj(n);
if(p){
printf("\nLuettu merkkijono on %s\n",p);
free(p);
}

return 0;

}

char*luemj(int max){

char *mj;

mj = (char *)malloc( sizeof(char)*(max+2) );
if ( mj==NULL ){
printf("Muistinvaraus epäonnistui\n");
return NULL;
}
printf("Syötä merkkijono (max %d merkkiä):",max);
fflush(stdin);
fgets(mj,max+2,stdin);

return mj;
}

Että osaa olla surkea sivu ku hukkaa hyvän muotoilun koodista :(

Äänestä
  • Joo paljon kiitosta jälleen kerran :)

    hmm.. kursillamme ei ole kyllä käsitelty ollenkaan fflush -funktiota. eli olisiko tuohon vielä joku muu ratkaisutapa?

    Sitten tuo toinen ongelma (jälleen kerran :)
    Eli kun sanoit:"Tässä on tosin 'pielessä' se sama mikä viimeksi eli sallii vähän pitemmän lopputuloksen" Niin miten tuo malloc pitäisi sitten toteuttaa että noin ei olisi, koska kai tässäkin pitää varata rivinvaihtomerkille ja loppumerkille tila?

    Niin tässä vielä alkuperäinen tehtävänanto:
    toteuta funktio, jonka prototyyppi on
    char *luemj(int max);
    funktio palauttaa korkeintaan max merkkiä pitkän käyttäjän antaman syötemerkkijonon. Tee pääohjelma joka testaa funktion toiminaa.


    Joo.. rasittavaa kyllä kun ei saa tota muotoilua säilytettyä :/

    Äänestä

  • jumissa kirjoitti:

    Joo paljon kiitosta jälleen kerran :)

    hmm.. kursillamme ei ole kyllä käsitelty ollenkaan fflush -funktiota. eli olisiko tuohon vielä joku muu ratkaisutapa?

    Sitten tuo toinen ongelma (jälleen kerran :)
    Eli kun sanoit:"Tässä on tosin 'pielessä' se sama mikä viimeksi eli sallii vähän pitemmän lopputuloksen" Niin miten tuo malloc pitäisi sitten toteuttaa että noin ei olisi, koska kai tässäkin pitää varata rivinvaihtomerkille ja loppumerkille tila?

    Niin tässä vielä alkuperäinen tehtävänanto:
    toteuta funktio, jonka prototyyppi on
    char *luemj(int max);
    funktio palauttaa korkeintaan max merkkiä pitkän käyttäjän antaman syötemerkkijonon. Tee pääohjelma joka testaa funktion toiminaa.


    Joo.. rasittavaa kyllä kun ei saa tota muotoilua säilytettyä :/

    > hmm.. kursillamme ei ole kyllä käsitelty ollenkaan
    >fflush -funktiota. eli olisiko tuohon vielä joku
    >muu ratkaisutapa?
    Jos C -kirjaston funktioita miettii, niin eipä kai. Joissain järjestelmissä ei oo tarvis tolle fflush:lle.
    >Niin miten tuo malloc pitäisi sitten toteuttaa että
    >noin ei olisi, koska kai tässäkin pitää varata
    >rivinvaihtomerkille ja loppumerkille tila?
    Ihan toimiva tapa se edellinenkin on. Toinen olisi tehdä esim.for -luupilla sama.

    Äänestä

  • test kirjoitti:

    > hmm.. kursillamme ei ole kyllä käsitelty ollenkaan
    >fflush -funktiota. eli olisiko tuohon vielä joku
    >muu ratkaisutapa?
    Jos C -kirjaston funktioita miettii, niin eipä kai. Joissain järjestelmissä ei oo tarvis tolle fflush:lle.
    >Niin miten tuo malloc pitäisi sitten toteuttaa että
    >noin ei olisi, koska kai tässäkin pitää varata
    >rivinvaihtomerkille ja loppumerkille tila?
    Ihan toimiva tapa se edellinenkin on. Toinen olisi tehdä esim.for -luupilla sama.

    eli eipä toimi vieläkään tämä. Ohjelma kysyy tuota mj:n maksimipituutta ja menee sitten sujuvasti ohjelman loppuun ilman tuon merkkijonon kyselemistä... Missähän vika voisi olla. Siis linuxissa gcc:llä kääntelen.

    #include
    #include

    char *luemj(int max);

    int main(void){

    int n;
    char *p;

    printf("Anna merkkijonon maksimipituus (n merkkiä): ");
    scanf("%d",&n);

    p=luemj(n);

    printf("\nLuettu merkkijono on %s\n",p);

    free(p);

    return 0;

    }

    char *luemj(int max){

    char *mj;

    mj = (char *)malloc( sizeof(char)*(max+2) );
    if ( mj==NULL ){
    printf("Muistinvaraus epäonnistui\n");
    return NULL;
    }
    printf("Syötä merkkijono (max %d merkkiä):",max);
    fflush(stdin);
    fgets(mj,max+2,stdin);


    return mj;
    }

    Äänestä

  • jumissa kirjoitti:

    eli eipä toimi vieläkään tämä. Ohjelma kysyy tuota mj:n maksimipituutta ja menee sitten sujuvasti ohjelman loppuun ilman tuon merkkijonon kyselemistä... Missähän vika voisi olla. Siis linuxissa gcc:llä kääntelen.

    #include
    #include

    char *luemj(int max);

    int main(void){

    int n;
    char *p;

    printf("Anna merkkijonon maksimipituus (n merkkiä): ");
    scanf("%d",&n);

    p=luemj(n);

    printf("\nLuettu merkkijono on %s\n",p);

    free(p);

    return 0;

    }

    char *luemj(int max){

    char *mj;

    mj = (char *)malloc( sizeof(char)*(max+2) );
    if ( mj==NULL ){
    printf("Muistinvaraus epäonnistui\n");
    return NULL;
    }
    printf("Syötä merkkijono (max %d merkkiä):",max);
    fflush(stdin);
    fgets(mj,max+2,stdin);


    return mj;
    }

    Jännä homma, winkkarilla kyllä pelittää. Mulla ei oo linuxia missään asenneltuna, joten en pääse testailee. Kokeile jotakin seuraavista:
    1. katsele antaako fflush(stdin) virheen EOF (jos palauttaa 0, pitäisi toimia)
    2. jos fflush(stdin) korvaisi _flushall()

    Jos mikään noista ei tunnu auttavan, niin kaipa se fgets on sitten korvattava scanf("%s",pc); -tyylillä. Tällöin tarvitset malloc:iin max:n tilalle ison määrän (esim. dossissa maksimi taisi saada maksimissaan 128 merkkiä)->pc. Näin ollen siihen funktion loppuun täytyy lisätä luuppi, jossa lyhennellään teksti oikeanmittaiseksi.

    Äänestä

  • jumissa kirjoitti:

    Joo paljon kiitosta jälleen kerran :)

    hmm.. kursillamme ei ole kyllä käsitelty ollenkaan fflush -funktiota. eli olisiko tuohon vielä joku muu ratkaisutapa?

    Sitten tuo toinen ongelma (jälleen kerran :)
    Eli kun sanoit:"Tässä on tosin 'pielessä' se sama mikä viimeksi eli sallii vähän pitemmän lopputuloksen" Niin miten tuo malloc pitäisi sitten toteuttaa että noin ei olisi, koska kai tässäkin pitää varata rivinvaihtomerkille ja loppumerkille tila?

    Niin tässä vielä alkuperäinen tehtävänanto:
    toteuta funktio, jonka prototyyppi on
    char *luemj(int max);
    funktio palauttaa korkeintaan max merkkiä pitkän käyttäjän antaman syötemerkkijonon. Tee pääohjelma joka testaa funktion toiminaa.


    Joo.. rasittavaa kyllä kun ei saa tota muotoilua säilytettyä :/

    Se fflush (stdin) on huono tapa, vaikka toimii jossakin. Älä käytä sitä. Tässä perustelu:

    http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1052863818&id=1043284351

    Tämä on ihan hyvä yksinkertaisiin ohjelmiin syötönkäsittelyn avuksi.

    void lue_rivi_loppuun (void)
    {
    /* oletamme, että syöttöpuskurissa on käsittelemätöntä syöttöä */

    /* luetaan se pois ja heitetään hukkaan. rivi tunnetusti loppuu rivinvaihtoon, joten sellaisen
    lukemisen jälkeen on rivi käsitelty */

    while (getchar() != '\n') /* tyhjä */ ;

    }

    Tämän käyttäminen oikeassa kohdassa jätetään harjoitukseksi.

    Äänestä

Arvaisin, että se fgets lukaisee sieltä syötteestä sen rivinvaihdon, jonka scanf jätti syöttöpuskuriin. Ks. toinen viestini flush (stdin):istä, miten korjaat tilanteen yhdellä tavalla.

Jos muistinvaraus epäonnistuu, kannattaa palauttaa NULL-pointteri. Jos sen käsittely on työlään ja turhan oloista, yksinkertaisessa ohjelmassa voi nakata hanskat tiskiin ja kutsua exit(EXIT_FAILURE);, että pääsee kärsimyksistään.

Tietty oikea sovellus ei saa lopettaa muistin puutteessa, vaan jotain hätäapua pitää keksiä. Se valittu toiminta on kuitenkin ohjelman tason mukaisesti ratkaistava.

Äänestä

Kommentoi aloitusta


jumissa kirjoitti:

No niin, taas sitä ollaan täällä :) Pitäisi tehdä funktio joka kysyy merkkijonon pituutta eli kuinka monelle merkille varataan tilaa. Tämä annetaan funktioon parametrinä ja funktiossa pyydetään käyttäjää syöttämään maximissaan varatun tilan pituinen merkkijono. Funktio palauttaa kyseisen merkkijonon.

Eli miten tuo mallocin käyttö pitäisi tässä hoitaa? Eli siinähän pitäisi tarkistaa myös että onnistuiko tuo muistin varaus, mutta eihän se oikeen toimi jos tuo *luemj-funktio palauttaa -1:n(siksi kommentoin sen if-lauseen nyt toistaiseksi pois). Ja nyt muutenkaan ko. funktio ei toimi niinkuin pitäisi.. se ohittaa kokonaan tuon fgets()-funktion, joten *luemj funktio ei palauta mitään arvoa.

#include
#include

char *luemj(int max);

int main(void){

int n;
char *p;

printf("Anna merkkijonon maksimipituus (n merkkiä): ");
scanf("%d",&n);

p=luemj(n);

printf("\nLuettu merkkijono on %s\n",p);

free(p);

return 0;

}

char *luemj(int max){

char *mj;

mj = (char *)malloc( sizeof(char)*(max 2) );
/*if ( mj==NULL ){
printf("Muistinvaraus epäonnistui\n");
return -1;
}*/
printf("Syötä merkkijono (max %d merkkiä):",max);
fgets(mj,max 2,stdin);

return mj;
}

Anonyymi
5000

Ilmoita asiaton sisältö

  • Sisältää materiaalia, joka on loukkaavaa, herjaavaa, rasistista, uhkailevaa tai ahdistelevaa.

  • Materiaali sisältää nimiä, yhteystietoja tai muita henkilökohtaisia tietoja. Julkisuuden henkilöistä, julkisissa viroissa toimivista ihmisistä sekä yritysten vastuuhenkilöistä saa keskustella työhön liittyen. Myös yksityiselämään liittyvistä asioista voi keskustella siltä osin, kuin niistä on julkisesti kerrottu.

  • Sisältää lapsille haitallista tai heiltä kiellettyä materiaalia. Seksuaalinen sisältö on sallittua aiheeseen tarkoitetuilla palstoilla, joiden ikäraja on 18 vuotta.

  • Lainvastaista sisältöä voi olla mm. yksityiselämää loukkaavan tiedon levitys, kiihottaminen kansanryhmää vastaan, laiton uhkaaminen, alaikäisiin liittyvä seksuaalinen sisältö/grooming, petokset, identiteettivarkaudet, kunnianloukkaukset ja tekijänoikeusrikkomukset.

  • Sisältö ei liity palstan tai keskusteluketjun aiheeseen.

  • Viesti ei ole suomea tai ruotsia (pl. International Forums), se sisältää mainontaa, se sisältää tekijänoikeuksin suojattua materiaalia, se on massapostitus tai jokin muu syy.

Jaa keskustelu