Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: vaikeuksia pointtereiden kanssa

Sivun loppuun

Palvy [10.02.2009 21:38:46]

#

Mikähän tuossa mahtaa olla vikana kun ei toimi oikein? Tarvittavat toiminnot: Inputin lukeminen pitäs pysähtyä kun *count:n verran arvoja luettu tai lukeminen failaa ja pitäs palauttaa viimeinen onnistuneesti luettu arvo tai 0.0 jos arvoja ei luettu ollenkaan. Onnistuneesti luettujen lukujen lkm tallennetaan *count:iin. Loput toiminnot koodin kommenteissa:

#include <stdio.h>
#include <stdlib.h>
/* pitäisi laskea standard inputista minimi, maksimi ja summa*/
double stats(size_t* count, double* min, double* max, double* sum)
{
	double number;
	if (scanf("%lf", &number) == 1)
	{
		if (min != NULL)
			*min = number;
		if (max != NULL)         /*jos nää on NULLeja, niin niiden pitää pysyä NULLeina */
			*max = number;
		if (sum != NULL)
			*sum += number;
		for (unsigned long i = 2; i <= *count; ++i)
		{
			if (scanf("%lf", &number) == 1)
			{
				if (sum != NULL)
					*sum += number;
				if (number > *max && max != NULL)
					*max = number;
				else if (number < *min && min != NULL)
					*min = number;
			}
			else
				*count = i - 1;
				return number;
		}
		return number;
	}
	else
		*count = 0;
		return 0.0;
}

edit: koodia sais varmasti lyhyemmäks mutta nyt ois joku virhe kiva löytää

Metabolix [10.02.2009 22:00:50]

#

Ainakin se on vikana, että parissa kohdassa on ensin *x ja sitten vasta NULL-tarkistus. Lisäksi kaikista else-lauseista puuttuvat lohkon rajaavat sulut, jolloin else-lauseeseen sisältyy vain seuraava rivi ja return-lause suoritetaan joka kerta. Sisennyksellä ei ole vaikutusta koodin merkitykseen. Hyvä tapa on käyttää sulkuja aina, kun kirjoittaa koodia sisennetysti seuraavalle riville, vaikka rivejä olisi vain yksi. Tällöin toisen rivin lisäämisessä ei voi sattua noin (vaikkei kyllä oikeasti voi tuollakaan tavalla sattua, on nimittäin niin perusasia.)

Voisit säästää paljon päänvaivaa tekemällä ensin laskut paikallisten muuttujien kanssa ja sijoittamalla tulokset paikalleen vasta lopuksi.

double stats(size_t *count_ptr, double *min_ptr, double *max_ptr, double *sum_ptr) {
    size_t i;

    /* Asetetaan oletusarvot, jos muita ei saada. */
    double d = 0, min = 0, max = 0, sum = 0;

    /* Pitää tarkistaa NULL-osoittimet. */
    if (!count_ptr) {
        abort();
    }
    /* Luetaan ne luvut. */
    for (i = 0; i < *count_ptr; ++i) {
        if (scanf("%lf", &d) != 1) {
            /* Meni pieleen, lopetetaan. */
            break;
        }
        if (i == 0) {
            /* Ensimmäinen luku kuuluu kaikkiin. */
            min = max = sum = d;
        } else {
            /* Muuten muutetaan niitä oikein. */
            if (d < min) min = d; else
            if (d > max) max = d;
            sum += d;
        }
    }
    /* Sijoitetaan arvot muuttujiin ja palautetaan viimeinen luettu. */
    *count_ptr = i;
    if (min_ptr) *min_ptr = min;
    if (max_ptr) *max_ptr = max;
    if (sum_ptr) *sum_ptr = sum;
    return d;
}

Edit.
Opettele ihan oikeasti käyttämään debuggeria edes sen verran, että osaat ajaa ohjelmaa rivi kerrallaan. Sillä olisit tuostakin suurimman virheesi löytänyt.

Palvy [10.02.2009 22:19:13]

#

Kiitokset opettavaisista neuvoista, joo täytyy opetella debuggaamaan. Tyhmiä virheitä, ehkä väsymyksen piikkiin osa :)

Palvy [12.02.2009 01:03:39]

#

Kokeilin Code::Blocksia ja sen mukana tulevaa GNU GCC -kääntäjää. Tässä yksi pätkä koodia:

printf("First: %zu == %zu\n", stringLength(strings[0]), stringLength(firstBuffer));

Tuo stringLength palauttaa siis size_t -tyyppisen muuttujan, mutta se ei kuitenkaan tule printtiin niin kuin pitäisi, vaan tyyliin "zu". Mistähän tuo voisi johtua?

Grez [12.02.2009 01:31:11]

#

Mistä oot tuon %zu keksinyt. Ainakaan mun printf dokumentaatiossa ei ole määritelty z -flagia.

fidori [12.02.2009 01:52:27]

#

z-lippu on ilmeisesti lisätty C99-standardissa.

Grez [12.02.2009 02:54:09]

#

Ohoh, mitenköhän mä sainkin eteeni sitten noin vanhat referenssisivun, mistä moinen puuttui.

Mutta anyways, kyllä tämä

#include <stdio.h>
#include <string.h>
int main() {
        const char str1[20]="Testi";
        const char str2[40]="Toinen testi";
        printf("First: %zu == %zu\n", strlen(str1), strlen(str2));
}

antaa gcc:llä käännettynä
First: 5 == 12

En keksinyt mistä tuo stringLength on kotoisin, mutta tuo strlen palauttaa myös size_t:n.

Palvy [12.02.2009 14:43:17]

#

Tuo stringLength toimii samoin kuin strlen, paitsi että lopetusmerkki on '!', eikä '\0'. Hmm, koulun Linuxilla kun käänsin, niin se kyllä tulostuu oikein, mutta omalla Vistalla + Code::Blocksilla + GNU GCC:llä tulee "zu". Joku asetus jossain ehkä pielessä...

Metabolix [12.02.2009 15:01:39]

#

Onko Windowsissa käyttämäsi GCC kirjastoineen riittävän uusi? Siitähän se on kiinni.

Palvy [12.02.2009 16:01:58]

#

Siitä se taitaa olla kiinni, onko tietoa onnistuisko GCC 4.2.4 -version käyttäminen Vistalla?

Metabolix [12.02.2009 16:04:39]

#

Varmasti onnistuu.

Palvy [12.02.2009 17:41:08]

#

Asensin tuolta http://www.tdragon.net/recentgcc/ tuon TDM/MinGW Installer
1.812.0:n, joka ilmeisesti sisältää gcc 4.3.2:n (ilmeisesti kuitenkin joku epävirallinen versio, en löytänyt MinGW:lle virallista noin uutta versiota). Sitten koitin kääntää mutta tulee edelleen:

"warning: ISO C90 does not support the 'z' printf length modifier"

Miksköhän se edes herjailee tuota ISO C90:ä, eikös tuon kääntäjän pitäis jo ymmärtää ISO C99:ä...

Metabolix [12.02.2009 17:53:04]

#

Kyseessähän on varoitus, joten ohjelma kääntyy ja toimii silti. Se vain varmuuden vuoksi ilmoittaa, että ohjelmasi ei toimi vanhoilla kääntäjillä. Varoitusta ei tulisi, jos kertoisit kääntäjälle, että käytät kyseistä C:n versiota:

gcc -std=c99 -Wall -pedantic koodi.c

Palvy [12.02.2009 18:10:08]

#

Koulun koneella käytänkin noita mainitsemiasi komentoja kääntäjälle, ja kokeilin nyt myös tällä Vistalla käyttää noita, ja kääntyy kyllä ilman varoituksia, mutta vieläkin tulee vain "zu" :)

Jos kääntää windowsin komentoriviltä, niin kääntäjän .exe-tiedoston ei ilmeisesti tarvitse olla siinä kansiossa missä kääntöhetkellä ollaan?

Grez: Mikä versio GCC:stä sulla on ja mistä olet saanut? Käytätkö Windowsia?

Grez [12.02.2009 18:30:30]

#

Tuo millä käänsi oli 4.1.2 ja se tuli käyttiksen mukana (taitaa olla CentOS). Käytän kyllä Windowsia ja ihan Windows-koneelta tuota CentOS-konetta käytinkin.

Latasin nyt kuitenkin huvin ja urheilun vuoksi myös Windowsini (64-bit Vista) suositellun version Cygwinistä (1.5.25-15, löytyy osoitteesta http://sourceware.org/cygwin/ ) ja valitsin gcc:n asennettavaksi (siinä näyttäisi olevan 3.4.4)

Silläkin käännettynä toimii ihan samalla tavalla:

$ cat >test.c
#include <stdio.h>
#include <string.h>
int main() {
        const char str1[20]="Testi";
        const char str2[40]="Toinen testi";
        printf("First: %zu == %zu\n", strlen(str1), strlen(str2));
}
^D

$ gcc test.c

$ ./a.exe
First: 5 == 12

Palvy [12.02.2009 19:03:43]

#

Ok, noh, täytyy joskus kokeilla...


Sivun alkuun

Vastaus

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

Tietoa sivustosta