Mikähän vika tässä koodissa on?
#include<stdio.h> void muuta_lukua(int x); int main() { int x; printf("Anna luku x:"); scanf("%d", &x); printf("Pääohjelmassa: x = %d\n", x); muuta_lukua(x); printf("Pääohjelmassa: x = %d\n", x); } return 0; }
Ohjelman pitäisi tulostaa näin:
Anna luku x: 3
Pääohjelmassa: x = 3
Aliohjelmassa: x = 6
Pääohjelmassa: x = 3
Saan herjan kohdassa "{ int x; ". Miksi? En ymmärrä mitä vikaa siinä kohdassa on?
Ehkäpä vikana on se että sulla ei ole aliohjelmaa ^ ^
Ainakin itse muuta_lukua-funktio uupuu. Lisäksi main-funktioon on eksynyt ylimääräinen aaltosulun lopetus ennen return-komentoa.
Millainen funktion pitäisi olla?
#include<stdio.h> void muuta_lukua(int x); int main() { int x; printf("Anna luku x:"); scanf("%d", &x); printf("Pääohjelmassa: x = %d\n", x); muuta_lukua(x); printf("Pääohjelmassa: x = %d\n", x); return 0; }
Maajo kirjoitti:
Millainen funktion pitäisi olla?
Se riippuu siitä, mitä sen pitäisi tehdä.
Tarkoitus on kirjoittaa aliohjelma "muuta_lukua". Sen pitäisi vastaanottaa kokonaisluku ja kasvattaa sitä kolmella.
Kirjoita siis puuttuva funktio main-funktion jälkeen. Tuo pelkkä määrittely ei sentään riitä. C-kääntäjä ei tiedä, mitä luvulle pitää tehdä, jos tätä ei lue missään.
Funktion toteutus riippuu siitä, pitääkö muuttujan arvon vaihtua myös pääohjelmassa. Jos pitää, funktiolle täytyy lähettää muuttujan arvon sijasta osoitin siihen. C-oppaan kolmannessa osassa on esimerkki molemmista funktiotyypeistä.
Taidan olla vähän tyhmä, kun en keksi mitä funktiota käyttää? :(
Oppaasta löytyy tällainen koodi:
#include <stdio.h> void arvot(int *a, int *b, int *c); int main(void) { int eka, toka, kolmas; arvot(&eka, &toka, &kolmas); printf("%i %i %i", eka, toka, kolmas); /* tulostus: "12 34 56" */ } void arvot(int *a, int *b, int *c) { *a = 12; *b = 34; *c = 56; }
Tuosta saa helposti sellaisen version, jossa (1) funktio ottaa vain yhden syötteen (poista siis muuttujat b ja c) ja (2) jossa sen sijaan, että *a:n arvoksi laitetaan 12, sen arvoksi laitetaankin *a + 3.
Niin, mitenköhän ne piti tohon koodiin laittaa?
Tällä hetkellä koodi on tällänen:
#include<stdio.h> void muuta_lukua(int x); void arvot(int *a); int main(void) { int eka, x; arvot(&eka); printf("%i", eka); } void arvot(int *a) { *a = 12+3; } printf("Anna luku x:"); scanf("%d", &x); printf("Pääohjelmassa: x = %d\n", x); muuta_lukua(x); printf("Aliohjelmassa: x = %d\n", x); printf("Pääohjelmassa: x = %d\n", x); return 0; }
Mitäs sitten kannattaisi/pitäisi tehdä?
No huh huh. Antti, puuttuu muuten esimerkistäsi return 0;
Ei sitä tiedä miten tuollaista oikein pitäisi auttaa. Jos lukisit C-oppaan ajatuksella ja yrittäisit pysyä ihan perusasioissa mukana. Sitten jos hankkisit kääntäjän (vaikkapa Dev-C++:n, käytä Googlea) ja yrittäisit kääntää ohjelmiasi sillä (etkä jollakin VIOPE:lla), niin voisit saada selville, mikä koodissa mättää. Virheilmoitusten lukeminen on hyväksi. Eihän tuo edes kääntyisi. Tuo koodi arvot-funktion sulkevan aaltosulun jälkeen ei kuulu edes mihinkään funktioon.
Kun muokkaa tuota oppaasta otettua koodinpätkää, saa aikaan tällaista:
#include <stdio.h> /* void arvot(int *a, int *b, int *c); Tästä poistetaan b ja c, jolloin: */ void arvot(int *a); int main(void) { /* Kaikista poistetaan "toka" ja "kolmas" */ int eka; /* Tähän lisätään arvon lukeminen */ scanf("%d", &eka); /* Tässä kutsutaan sitä funktiota */ arvot(&eka); /* Tässä tulostetaan saatu luku ruudulle */ printf("%d\n", eka); return 0; } /* Täältäkin poistettiin b:t ja c:t */ void arvot(int *a) { /* *a = 12; Sen sijaan, että laitetaan *a:n arvoksi 12, laitetaan sen arvoksi *a + 3 */ *a = *a + 3; }
Jokohan tuolla pärjäisi? Itse varmaankin keksit, miten voit muuttaa muuttujan tai funktion nimeä? Muistathan muuttaa sen jokaisesta kohdasta.
Niin ja jos funktion ei pitänyt nostaa sen arvoa lopullisesti, niin sitten tuosta voi poistaa neljä tähteä ja yhden &-merkin. Arvaa itse, mitkä tähdet ja minkä &-merkin :)
Jos minä joudun ikinä tekemään tehtäviä jollakin VIOPE:lla, yritän varmasti tehdä ne varmasti helpolla tavalla:
#include <stdio.h> int main(void) { printf("Anna luku x: 3\nPääohjelmassa: x = 3\n"); printf("Aliohjelmassa: x = 6\nPääohjelmassa: x = 3"); return 0; }
Se Metabolixin koodi oli esimerkki funktion toteutuksesta. En tosiaankaan ymmärrä mitä teet "arvot"-nimisellä funktiolla, kun halusit toteuttaa "muuta_lukua"-funktion.
#include<stdio.h> void muuta_lukua(int x); /* funktion muuta_lukua esittely */ void main(void) { int x: printf("Anna luku x: "); scanf("%d", &x); printf("Pääohjelmassa: x = %d\n", x); muuta_lukua(x); /* tässä kutsut funktiota nimeltä muuta_lukua*/ printf("Pääohjelmassa: x = %d\n", x); return 0; } /* tässä määrittelet funktion nimeltä muuta_lukua */ void muuta_lukua( int x ) { /*tee täällä jotain luvulle x ja tulosta se "Aliohjelmassa" hommeli */ }
Ohjelma valittaa tuommoista:
"Tarkista oletko määritellyt kaksi samantyyppistä muuttujaa tai funktiota (main)"
Tästä kohdasta ohjelma valittaa:
{ int eka;
Kaava on tässä muodossa:
#include <stdio.h> void arvot(int *a); int main(void) { int eka; printf("Anna luku x: 3\nPääohjelmassa: x = 3\n"); printf("Aliohjelmassa: x = 6\nPääohjelmassa: x = 3"); scanf("%d", &eka); arvot(&eka); printf("%d\n", eka); void arvot(int *a) { *a = *a + 3; } return 0; }
Missä on vika?
Tuo palautin-pulauttimen antama virhe luultavasti johtuu siitä , että tehtävänannossa luultavasti lukee, että PALAUTTAKAA VAIN FUNKTION muuta_lukua TOTEUTUS. Voin olla väärässä, mutta palautusohjeita kannattaa lukea. Älä siis palauta main funktion sisältöä. Toisaalta koodisi ei mene tuollaisena edes oikeasta kääntäjästä läpi. Kannattaa hommata semmonen...
Metabolix kirjoitti:
No huh huh. Antti, puuttuu muuten esimerkistäsi
return 0;
Eihän sitä return 0; ole sinne ainakaan kaikissa kääntäjissä pakko laittaa. Silloin jos aikoo siis palauttaa nollan.
Tuota arvot()-funktiota kannattaaa hieman siirtää
#include <stdio.h> void arvot(int *a); int main(void) { int eka; printf("Anna luku x: 3\nPääohjelmassa: x = 3\n"); printf("Aliohjelmassa: x = 6\nPääohjelmassa: x = 3"); scanf("%d", &eka); arvot(&eka); printf("%d\n", eka); return 0; } void arvot(int *a) { *a = *a + 3; }
Olli Vanhoja kirjoitti:
Eihän sitä return 0; ole - - pakko laittaa.
Tuossa nyt sattuu olemaan int main(void)
, joten kyllä sen pitäisi jokin lukuarvo palauttaa, ja yleensä on tapana palauttaa nolla, jos ei tapahdu virheitä.
Metabolix kirjoitti:
Olli Vanhoja kirjoitti:
Eihän sitä return 0; ole - - pakko laittaa.
Tuossa nyt sattuu olemaan
int main(void)
, joten kyllä sen pitäisi jokin lukuarvo palauttaa, ja yleensä on tapana palauttaa nolla, jos ei tapahdu virheitä.
Jep, mutta jos ottaa laittaakin pelkän main() {} niin ei tarvitse returniakaan :)
Kyse lienee kuitenkin yleisestä käytännöstä, eli int main(void) ja return 0.
Määrittely main()
ei taida olla laillinen. Oikeaoppisesti tuo mitään palauttamaton main-funktio olisi void main()
, ja ANSI C:n tapauksessa suluissakin pitää vielä olla void ilmoittamassa, että syötteitä ei tosiaan ole. vaihtoehtoisesti syötteenä voi olla (int, char **)
eli parametrien määrä ja taulukko, jossa kukin parametri on omana merkkijononaan.
Ymmärrän viesteistänne lähes kaiken muun, paitsi sen mikä auttaisi ongelmassani?
Maajo, käytätkö nyt tuota Linkun antamaa koodia? Jos niin, missä on ongelma? Jos et, hus siitä ottamaan se käyttöön.
Metabolix kirjoitti:
Määrittely
main()
ei taida olla laillinen. Oikeaoppisesti tuo mitään palauttamaton main-funktio olisi void main(), ja ANSI C:n tapauksessa suluissakin pitää vielä olla void ilmoittamassa, että syötteitä ei tosiaan ole.
C99:stä tämä on muistaakseni poistettu, mutta ainakin sitä ennen käytettiin "implicit int
" -sääntöä, eli jos tyyppiä ei mainittu, sen oletettiin olevan int
. Mikä taas tarkoittaa että main()
on sama kuin int main()
.
void main()
on lähes kaikkien asiaatuntevien mielestä vääräoppista, mutta C99-standardi vaikuttaisi kertovan toista. Tyyppi arvelee sen olevan korjattava puute, joka se todennäköisesti (toivottavasti ;)) onkin.
Metabolix kirjoitti:
Määrittely
main()
ei taida olla laillinen. Oikeaoppisesti tuo mitään palauttamaton main-funktio olisivoid main()
, ja ANSI C:n tapauksessa suluissakin pitää vielä olla void ilmoittamassa, että syötteitä ei tosiaan ole. vaihtoehtoisesti syötteenä voi olla(int, char **)
eli parametrien määrä ja taulukko, jossa kukin parametri on omana merkkijononaan.
Juu itseasiassa taitaa olla Borlandin sääntöjen ja parin muun kääntäjän omien sääntöjen mukainen ainoastaan tuo main(), että ei todennäköisesti toimi läheskään kaikilla kääntäjillä.
Kyllä se varmasti useammallakin kääntäjällä toimii, mutta taitaapi yleensä tulla varoitus.
Deewiant kirjoitti:
Maajo, käytätkö nyt tuota Linkun antamaa koodia? Jos niin, missä on ongelma? Jos et, hus siitä ottamaan se käyttöön.
Silläkin koodilla ohjelma valittaa siitä "int eka"-kohdasta. Jotain pitäisi siis tehdä koodille, mutta mitä?
Minkälaisia virheitä tulee?
Itselläni kääntyi gcc:llä ihan ilman mitään virheitä.
Maajo kirjoitti:
Tarkoitus on kirjoittaa aliohjelma "muuta_lukua". Sen pitäisi vastaanottaa kokonaisluku ja kasvattaa sitä kolmella.
Suomeksi: Kirjoita aliohjelma (funktio), mitään muuta ei mainita
Maajo kirjoitti:
"Tarkista oletko määritellyt kaksi samantyyppistä muuttujaa tai funktiota (main)"
Suomeksi: main() on jo olemassa
FooBat kirjoitti:
Tuo palautin-pulauttimen antama virhe luultavasti johtuu siitä , että tehtävänannossa luultavasti lukee, että PALAUTTAKAA VAIN FUNKTION muuta_lukua TOTEUTUS. Voin olla väärässä, mutta palautusohjeita kannattaa lukea. Älä siis palauta main funktion sisältöä.
Elikkä vastaukseksi vaaditaan pelkkä funktio. Kaiken muun saa siis jättää pois.
FooBat kirjoitti:
- - virhe luultavasti johtuu siitä, että tehtävänannossa luultavasti lukee, että PALAUTTAKAA VAIN FUNKTION muuta_lukua TOTEUTUS.
Toisin sanoen, otat koko tiedostosta pois kaiken muun paitsi sen muuta_lukua-funktion. Onko se niin vaikeaa?
acorn oli vikkelämpi :)
lainaus:
Toisin sanoen, otat koko tiedostosta pois kaiken muun paitsi sen muuta_lukua-funktion. Onko se niin vaikeaa?
acorn oli vikkelämpi :)
Kyllä se on niin vaikeaa.. Mulla menee pää vaa sekavemmaks koko ajan... Siis ny mä en tiedä enää yhtään mitään, mitä tehä... Mikä koodi ja mistä ja missä muodossa ja mitä muutetaan mihinkäkin jajajaja.... :(
Maajo, luitko tuon mitä lainasit? Lainatakseni itsekin Metabolixia, otat koko tiedostosta pois kaiken muun paitsi sen muuta_lukua-funktion. Väännetään nyt vielä varmuuden vuoksi rautalangasta... vastauksesi:
void muuta_lukua(int * const a) { *a = *a + 3; }
Joko mä en ymmärrä enää yhtään mitään mistään tai sitten toi ei vain toimi... En siis saanu ohjelmaa toimimaan (vieläkään).
Ohjelman pitäisi tulostaa näin:
Anna luku x: 3
Pääohjelmassa: x = 3
Aliohjelmassa: x = 6
Pääohjelmassa: x = 3
#include<stdio.h> void muuta_lukua(int x); int main(int argc, char ** argv) { int x; printf("Anna luku x:"); scanf("%d", &x); printf("Pääohjelmassa: x = %d\n", x); muuta_lukua(x); printf("Pääohjelmassa: x = %d\n", x); return 0; } void muuta_lukua(int x) { printf("Aliohjelmassa: x = %d\n", x); }
Mitä osaa et ymmärrä?
Tietenkään tuo Deewiantin koodi ei toimi, siitä esim. puuttuu main()-funktio. Mutta jos tehtävä on palauttaa funktio joka tekee, annat vani tekstitiedostossa nuo Deewiantin antamat 4 riviä. Sitä ei voi kääntää mutta tehtävä on suoritettu.
Linkku kirjoitti:
#include<stdio.h> void muuta_lukua(int x); int main(int argc, char ** argv) { int x; printf("Anna luku x:"); scanf("%d", &x); printf("Pääohjelmassa: x = %d\n", x); muuta_lukua(x); printf("Pääohjelmassa: x = %d\n", x); return 0; } void muuta_lukua(int x) { printf("Aliohjelmassa: x = %d\n", x); }Mitä osaa et ymmärrä?
Sitä, kun aina vaan ohjelma herjaa intistä, enkä mä tiedä mitä sille pitäis tehdä..
Sit sitäkin mä ihmettelen, kun vaikka sen intin ottais sieltä kokonaan pois, niin se herjaa samaa ongelmaa... ???
No aivan varmasti menee mistä tahansa kääntäjästä tollaisenaan läpi! Mitä kääntäjää käytät?
Ei se mitään, lataa Dev-C++ http://www.bloodshed.net/dev/devcpp.html
No mä kokeilen..
Kokeilin ohjelmaa (ton linkin takaa) ja kyllä se sikäli toimi, että se kysy numeron, MUTTA sitten se heitti koko jutun sammuksiin. Ei siis tehny sille luvulle yhtään mitään.. Ei toimi siis???
Toimiihan se hyvinkin, mutta koska ohjelma loppuu heti viimeisen tulostuksen jälkeen niin et ehdi näkemään mitä ruudulle tulostuu. Eli ohjelma pitää pysäyttää ennen "return 0;" lauseketta. Siisteimmin onnistut siinä kun lisäät alkuun "#include <conio.h>" ja ennen return lauseketta "getch();" (ilman lainausmerkkejä).
WinC kirjoitti:
Siisteimmin onnistut siinä kun
...ajat ohjelman oikealla tavalla. Ks. esim. http://pp.kpnet.fi/blaze/codefaq/#justflashes
eikö Console.RealLine(); toimi tuossa koodissa?
Cc kirjoitti:
eikö Console.RealLine(); toimi tuossa koodissa?
Mikä ihmeen "Console.RealLine();"?
Köhm, kyseessä ei ole C#, jossa on Console.ReadLine();.
C:tä tuo on.
#include <stdio.h> #include <conio.h> void arvot(int *a); int main(void) { int eka; printf("Anna luku x: \n"); scanf("%d", &eka); printf("Pääohjelmassa: x = \n"); arvot(&eka); printf("Aliohjelmassa: x = \n"); printf("%d\n", eka); printf("Pääohjelmassa: x = "); getch(); return 0; } void arvot(int *a) { *a = *a + 3; }
Tuollaisella koodilla tulee itse luku oikeaan paikkaan ja myöskin aliohjelman luku on oikein.. Miten tulostan pääohjelmaan sen alkuperäisen luvun?
Tulostaa pääohjelmaan? Mitä ihmettä se on? o_O
Haluutko aliohjelmassa muokatun arvon käyttöön pääohjelman puolella? Sehän onnistuu ottamalla aliohjelman palauttama arvo talteen muuttujaan:
int muuli; muuli = pulautaJokuLuku(); printf("%i", muuli);
Siis pääohjelmassa tulostuu se sama luku, minkä käyttäjä on syöttänyt ohjelmaan ja aliohjelmassa se on sama luku + 3 (eli jos pääohjelmassa luku on 2, niin aliohjelmassa se on 2+3=5).
Sen jälkeen kun luet tuolla scanf()
-funktiolla sen luvun muuttujaan eka
, kopioit eka
n johonkin toiseen muuttujaan. Sen jälkeen voit muuttaa eka
a arvot()
-funktiolla kuten nytkin olet jo tehnyt, ja se toinen muuttuja pysyy samana. Lopussa sitten tulostat printf()
-funktiolla sen toisen muuttujan.
Millä pystyn kopioimaan sen luvun?
Valmis koodi oli näin:
#include<stdio.h> void muuta_lukua(int x); int main() { int x; printf("Anna luku x:"); scanf("%d", &x); printf("Pääohjelmassa: x = %d\n", x); muuta_lukua(x); printf("Pääohjelmassa: x = %d\n", x); return 0; }
Haluttu tuloste (output):
Anna luku x: 3
Pääohjelmassa: x = 3
Aliohjelmassa: x = 6
Pääohjelmassa: x = 3
2. ensimmäistä ja viimeinen rivi tulostuvat. Itse täytyy siis tulostaa vain tuo 3. rivi (Aliohjelmassa: x = 6). Pointterit (osoitin) pois tuosta koodista ja vastaukseksi pitäisi riittää funktio muuta_lukua(int x), jossa tulostetaan teksti "Aliohjelmassa: x = " ja sen perään parametrina annettu luku+3. (taisi mennä hepreaksi, mutta voihan tästä olla apuakin)
#include <stdio.h> #include <conio.h> void arvot(int *a); int main() { int a; int eka; printf("Anna luku x: \n"); scanf("%d", &a); printf("Pääohjelmassa: x = %d\n", a); printf("Aliohjelmassa: x = \n"); arvot(&eka); printf("%d\n", a+3); printf("Pääohjelmassa: x = %d", a); getch(); return 0; } void arvot(int *a) { *a = *a + 3; }
Koodi on toimiva, mutta vieläkin tulee herjaa... Herja tulee tästä kohdasta:
{ int a; int eka;
Mehän kävimme tämän jo läpi. Sinun ei tarvitse palauttaa muuta kuin tämä:
void muuta_lukua(int * const a) { *a += 3; }
Eli se ohjelman osa, joka kasvattaa annettua lukua kolmella.
Herja johtuu siitä, että ilmeisesti lähetät tuon koodin jonnekin nettiin, jossa se lisätään valmiiseen koodiin ja käännetään. Siinä valmiissa koodissa on jo main()
-funktio ja sinä määrität omassasi toisen. Siksi sinun ei tule lähettää kuin tuo ylläoleva koodinpätkä, koska siellä päässä on kaikki muu valmiina.
Mutta kun tuo ei ratkaise ongelmaa.. Viope herjaa edelleen siitä int a/int eka-kohdasta.
#include <stdio.h> #include <conio.h> void arvot(int *a); int main() { int a; int eka; printf("Anna luku x: \n"); scanf("%d", &a); printf("Pääohjelmassa: x = %d\n", a); printf("Aliohjelmassa: x = \n"); arvot(&eka); printf("%d\n", a+3); printf("Pääohjelmassa: x = %d", a); getch(); return 0; } void arvot(int *a) { *a = *a + 3; }
Muuten koodi toimii kyllä.
1. Käytä funktiota nimelta "muuta_lukua" ÄLÄ "arvot" nimistä funktiota.
2. Tulosta "Aliohjelmassa x = 6" lause "muuta_lukua" funktion sisällä.
3. Muuta funktion parametrin tyyppi "int * a" -> "int a"
4. Palauta vain "muuta_lukua"-funktion toteutus eli
void muuta_lukua(int a) { printf("Aliohjelmassa ..."); }
Jos noi ei toimi:
5. Luo tehtävän ohje uudestaan.
6. Luo tehtävän palautusohje kahteen kertaan.
7. Palauta vain mitä tehtävässä sanotaan.
Siis mitä ohjelmasi pitää tehdä? Pitääkö muuta_lukua funktion muuttaa lukua?
Jos kyllä käytä seuraava
#include <stdio.h> #include <conio.h> void muuta_lukua(int *a); int main() { int a; printf("Anna luku x: "); scanf("%d", &a); printf("Pääohjelmassa: x = %d\n", a); muuta_lukua(&a); printf("Pääohjelmassa: x = %d\n", a); getch(); return 0; } void muuta_lukua(int *a) { *a += 3; printf("Aliohjelmassa: x = %d\n", *a); }
Ensimmäinen viestisi antoi ymmärtää, että aliohjelma ei muuta lukua.
Tämä ohjelma tulostaa
lainaus:
Anna luku x: 2
Pääohjelmassa: x = 2
Aliohjelmassa: x = 5
Pääohjelmassa: x = 5
Maajo kirjoitti:
Mutta kun tuo ei ratkaise ongelmaa.. Viope herjaa edelleen siitä int a/int eka-kohdasta.
Olet vieläkin täysin pihalla. Et lähetä Viopeen sitä int a/int eka -kohtaa. Lähetät vain kohdan, joka alkaa void muuta_lukua
. Lue FooBatin viesti.
Ymmärräthän, että kirjoitan tämän vain, jotta et enää vaivaisi meitä tällä idioottimaisella asialla.
Jos 1. viestisi ketjussa pitää paikkansa, tämä on oikea vastaus Viopelle:
#include <stdio.h> void muuta_lukua(int x) { x = x + 3; printf("Aliohjelmassa: x = %d\n", x); }
Ei ole tarkoitukseni olla töykeä, mutta tunnut vain olevan aika toivoton tapaus ohjeiden noudattamisessa.
Tuo toimii kyllä... Kiitokset koodista ja muutenkin avusta. :)
Kyllä mä sen ymmärrän, ettette te välttämättä ymmärrä sitä, että mä en ymmärrä..
Jos joku on kiinnostunut tuosta Viope-systeemistä, kotisivu on http://www.viope.com/ .
Jonkin C-kurssin ohjelma löytyy osoitteesta http://www.viope.com/viope_c_peruskurssi.html joten voimme ehkä arvata, mitä täältä seuraavaksi tullaan kysymään.
Kohdassa "Demo" on mailto-linkki, jolla voi ilmeisesti tilata kokeilutunnukset. Mahtaako olla vanhentunut sivu... No kokeilenpa kuitenkin :)
Aihe on jo aika vanha, joten et voi enää vastata siihen.