Scholieren.com forum

Scholieren.com forum (https://forum.scholieren.com/index.php)
-   Software & Hardware (https://forum.scholieren.com/forumdisplay.php?f=20)
-   -   [Prog] C: infinite loop verkeerde waarde (https://forum.scholieren.com/showthread.php?t=1136327)

dragonstorm 24-03-2005 14:46

[C] infinite loop verkeerde waarde
 
Code:





#include <stdio.h>
#include <math.h>
#define LIMIET 45


int priem(int),fibonacci(int);
void is_fib_priem(int);

main() {
        int n;
        while (1)
        {
                printf("Geef a.u.b een waarde;\n");
                scanf("%d",&n);       
                if (n < LIMIET)
                        is_fib_priem(n);
                else
                        printf("Deze waarde is te hoog, geef een andere waarde\n");
        }
       
}

int priem(int n)
{
        int i = 2;
        while (i <= sqrt(n)) {
                if (n % i == 0)
                        return 0;
                ++i;
        }
        return 1;
}

int fibonacci(int n)
{
        static int fib[LIMIET],temp;
        fib[0] = 0, fib[1] = 1;
        if (n < temp)
                return fib[n];
        int i = 2;
        for (; i <= n; ++i)
                fib[i] = fib[i-1] + fib[i-2]; /*dit werkt*/
        temp = i;
        /*        for (l = 0; l < i; ++l)
                        printf("%d %d\n",l,fib[l]); algoritme-evaluatie       
        */
        return fib[--i]; /*oh. dus de laatste word een keer teveel ge-evalueerd. Never mind :)'*/
}


void is_fib_priem(int n)
{
        int fib = fibonacci(n);
        if (priem(fib))
                printf("%s%d%s%d\n","Het ",n,"e fibonacci-getal is het priemgetal: ",fib);
        else
                printf("%s%d%s%d\n","Het ",n,"e fibonacci-getal is geen priemgetal: ",fib);       
}

Goed, dit is dus een leuk miniprogrammatje, en hij werkt heel aardig. Toelichting: hij vraagt om een getal, berekent hiermee het getal in de rij van fibonacci dat hiermee overeenstemt, en kijkt of dit een priemgetal is.

Ik kan btw ook unsigned ints gebruiken voor dit algoritme, maar of dit echt nut heeft weet ik niet zeker - ik zal hoogstens wat meer waardes kunnen evalueren.

Het punt is dat 'm in een infinite loop raakt bij verkeerde input (alles wat niet een cijfer is), en dat is heel irritant. Slimme jongens zeggen nu wel 'ja maar hij is altijd in een infinite loop - ik bedoel uiteraard dat 'm de scanf() functie niet meer uitvoert, en gewoon alles telkens blijft herhalen.

Weet iemand een manier om dit te voorkomen?

GVR 24-03-2005 14:52

fflush(stdin);
ervoor zetten.

dragonstorm 24-03-2005 15:09

waarvoor precies? :O

GVR 24-03-2005 15:31

Code:

main()
{
    int n;
    for ( ;; ) {
        printf("Geef a.u.b een waarde;\n");

        while( scanf("%d", &n)!=1 ) {
                scanf("%*s");
                printf("Incorrecte invoer\n");
        }
        if (n < LIMIET)
            is_fib_priem( n );
        else if (n == 0 )
                break;
        else
            printf("Deze waarde is te hoog, geef een andere waarde\n");
    }
return 0;
}

Lama, je mag geen input buffer flushen in ansi C :bloos:
Dit moet werken...

dragonstorm 24-03-2005 16:25

Code:


main() {
        int n;
        while (1)
        {
       
                printf("Geef a.u.b een waarde;\n");
                while (scanf("%d",&n)!= 1) {
                        scanf("%s*s");
                        printf("Verkeerde invoer\n");
                }
                if (n < LIMIET && n > 0)
                        is_fib_priem( n);
                else if (!n)
                        break;
                else
                        printf("Deze waarde is te hoog/negatief, geef een andere waarde\n");
               
        }
       
}

Deze code is naar mijn weten equivalent (behavle dat ik ook voor 0 check voor 'm naar is_fib_priem() te sturen, maar hij stopt nu bij de 0, is dat de bedoeling? :) het is wel handig.

edit: en btw, ik weet zeker dat er een meer efficient algoritme moet zijn voor het vinden van priemgetallen :O je hoeft nl alleen maar door priemgetallen te delen. Probleem daarvan is dat je eerst wel een array moet hebben van die priemgetallen.

GVR 24-03-2005 17:33

Was de bedoeling idd (code niet goed gelezen)

ipv van %*s kan je eigenlijk beter %*[^\n] (leest tot newline), dan moet je eigenlijk ook een do while loopje ervoor maken, je kan nu meerdere invoeren op een regel geven: "2 3 4 5 6", tenzij je dit goed vind

Voor beter algo moet je even kijken op google. Er zijn algos die zonder tabel kunnen controleren op priem in kortere tijd. Maar het gaat toch snel genoeg zo ?

En natuurlijk even zeuren over slechte code :)

1. main MOET int zijn (ANSI C)
2. main MOET return value geven (ANSI C)

Dr HenDre 24-03-2005 17:47

hmm, als ik t goed begrijp treed er een probleem op wanneer de invoer niet numeriek is? Kan je niet gewoon effe kijken wat de invoer is voordat je t schrijft naar een variable? Of anders nadat het geschreven is controleren of t wel of geen geldige variable is en zoniet een break; ?

GVR 24-03-2005 18:21

Citaat:

Dr HenDre schreef op 24-03-2005 @ 18:47 :
hmm, als ik t goed begrijp treed er een probleem op wanneer de invoer niet numeriek is? Kan je niet gewoon effe kijken wat de invoer is voordat je t schrijft naar een variable? Of anders nadat het geschreven is controleren of t wel of geen geldige variable is en zoniet een break; ?
Misschien wil je over een jaar nog een keer een foutieve oplossing posten op een probleem dat al opgelost is?

dragonstorm 24-03-2005 18:24

ja natuurlijk wel, maar ik druk nog wel 'ns op omhoog voor ik op enter druk, en dan flipt 'm ook :) en het is makkelikjker dat sofwarematig op te lossen

GVR...

ehm... ik ga nog wel ff kjken of ik dat kan implementeren... maar eigenljk snap ik nog niet helemaal wat die code doet :bloos:

edit:
k heb zojuist factor herschreven :cool:
bedankt, het heeft geholpen :)

dragonstorm 28-03-2005 17:12

Citaat:

En natuurlijk even zeuren over slechte code :)

1. main MOET int zijn (ANSI C)
2. main MOET return value geven (ANSI C)

om even terug te zeuren: beide dingen zijn impliciet (main is int, en functies-die-niets-teruggeven leveren 0 af) :P dus hoeven_niet_perse geschreven te worden.

Het is uiteraard wel aardig om op te schrijven, voor t geval je een kutcompiler hebt.

btw, als ik de functies sqrt(), pow() en de andere functies van math.h gebruik, moet ik de -lm optie van gcc gebruiken, omdat 'm anders niet compileert. Wete jullie hoe dit komt, en of het te omzeilen valt? bedankt :)

GVR 28-03-2005 18:15

Citaat:

dragonstorm schreef op 28-03-2005 @ 18:12 :
om even terug te zeuren: beide dingen zijn impliciet (main is int, en functies-die-niets-teruggeven leveren 0 af) :P dus hoeven_niet_perse geschreven te worden.

Het is uiteraard wel aardig om op te schrijven, voor t geval je een kutcompiler hebt.

btw, als ik de functies sqrt(), pow() en de andere functies van math.h gebruik, moet ik de -lm optie van gcc gebruiken, omdat 'm anders niet compileert. Wete jullie hoe dit komt, en of het te omzeilen valt? bedankt :)

-lm betekent dat libmath meegelinkt moet worden. (het is een afkorting)
Je kan er niet onderuit, anders krijgen de functies in math.h geen bijhorende code.

Functies die geen returnvalue geven, geven niet perse 0 terug !!! Zij geven een ongedefineerde waarde terug.
En main mag dan impliciet int zijn, volgens mij is dat er ook uit in c99...

dragonstorm 29-03-2005 15:46

is er eigenlijk een manier om een functie meerdere variabelen terug te laten geven? want ik zou graag een functie invoer() willen maken die het volgende doet:

Code:

        /*invoer*/
                double k,con,c,x;
                printf("Geef de beginconcentratie:\n");       
                scanf("%lf",&con);
                printf("En geef de Kz:\n");
                scanf("%lf",&k); 
        /*einde invoer*/

de enige manier die ik ken is met externe variabelen, en zo heel netjes vind k dat niet :(

GVR 29-03-2005 18:58

Citaat:

dragonstorm schreef op 29-03-2005 @ 16:46 :
is er eigenlijk een manier om een functie meerdere variabelen terug te laten geven? want ik zou graag een functie invoer() willen maken die het volgende doet:

Code:

/*invoer*/
  double k,con,c,x;
  printf("Geef de beginconcentratie:\n");
  scanf("%lf",&con);
  printf("En geef de Kz:\n");
  scanf("%lf",&k); 
 /*einde invoer*/

de enige manier die ik ken is met externe variabelen, en zo heel netjes vind k dat niet :(

Code:


#include <stdio.h>

typedef struct {
        int a,b;
} onzin;

/* manier een: pointers, (is goed) */
int meer(int* var1, int* var2)
{
        *var1 = 16;
        *var2 = 32;
        return 0;
}

/* manier twee, struct terug geven, (is slecht) */
onzin minder(void)
{
        onzin r;
        r.a = 64;
        r.b = 128;
        return r;
}

int main(void)
{
        int a,b;
        onzin c;
        (void)meer( &a, &b );
        c = minder();
        (void)printf("%d %d\n", a,b );
        (void)printf("%d %d\n", c.a, c.b );
        return 0;
}

Zoiets??

dragonstorm 31-03-2005 21:35

Code:

void invoer(int *p, int *q)
{
        scanf("%d", p); /*dat was heel educatief,
        scanf stuurt de waarde naar 'n adres*/
        scanf("%d", q);
}

als in: zo?
aan te roepen met

Code:

int a,b;
invoer(&a, &b);

of

Code:

int a,b,*p,*q;
p = &a, q = &b;
invoer(p,q);

grappig

ik wist niet dat scanf naar 'n adres stuurde (hoewel t wel logisch is, gezien je ook &a voor n normale variabele geeft)

GVR 31-03-2005 22:49

Citaat:

dragonstorm schreef op 31-03-2005 @ 22:35 :
Code:

void invoer(int *p, int *q)
{
 scanf("%d", p); /*dat was heel educatief,
        scanf stuurt de waarde naar 'n adres*/
 scanf("%d", q);
}

als in: zo?

Jup

Citaat:

aan te roepen met

Code:

int a,b;
invoer(&a, &b);


Jup

Citaat:

Code:

of

int a,b,*p,*q;
p = &a, q = &b;
invoer(p,q);


Nee, extra variabelen, extra ellende...

Citaat:


grappig

ik wist niet dat scanf naar 'n adres stuurde (hoewel t wel logisch is, gezien je ook &a voor n normale variabele geeft)

Anders kan scanf er ook niet naar schrijven. Als je een gewone int zou geven zou de int gekopieerd worden naar scanf en wordt dus nooit teruggegeven, met & wordt de referentie gekopieerd.

Als je een beetje goede inleiding wil in C (dat is pointers ed) kan ik je aanraden om de tutorial te lezen van lcc-win32 (google naar lcc-win32 voor website :) ) Hoewel er enkele windows onderdelen in zitten geeft hij heel wat duidelijkheid over C zelf.

dragonstorm 01-04-2005 10:31

Citaat:

Als je een beetje goede inleiding wil in C (dat is pointers ed) kan ik je aanraden om de tutorial te lezen van lcc-win32 (google naar lcc-win32 voor website :) ) Hoewel er enkele windows onderdelen in zitten geeft hij heel wat duidelijkheid over C zelf.
ik heb hier een boek liggen, 'de programmeertaal C, 4e editie' van Al Kelley en Ira Pohl. Het is dik en er staat heeeeeel veel een, maar niet zoveel grafische zooi, en op sommige dingen gaat t iets minder diep in als ik wel zou willen zien. Maar het is een fijn boek. Ik zal 'ns kijken naar die tutorial.

dragonstorm 03-04-2005 21:42

:O het zit weer ns niet mee

ik hoef voor geen enkele functie uit <string.h> iets extra's te doen, maar voor strien() wel, heb t zo gefixt (met wat hulp uit m'n boek ;))

Code:



unsigned strien (const char *s)
{
        register int n;
        for (n = 0; *s != '\0'; ++s)
                ++n;
        return n;
}


is er een compilatieoptie om het te fixen? dat is makkelijker dan dit telkens mee te voegen :) hoewel ik natuurlijk altijd een header file kan maken

GVR 04-04-2005 16:46

Citaat:

dragonstorm schreef op 03-04-2005 @ 22:42 :
:O het zit weer ns niet mee

ik hoef voor geen enkele functie uit <string.h> iets extra's te doen, maar voor strien() wel, heb t zo gefixt (met wat hulp uit m'n boek ;))

Code:



unsigned strien (const char *s)
{
 register int n;
 for (n = 0; *s != '\0'; ++s)
  ++n;
 return n;
}


is er een compilatieoptie om het te fixen? dat is makkelijker dan dit telkens mee te voegen :) hoewel ik natuurlijk altijd een header file kan maken

bedoel je niet stiekem strlen :D

dragonstorm 05-04-2005 10:31

oeps, jah ... :bloos:


Alle tijden zijn GMT +1. Het is nu 12:12.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.