onko tässä jotain väärin

tai "epämääräisesti"

#include
#include

int main(void)
{

char etunimi[15]; // etunimi voi olla 15 merkkiä
char sukunimi[20]; // sukunimi 20 merkkiä
char tiedosto_nimi[12];

printf("Ohjelma tallentaa etunimesi ja sukunimesi tiedostoon.\n");
printf("Syötä etunimesi:");
scanf("%s",&etunimi[0]);
printf("Syötä sukunimesi:");
scanf("%s",&sukunimi[0]);
printf("Tiedosto johon haluat tallentaa nimesi:");
scanf("%s",&tiedosto_nimi[0]);


FILE *avaus;
char *tiedoston_nimi = tiedosto_nimi;
char *avaus_moodi = "w";
avaus = fopen(tiedoston_nimi, avaus_moodi);

if(avaus == NULL)
{
printf("Tiedoston avauksessa on tapahtunut virhe!");

return 0;
}
else
{
fprintf(avaus, "%s %s", etunimi, sukunimi);
fclose(avaus);
printf("\nTallennus onnistui!");    
}

getche();
return 0;

}

11

937

    Vastaukset

    Anonyymi (Kirjaudu / Rekisteröidy)
    5000
    • dx2

      Voisi ainakin kääntäjä tykätä parempaa jos poistat tuon rivin:

      char *tiedoston_nimi = tiedosto_nimi;

      koska ei ole hyvä idea määritellä montaa samannimistä muuttujaa. Ja jos käytät ANSI-C-kääntäjää, niin joudut myös siirtämään nämä rivit heti tuon tiedosto_nimi[12]-rivin jälkeen:

      FILE *avaus;
      char *avaus_moodi = "w";

      Itse myös poistaisin tuon rivin kun se ei ole ANSI-C:tä:

      getche();

      ja samalla myös sen -rivin. Joskin kyllä tuo getche() voi auttaa tulostuksen näkemistä joissain epämääräisissä kääntäjissä, jossa konsoli-ikkuna sulkeutuu heti ohjelman päättymisen jälkeen.

      • käytössä

        niin pakko jollain pysäyttää, siksi tuo getche().

        Voishan siihen tietenkin vissiin laittaa pause tai jotain muuta.


      • jatkoa

        char *tiedoston_nimi = tiedosto_nimi;

        ei ole saman niminen muuttuja (?)

        Voiko tuon tiedoston nimen (char *tiedoston_nimi)
        viedä suoraan tuona tiedosto_nimi -muuttujana, jonka ohjelma kysyy käyttäjältä?


      • voi...
        jatkoa kirjoitti:

        char *tiedoston_nimi = tiedosto_nimi;

        ei ole saman niminen muuttuja (?)

        Voiko tuon tiedoston nimen (char *tiedoston_nimi)
        viedä suoraan tuona tiedosto_nimi -muuttujana, jonka ohjelma kysyy käyttäjältä?

        Voi:
        avaus = fopen(tiedosto_nimi, "w");

        Koska taulukon nimi toimii myös osoittimena. Samasta syystä myös tämä käy:
        scanf("%s", etunimi);

        Tuolta löytyy asiaan jotain selitystä:
        http://www.nic.funet.fi/c opas/osoittimet.html

        Osoittimia pitää C:ssä tankata niin kauan että ne tosiaan osaa ja tajuu.

        Mitäs muuten tapahtuu kun syöttää etunimeen yli 15 merkkiä?


      • jossain muussa ehkä tapahtuu
        voi... kirjoitti:

        Voi:
        avaus = fopen(tiedosto_nimi, "w");

        Koska taulukon nimi toimii myös osoittimena. Samasta syystä myös tämä käy:
        scanf("%s", etunimi);

        Tuolta löytyy asiaan jotain selitystä:
        http://www.nic.funet.fi/c opas/osoittimet.html

        Osoittimia pitää C:ssä tankata niin kauan että ne tosiaan osaa ja tajuu.

        Mitäs muuten tapahtuu kun syöttää etunimeen yli 15 merkkiä?

        Ei tapahdu mitään Dev-Cpp:ssä vaan ottaa ne ylimääräisetkin merkit talteen, kun kokeilin.

        Joku toinen IDE ei välttämättä tykkää.


      • TRRY
        jossain muussa ehkä tapahtuu kirjoitti:

        Ei tapahdu mitään Dev-Cpp:ssä vaan ottaa ne ylimääräisetkin merkit talteen, kun kokeilin.

        Joku toinen IDE ei välttämättä tykkää.

        Ensimmäinen kuolemansynti on scanf("%s", ...). scanf:lle pitää kertoa, kuinka monta merkkiä sille annetun osoittimen päässä on muistia käytettävissä tallennettavalle merkkijonolle. Jos tätä ei kerrota, data tallennetaan mahdollisesti muuhun käyttöön tarkoitetulle muistialueelle, ja seuraukset ovat arvaamattomat.

        Toisin sanoen rivin "scanf("%s",&etunimi[0]);" pitäisi olla "scanf("%14s", etunimi);" (14 siksi, että 15. merkki pitää jättää merkkijonon lopputavulle.)

        Toinen kuoleman synti, on scanf:n paluuarvojen tarkastamatta jättäminen. scanf palauttaa EOFin, jos syötettä ei saada luettua. Jos suoritat ohjelman komennolla

        echo "Erkka" | ohjelma.exe

        niin se yrittää tyytyväisenä avata määrittelemättömän nimistä tiedostoa (joskus saattaa onnistuakin!) tallentaakseen sinne Erkka-etunimen ja määrittelemättömän sukunimen.

        Kolmas synti (ei ehkä enää kuoleman sellainen) on kirjoitettavan tiedoston nimen tarkastamatta jättäminen. Turvallisuussyistä olisi paikallaan varmistaa, onko annettu tiedosto olemassa. Käyttäjä voi "vahingossa" ylikirjoittaa omia tai jopa järjestelmän tiedostoja. Myös varatut tiedostonimet kuten Windowsissa CON, PRN, COM1 yms. voivat tuottaa yllättäviä tuloksia. *nix-ympäristössä puolestaan /dev/x:t ovat myös jännittäviä tiedostoja, ja esim. pipe-tiedostoon kirjoittaminen pysäyttää ohjelman kunnes pipe luetaan (tämä voi olla haluttuakin).

        Neljäs synti on tulostaa "Tallennus onnistui" vaikkei asia olisikaan niin. Tämä taas johtuu siitä, ettei fprintf:nkään paluuarvoa tarkasteta. Tiedostoon kirjoittaminen ei välttämättä onnistu, vaikka se olisikin pystytty avaamaan write-tilaan. Esimerkiksi levyssä voi olla vikaa tai se voi olla täysi.

        Näiden syntien lisäksi siistimpää (niponipo) olisi käyttää stdlibin getcharia ja return EXIT_SUCCESS:ia kuin jonkin epästandardin conio:n getche:a ja return 0:aa.


      • ...vielä
        TRRY kirjoitti:

        Ensimmäinen kuolemansynti on scanf("%s", ...). scanf:lle pitää kertoa, kuinka monta merkkiä sille annetun osoittimen päässä on muistia käytettävissä tallennettavalle merkkijonolle. Jos tätä ei kerrota, data tallennetaan mahdollisesti muuhun käyttöön tarkoitetulle muistialueelle, ja seuraukset ovat arvaamattomat.

        Toisin sanoen rivin "scanf("%s",&etunimi[0]);" pitäisi olla "scanf("%14s", etunimi);" (14 siksi, että 15. merkki pitää jättää merkkijonon lopputavulle.)

        Toinen kuoleman synti, on scanf:n paluuarvojen tarkastamatta jättäminen. scanf palauttaa EOFin, jos syötettä ei saada luettua. Jos suoritat ohjelman komennolla

        echo "Erkka" | ohjelma.exe

        niin se yrittää tyytyväisenä avata määrittelemättömän nimistä tiedostoa (joskus saattaa onnistuakin!) tallentaakseen sinne Erkka-etunimen ja määrittelemättömän sukunimen.

        Kolmas synti (ei ehkä enää kuoleman sellainen) on kirjoitettavan tiedoston nimen tarkastamatta jättäminen. Turvallisuussyistä olisi paikallaan varmistaa, onko annettu tiedosto olemassa. Käyttäjä voi "vahingossa" ylikirjoittaa omia tai jopa järjestelmän tiedostoja. Myös varatut tiedostonimet kuten Windowsissa CON, PRN, COM1 yms. voivat tuottaa yllättäviä tuloksia. *nix-ympäristössä puolestaan /dev/x:t ovat myös jännittäviä tiedostoja, ja esim. pipe-tiedostoon kirjoittaminen pysäyttää ohjelman kunnes pipe luetaan (tämä voi olla haluttuakin).

        Neljäs synti on tulostaa "Tallennus onnistui" vaikkei asia olisikaan niin. Tämä taas johtuu siitä, ettei fprintf:nkään paluuarvoa tarkasteta. Tiedostoon kirjoittaminen ei välttämättä onnistu, vaikka se olisikin pystytty avaamaan write-tilaan. Esimerkiksi levyssä voi olla vikaa tai se voi olla täysi.

        Näiden syntien lisäksi siistimpää (niponipo) olisi käyttää stdlibin getcharia ja return EXIT_SUCCESS:ia kuin jonkin epästandardin conio:n getche:a ja return 0:aa.

        Vielä ainakin yksi ongelma eli stdin-puskuriin jää merkkejä jos niitä syötetään enemmän kuin scanf hakee, joten se pitää tyhjentää (ehkäpä) näin:

        while((c = getchar()) != '\n' && c != EOF);

        http://c-faq.com/stdio/stdinflush2.html

        Koska scanf:n käyttö menee näin monimutkaiseksi ja riskaabeliksi, niin järkevää olisi kai käyttää valmista kirjastoa apuna. Jotain tollaisia:

        http://tiswww.case.edu/php/chet/readline/rltop.html
        http://www.astro.caltech.edu/~mcs/tecla/index.html
        http://www.thrysoee.dk/editline/

        Samalla saa mukaan muita 'herkkuja'.

        Scanf:stä tietoa:
        http://en.wikipedia.org/wiki/Scanf

        (hmm.. wikipedian mukaan GNU readline on buginen ja rajoittunut.)


      • pitääpä pähkäillä ja kokeilla
        ...vielä kirjoitti:

        Vielä ainakin yksi ongelma eli stdin-puskuriin jää merkkejä jos niitä syötetään enemmän kuin scanf hakee, joten se pitää tyhjentää (ehkäpä) näin:

        while((c = getchar()) != '\n' && c != EOF);

        http://c-faq.com/stdio/stdinflush2.html

        Koska scanf:n käyttö menee näin monimutkaiseksi ja riskaabeliksi, niin järkevää olisi kai käyttää valmista kirjastoa apuna. Jotain tollaisia:

        http://tiswww.case.edu/php/chet/readline/rltop.html
        http://www.astro.caltech.edu/~mcs/tecla/index.html
        http://www.thrysoee.dk/editline/

        Samalla saa mukaan muita 'herkkuja'.

        Scanf:stä tietoa:
        http://en.wikipedia.org/wiki/Scanf

        (hmm.. wikipedian mukaan GNU readline on buginen ja rajoittunut.)

        Ok, pitääpä pähkäillä noita kommentteja ja neuvoja. Tosiaan vielä perusteita opiskelemassa niin ei ihan vielä kaikki hallinnassa. Tosin aina välillä tulee niitä hetkiä joilloin itsekin tajuaa " entäs jos..." ja kun ei tiedä oikein noita mahdollisuuksia niin jää tekemättä. Eikä kyllä aikakaan riittäisi pelkästään C:n harjoituksille, valitettavasti.

        Hitto kun olisi sellainen opettaja/kurssi, jossa käytäisiin just näin läpi tehtäviä. Oppilaat kirjoittaisivat koodin, sitten niistä käytäisiin läpi selkeitä virheitä, arveluttavia toteutustapoja tyyliin "mitä tapahtuu" jos. Sitten noiden korjaamisen tapooihin annettaisiin vähän vinkkiä.

        Onko muuten olemassa kirjaa, jossa olisi esitelty tyyliin "EI MISSÄÄN TAPAUKSESSA NÄIN"?


      • ..vielä
        ...vielä kirjoitti:

        Vielä ainakin yksi ongelma eli stdin-puskuriin jää merkkejä jos niitä syötetään enemmän kuin scanf hakee, joten se pitää tyhjentää (ehkäpä) näin:

        while((c = getchar()) != '\n' && c != EOF);

        http://c-faq.com/stdio/stdinflush2.html

        Koska scanf:n käyttö menee näin monimutkaiseksi ja riskaabeliksi, niin järkevää olisi kai käyttää valmista kirjastoa apuna. Jotain tollaisia:

        http://tiswww.case.edu/php/chet/readline/rltop.html
        http://www.astro.caltech.edu/~mcs/tecla/index.html
        http://www.thrysoee.dk/editline/

        Samalla saa mukaan muita 'herkkuja'.

        Scanf:stä tietoa:
        http://en.wikipedia.org/wiki/Scanf

        (hmm.. wikipedian mukaan GNU readline on buginen ja rajoittunut.)

        On tietysti vielä tämä:
        http://en.wikipedia.org/wiki/Fgets

        Joka tapauksessa scanf:ää EI KANNATA KÄYTTÄÄ stdin-virran lukemiseen.


      • juuu...
        pitääpä pähkäillä ja kokeilla kirjoitti:

        Ok, pitääpä pähkäillä noita kommentteja ja neuvoja. Tosiaan vielä perusteita opiskelemassa niin ei ihan vielä kaikki hallinnassa. Tosin aina välillä tulee niitä hetkiä joilloin itsekin tajuaa " entäs jos..." ja kun ei tiedä oikein noita mahdollisuuksia niin jää tekemättä. Eikä kyllä aikakaan riittäisi pelkästään C:n harjoituksille, valitettavasti.

        Hitto kun olisi sellainen opettaja/kurssi, jossa käytäisiin just näin läpi tehtäviä. Oppilaat kirjoittaisivat koodin, sitten niistä käytäisiin läpi selkeitä virheitä, arveluttavia toteutustapoja tyyliin "mitä tapahtuu" jos. Sitten noiden korjaamisen tapooihin annettaisiin vähän vinkkiä.

        Onko muuten olemassa kirjaa, jossa olisi esitelty tyyliin "EI MISSÄÄN TAPAUKSESSA NÄIN"?

        "Onko muuten olemassa kirjaa, jossa olisi esitelty tyyliin "EI MISSÄÄN TAPAUKSESSA NÄIN"?"

        En tiedä kirjasta mutta C FAQ:
        http://c-faq.com/index.html

        Paras kirja suomeksi lienee: C ohjelmointi Kernighan, Brian W. ; Ritchie, Dennis M.


      • ..vielä
        ..vielä kirjoitti:

        On tietysti vielä tämä:
        http://en.wikipedia.org/wiki/Fgets

        Joka tapauksessa scanf:ää EI KANNATA KÄYTTÄÄ stdin-virran lukemiseen.

        Ööö... komento takaisin. Eihän tossa fgets:ssä ole mitään käytännön eroa tuohon scanf("s", str); Puskuriin jää kamaa molemmissa.

        Jos tota aiemmin mainittua readline-juttua ei voi käyttää niin on getline (Dev-Cpp kai mukana):
        http://crasseux.com/books/ctutorial/getline.html

        Myös numerot pitää käpistellä getline/readline sscanf:
        http://crasseux.com/books/ctutorial/sscanf.html


    Ketjusta on poistettu 0 sääntöjenvastaista viestiä.

    Luetuimmat keskustelut

    1. 6 kW saunan lämmityksestä kohta 10 euron lisämaksu / kerta

      Kokoomuslainen sähköyhtiöiden hallitsema Energiavirasto ehdottaa 5 kW:n rajaa, jonka ylittämisestä tulee lisämaksu. Tark
      Maailman menoa
      208
      6659
    2. Minja jytkyttää vas.liiton kannatusta ylöspäin

      Alkaa raavaat duunarimiehetkin palaamaan vasemmistoliiton kannattajiksi. Eduskunnassahan on vain kaksi työntekijöiden p
      Maailman menoa
      290
      4583
    3. "Mitä sä nainen tuot sitten pöytään" ?

      Jos mies provaidaa ja suojelee... Pitääkö miesten kysyä tuollaisia?
      Ikävä
      142
      3595
    4. Duunarit hylkäsivät vasemmistoliiton, siitä tuli feministinaisten puolue

      Pääluottamusmies Jari Myllykoski liittyi vasemmistoliittoon, koska se oli duunarien puolue. Sitä samaa puoluetta ei enää
      Maailman menoa
      113
      3420
    5. Ekologinen kommunismi tulee voittamaan fossiilikapitalismin

      Kiina on mahtitekijä uusiutuvien energialähteiden kehityksessä, ja Trump osoitus viimeisestä öljyn perään itkemisestä, m
      Maailman menoa
      67
      3405
    6. Mies, kerro minulle vielä jotakin aivan uniikkia

      ja ainutlaatuista minkä vain me kaksi voisimme ymmärtää jos olemme sen kokeneet ja eläneet, jotta ihan varmasti tietäisi
      Tunteet
      49
      2876
    7. Hyviäkin uutisia tulossa, hallinto-oikeus asettaa toimeenpanokieltoon

      Hyvinvointitalon työmaa pysähtyy. Rillankivi+energia ja vesi kytkyrahanpesu stoppaa. Tytäryhtiöiden hallitusjäsenet+kon
      Pyhäjärvi
      258
      2590
    8. Oikeistopuolueiden kannatus vain 37,8 %, vasemmiston 43,0 %

      Keskustaan jää 17,4 prosenttia ja loput ovat sitten mitä ovat. Mutta selvästikin Suomen kansa on vasemmalle kallellaan.
      Maailman menoa
      75
      2427
    9. Tiedän ettei

      Meistä mitään tule. Toinen oli sinulle tärkeämpi
      Ikävä
      25
      2366
    10. Gallup: Mikä on ollut mielestäsi paras tv-sarja ikinä?

      Gallup: Mikä on ollut mielestäsi paras tv-sarja ikinä? Onko se joku suomalainen viihdepläjäys, brittirikossarja, amerikk
      Tv-sarjat
      101
      1941
    Aihe