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;
}
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;
}
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 :(
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.
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.
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.
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.