开发者

Test of procedure is fine but when called from a menu gives uninitialized errors. C

开发者 https://www.devze.com 2023-02-01 10:36 出处:网络
The language is portuguese, but I think you get the picture. My main calls only the menu function (the function in comment is the test which works).

The language is portuguese, but I think you get the picture. My main calls only the menu function (the function in comment is the test which works).

In the menu i introduce the option 1 which calls the same function. But there's something wrong.

If i test it solely on the input:

(1/1)x^2 //it reads the polinomyal (2/1) //reads the rational and returns 4

(you can guess what it does, calculates the value of an instace of x over a 开发者_运维问答rational)

My polinomyals are linear linked lists with a coeficient (rational) and a degree (int)

int main ()
{
    menu_interactivo ();
//  instanciacao ();
    return 0;
}

void    menu_interactivo(void)
{
    int i;
    do{
        printf("1. Instanciacao de um polinomio com um escalar\n");
        printf("2. Multiplicacao de um polinomio por um escalar\n");
        printf("3. Soma de dois polinomios\n");
        printf("4. Multiplicacao de dois polinomios\n");
        printf("5. Divisao de dois polinomios\n");
        printf("0. Sair\n");
        scanf ("%d", &i);
        switch  (i)
        {
            case 0: exit(0);
                    break;
            case 1: instanciacao ();
                    break;
            case 2: multiplicacao_esc ();
                    break;
            case 3: somar_pol ();
                    break;
            case 4: multiplicacao_pol ();
                    break;
            case 5: divisao_pol ();
                    break;
            default:printf("O numero introduzido nao e valido!\n");
        }
    }
    while (i != 0);
}

When i call it with the menu, with the same input, it does not stop reading the polinomyal (I know this because it does not ask me for the rational as on the other example)

I've run it with valgrind --track-origins=yes returning the following:

==17482== Memcheck, a memory error detector
==17482== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==17482== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==17482== Command: ./teste
==17482== 
1. Instanciacao de um polinomio com um escalar
2. Multiplicacao de um polinomio por um escalar
3. Soma de dois polinomios
4. Multiplicacao de dois polinomios
5. Divisao de dois polinomios
0. Sair
1
Introduza um polinomio na forma (n0/d0)x^e0 + (n1/d1)x^e1 + ... + (nk/dk)^ek,
com ei > e(i+1):
(1/1)x^2
==17482== Conditional jump or move depends on uninitialised value(s)
==17482==    at 0x401126: simplifica_f (fraccoes.c:53)
==17482==    by 0x4010CB: le_f (fraccoes.c:30)
==17482==    by 0x400CDA: le_pol (polinomios.c:156)
==17482==    by 0x400817: instanciacao (t4.c:14)
==17482==    by 0x40098C: menu_interactivo (t4.c:68)
==17482==    by 0x4009BF: main (t4.c:86)
==17482==  Uninitialised value was created by a stack allocation
==17482==    at 0x401048: le_f (fraccoes.c:19)
==17482== 
==17482== Conditional jump or move depends on uninitialised value(s)
==17482==    at 0x400D03: le_pol (polinomios.c:163)
==17482==    by 0x400817: instanciacao (t4.c:14)
==17482==    by 0x40098C: menu_interactivo (t4.c:68)
==17482==    by 0x4009BF: main (t4.c:86)
==17482==  Uninitialised value was created by a stack allocation
==17482==    at 0x401048: le_f (fraccoes.c:19)
==17482== 

I will now give you the functions which are called

void    le_pol (pol *p)
{
    fraccao f;
    int     e;
    char    c;

    printf ("Introduza um polinomio na forma (n0/d0)x^e0 + (n1/d1)x^e1 + ... + (nk/dk)^ek,\n");
    printf("com ei > e(i+1):\n");

    *p = NULL;

    do
    {
        le_f (&f);

        getchar();
        getchar();

        scanf ("%d", &e);

        if (f.n != 0) //polinomios.c line 163
            *p = add (*p, f, e);

        c = getchar ();

        if (c != '\n')
        {
                getchar();
                getchar();
        }
    }
    while (c != '\n');
}


void    instanciacao (void)
{
    pol     p1;
    fraccao f;

    le_pol (&p1);
    printf ("Insira uma fraccao na forma (n/d):\n");
    le_f (&f);
    escreve_f(inst_esc_pol(p1, f));
}


void    le_f (fraccao *f)
{ //line fraccoes.c line 19
    int n, d;

    getchar ();
    scanf ("%d", &n);
    getchar ();
    scanf ("%d", &d);
    getchar ();

    assert (d != 0);

    *f = simplifica_f(cria_f(n, d));
}

simplifica_f simplifies a rational and cria_f creates a rationa given the numerator and the denominator

Can someone help me please? Thanks in advance.

If you want me to provide some tests, just post it.

See ya.


You probably need to introduce some error checking - specifically, you need to check that the scanf() calls actually convert a value. My suspicion is that the scattered getchar() calls are eating too little or too much, and that one or more of your scanf() operations is failing, leaving variables such as n and/or d (in le_f()) uninitialized, which then causes problems further down the road.

Always, but always, assume that I/O (especially input) will go wrong - there'll be an idiot on the other end (e.g. me, or you) typing data differently from what your code expects.

For debugging purposes, at least, replace the getchar() calls with your own function that read the character and echoes what was read (and detects EOF and bails out on error - until you've got a more sophisticated error handling scheme in place):

#include <ctype.h>
#include <stdio.h>

static void readchar(void)
{
    int c;
    if ((c = getchar()) == EOF)
    {
        fprintf(stderr, "Unexpected EOF - exiting\n");
        exit(1);
    }
    printf("Got: %d (0x%02X) %c\n", c, c, isprint(c) ? c : '?');
}

Similarly, you should do something similar with the scanf() calls:

static void readint(int *var)
{
    if (scanf("%d", var) != 1)
    {
        fprintf(stderr, "Failed to read integer - exiting\n");
        exit(1);
    }
    printf("Got: %d\n", *var);
}

Use this in place of your scanf() calls. You could improve the diagnostic from readint() by reading the rest of the line into a buffer and printing that:

static void readint(int *var)
{
    if (scanf("%d", var) != 1)
    {
        char buffer[32];
        fprintf(stderr, "Failed to read integer - exiting\n");
        if (fgets(buffer, sizeof(buffer), stdin) != 0)
             fprintf(stderr, "Residual data: <<%s>>\n", buffer);
        exit(1);
    }
    printf("Got: %d\n", *var);
}

You might get two newlines out of the 'residual data' print, but that's better than none (which would happen if the residual line is longer than 31 characters. The information is probably sufficient to tell you where the problem is - lacking any better input tracking.

Using scanf() is usually not the best way to go - you get better control over error handling etc if you read lines with fgets() and then scan the input with sscanf().


Just insert a

getchar()

After reading the int from the menu and you're done ^^

The problem was resulting from the unread '\n' which you input after the menu choice. Use that call to discard it and all goes according to plan.

0

精彩评论

暂无评论...
验证码 换一张
取 消