0

i'm learning myself programming in c witch basicly no previous programming experience and now i have a weird bug and would like to ask some advice.

In the program flow some of the input data gets suddenly changed and i can't see nor reason why that happens.

1.program starts -> user gets a menu choice -> selects case 1 -> program provides and additional input posiblity.... So far everything works correctly as i could see in debug mode.

2.The user puts in some numbers and the variable gets set to that number. (this happens in input.c)

3.Then the program continues in main.c to info_bottom(). (in circlemenu.c) 4.In there the function getRadius() gets called that should calculate a radius based on the user input set in input.c in point 2.

5.That calculation function is located in circlefunctions.c

But here/there is the strange thing.

If i look in the debugger, i see that the variable diameter and radius are both changed to some weird numbers and not the number that the user specified in point 2. Somehow the data stored in the pointer gets corrupted as far as i can judge. Unfortunately im still to inexperienced with debugging to find this out on my own so hopefully someone can please tell me what is going on. This problem occured while trying to get rid of all global variables in my program.

Im beginning to get a whole new respect and understanding for professional programmers and why it can take so long sometimes to fix bugs o0.

(i also made the corresponding header files but no need to put them up i think?)

main.c

#include <stdio.h>

#include "menu/menu.h"
#include "circle/circlemenu.h"
#include "input/input.h"

int main(void)
{
    while(1)
{
    menu();
    switch(menu_user_input())
{
    case 1:

        info_top();
        cir_user_input();
        info_bottom();
        break;

    case 2:
        system("cls");
        break;

    case 3:
        system("cls");
        break;

    case 8:
        system("cls");
        break;

    case 9:
        system("cls");
        break;

    case 0:
        return(0);

    default:
        system("cls");
        printf("\n **Wrong choice try again...**\n");
        break;
}

}
 return 0;
}

menu.c

#include <stdio.h>
#include "menu.h"

void menu()
{
    printf(" \n Made by ************* 2015.\n");
    printf(" ----------------------------------------\n\n");
    printf(" 1. Calculate circle measurements. \n");
    printf(" 2. \n");
    printf(" 3. \n");
    printf(" 8. Info. \n");
    printf(" 9. Clear screen. \n");
    printf(" 0. Exit. \n \n");
    printf(" Make your choice and press enter: ");
}

input.c

#include <stdio.h>
#include "input.h"

int menu_user_input()
{
    static int number;
    scanf(" %i", &number);
    return number;
}

float cir_user_input()
{
    static float diameter;
    scanf("%f", &diameter);
    return diameter;
}

circlemenu.c

#include <stdio.h>
#include "circlemenu.h"
#include "circlefunctions.h"

void info_top()
{
    system("cls");
    printf(" ----------------------------------------\n");
    printf(" Typ the diameter of the circle: ");
    return;
}

void info_bottom()
{
    printf(" ----------------------------------------\n");
    printf(" The radius = %f \n\n" , getRadius());
    printf(" The surface = %f \n\n" , getSurface());
    printf(" The outline = %f \n" , getOutline());
    printf(" ----------------------------------------\n");
    return;
}

circlefunctions.c

#include "circlefunctions.h"
#include "../input/input.h"
#define PI 3.14

double getRadius()
{
    static diameter = (*cir_user_input);
    double radius = diameter / 2;
    return radius;
}

double getSurface()
{
    double radius = getRadius();
    return PI * (radius * radius);
}

double getOutline(){
    double radius = getRadius();
    return 2 * PI * radius;
}
user2645886
  • 47
  • 1
  • 9
  • 1
    Check warnings: `warning: type defaults to 'int' in declaration of 'diameter' [enabled by default]` `static diameter = (*cir_user_input);` – Anto Jurković Mar 22 '15 at 19:24
  • `*cir_user_input` does not access static variables inside that function... it gives you the code address of the function (which is the "weird numbers" you are seeing). You must get multiple warnings for that line (if not then figure out how to activate your compiler properly). – M.M Mar 22 '15 at 19:29
  • please, for readability and ease of debug, format the code such that each opening brace '{' has the code under it indented, say, 4 spaces, with open/closing braces for the same code block vertically aligned – user3629249 Mar 22 '15 at 21:34
  • in general, except for error exits, a function should have only one entry point and only one exit point. suggest modifying the 'while(1)' statement to something like: int done = 0; while( !done ) and in case 0: done = 1; break; – user3629249 Mar 22 '15 at 21:38
  • with switch/case statements it is usually best to list the cases in numeric order, as (especially when there are lots of cases) much easier to determine if any case has been omitted – user3629249 Mar 22 '15 at 21:41
  • always check the returned value from scanf (and family) to assure the input/conversion operation(s) were successful – user3629249 Mar 22 '15 at 21:46
  • the user prompt, regarding the diameter of the circle probably should indicate the dimension to be used. inches, feet, yards, rods, miles, meters, centimeters, milimeters, etc – user3629249 Mar 22 '15 at 21:50
  • for good programming practice when there is an input error, the program probably should echo the users' input – user3629249 Mar 22 '15 at 21:52
  • regarding this line: 'static diameter = (*cir_user_input);' 1) 'static' should be 'float' 2) to call a function use cir_user_input() 3) cir_user_input returns a float, not a pointer Suggest enabling all warnings when compiling/linking so the compiler can tell you what it finds questionable. Then fix those warnings – user3629249 Mar 22 '15 at 21:57
  • Thank you verry much for all the information. I still lack a lot of common programing sence but then again im still a novice. I adjusted the main.c as you adviced. i left the output unit blanc as it is in the decimal number system and i live in europe. The was basicly intentionally but i can adjust it ofcourse. The input check is on my to-do list but i want to tackle one problem at the time before going on to the next. Ill try and configure my debugger more but yesterday was the first day i ever used a debugger os im not that wel versed with it yet unfortunately. – user2645886 Mar 23 '15 at 11:52

2 Answers2

1

You are using your cir_user_input in your getRadiusfunction like a variable/pointer, although it is a function. It is surprising that this works without any warnings or errors (would be interesting to know what compiler you are using).

I think what you actually intended was something like this, i.e., a call to cir_user_input which stores the result in a float variable.

double getRadius()
{
    float diameter = cir_user_input(); //float type; not static (see below)
    double radius = diameter / 2;
    return radius;
}

Furthermore, the switch statement in your main function only calls the user input function cir_user_input, but none of the calculation routines (case 1). Since the return value of the function is not store, it cannot be used later.

In addition, you have seem to be confused about the use of the static key word:

This problem occured while trying to get rid of all global variables in my program.

When you use the static key word to declare variables inside a function, they retain their values throughout function calls, i.e., they are effectively global.

Conversely, if you use the static key word for a global variable/function etc., it is only visible inside the file you specified it in. For beginners, this is often confusing since the key word is written in exactly the same way, see What does "static" mean?.

Best regards Andreas

Community
  • 1
  • 1
  • Thank you verry much for the clarifications. i was indeed confuced about the STATIC but your explanation made it quite clear. I do use code blocks as a programming/compiler tool. I'm just a beginner and i needed to start somewhere simple :). Im runnin basicly everything with default settings and only activated some extra warning in the debugger. minnd you tho that i ony today started to use a debugger in my life so im really novice in that all. I was happy i could easely add breakpoints and run trough the program step bij step . But with your suggestion gives a new set of issues unfortunat – user2645886 Mar 22 '15 at 19:39
  • @user2645886: Please consider accepting an answer if it helped you at solving your problem. If you have additional problems with an adapted version of your program, please ask a new (separate) question. Thank you. – Andreas Unterweger Mar 23 '15 at 16:52
0
here is a good implementation of the main() function

#include <stdio.h>

#include "menu/menu.h"
#include "circle/circlemenu.h"
#include "input/input.h"

int main(void)
{
    int done = 0;
    while( !done )
    {
        menu();
        switch(menu_user_input())
        {

            case 0:
                done = 1;
                break;

            case 1:
                info_top();
                cir_user_input();
                info_bottom();
                break;

            case 2:
                system("cls");
                break;

            case 3:
                system("cls");
                break;

            case 8:
                system("cls");
                break;

            case 9:
                system("cls");
                break;

            default:
                system("cls");
                printf("\n **Wrong choice try again...**\n");
                break;
        } // end switch

    } // end while
    return 0;
} // end function: main
user3629249
  • 16,402
  • 1
  • 16
  • 17