I'm a beginner in the code world, taking my first programming class this semester. I got bored over spring break and wrote a program to send to some friends just for the fun of it, but I'm having a problem. I want to isolate any character entered that is not an integer and get it to print a silly error message. I used a scanf check of sorts to do it, but unfortunately it instantly loops if the statement fails. (I only wanted it to loop once). Code follows (sorry if it's a little choppy, I copied and pasted):

//Zephraph, 2010
#include <stdio.h>
#include <stdlib.h>

int Ndice (void);
int prog (void);
void Side1 (void); //Again, chopped these off
void Side2 (void); //so the code wouldn't be
void Side3 (void); //as long.
void Side4 (void);
void Side5 (void);
void Side6 (void);

int main (void)
{
   char ans;
   printf ("Welcome to the dice simulator!\n\n");
   
   prog ();
  
   printf ("Would you like to re-run the program? (y/n)\n");
   scanf  ("%c", &ans);
  
   if (ans == 'y'){
      printf("\n\n");
      main();
   }
   else
     exit(1);
  
  
  
   return 0;
}

int prog (void)
{
  
   int dice; //number of dice to be rolled
   int times;
   int side;
     
   dice = Ndice ( );
  
   printf ("\nYou've entered: %d\n\n", dice);
  
   if (dice < 0){
      printf ("\nVery funny, wise guy. I'd like to see you roll a negative number of dice.\n"
              "While you're at it, how about dividing by zero? I'll wait. Meanwhile, try again. \n\n");
      prog ();
      }
     
   else if (dice == 0){
      printf ("\nYou DO know this is a dice simulator, right? Oh wait, yeah, I told you.\n"
              "Well, if you enjoy feeling like an imbecile, feel free to enter zero again,\n"
              "otherwise enter something greater than zero, yeah? Try again.\n\n");
      prog ();
      }
     
   else if (dice > 0 && dice <= 10)
      for ( times = 1;times <= dice; times++)
      {
     
         side = 1 + rand() % 6;
        
         if (side == 1)
            Side1();
         else if (side == 2)
            Side2();
         else if (side == 3)
            Side3();
         else if (side == 4)
            Side4();
         else if (side == 5)
            Side5();
         else
            Side6();
        
      }
     
   else {
      printf ("Did you not get the memo? I said 10 or less, and %d is sure as heck not less\n"
              "than 10. You're a numerical failure. Try again.\n\n", dice);
      prog ();    
      }
  
   return 0;
}

int Ndice ( void )
{
   int nrolls = 0;
  
   printf ("Please enter the numerical amount of dice you would like to roll (maximum 10):\n");
  
   if (scanf("%d", &nrolls) !=1 ){
       printf ("\nI'm not even programmed to recognize what you entered, so I'm guessing\n"
              "that it wasn't even a number. You Sir/Madam, are retarded. Read the directions\n"
              "and try again.\n\n");
       prog ();
   }
  
   return nrolls;
}

For the sake of space I chopped off the end functions. All they contain are printf statements of dice "images" if you will. My error is occurring in Ndice(). That function basically asks the user how many dice to roll and, if in the correct bounds, returns the value of nrolls to help calculate other things in the prog() function. That part works golden. But if it fails the IF statement it's suppose to print the error message, call itself, and repeat... but not indefinitely? Which it does.... Any pointers? (By the way, if I remove the call statement it doesn't do the crazy infinite loop but I'm not sure how else to repeat the function).

Oh and also, I kinda want the program to exit upon completion. As in, the console completely close. I've fiddled around with the exit command and even the close and. Can't seem to get it.

Lastly, don't mind the insults on the program. It's all in good fun and my friends know that.

Thanks for any help!

Write the ndice function this way

int Ndice ( void )
{
   int nrolls = 0;
     
    while( /*loop infinitely */)
   {
        printf ("Please enter the numerical amount of dice you would   like to roll (maximum 10):\n");
  
       if(/*If the value entered is not correct */ 
     {
       // Print the error message
      }
       else
            return nrolls;
     }
}

I hope you understood what I am trying to get at

First off, nice screen name :)

now to your problem: note how the function "NDice" is called from the "prog" function.

therefore , you shouldnt re-call your function "prog()" from within NDice.

it's like some sort of infinite recursion or something. like two mirrors facing each other.

this is how you should approach it. you need to make the functions clearly defined to do a certain thing and return to main.

main  
   call "NDice"
       NDice function gets number input
       if input error
           print insult and repeat 
       otherwise
           return number of dice
   
   call "RollDice" (argument : Number from NDice)
       RollDice function rolls number dice requested
       returns value of roll(s)

   "PrintFace" (argument : value from RollDice)
       PrintFace function print results as graphic dice face

end

so, rewrite your program with this simple structure in mind and try again

Edited 6 Years Ago by jephthah: n/a

I went back and tweaked it a little to see if it would have the same problem if it recalled itself and it did. Pretty interesting. I'll have to look into recursion. Meanwhile, trying the first suggestion first and if that's a no go I'll do a re-write as you suggested. I know it's a little congested lol, still trying to wrap my head around "stylistic" programming.

no, don't look up recursion. you're not even there yet.

what i'm saying is, your program is potentially doing this:

main
   prog
      nDice
         prog
            nDice
               prog
                  nDice
                    prog
                       nDice

just don't do that. it could be endless. it will be ugly.

and what i'm saying to do, is not a "stylistic" program

it's just plain and simple. keep your functions simple. write them cleanly. call them one at a time. return back to the caller (main) before calling another one.

this is a simple program, stop making it harder than it needs to be.

Write the ndice function this way

int Ndice ( void )
{
   int nrolls = 0;
     
    while( /*loop infinitely */)
   {
        printf ("Please enter the numerical amount of dice you would   like to roll (maximum 10):\n");
  
       if(/*If the value entered is not correct */ 
     {
       // Print the error message
      }
       else
            return nrolls;
     }
}

I hope you understood what I am trying to get at

I tried this, and I like this approach. Gets rid of the call, unforunately it's still looping.

int Ndice ( void )
{
   int nrolls = 0;
   
   printf ("Please enter the numerical amount of dice you would like to roll (maximum 10):\n");
   
   while( 1 == 1) //That what you meant by infinite loop?
   {//open while

    /* This part  below is questionable. It's my constraint to make sure that what's entered is a variable, but I don't actually know how it works. I was told it works, and it does if I don't try to loop and ask again for the right answer. I actually thing this is what's causing the error but I don't know how else to go about excluding everything but integers*/
     if (scanf("%d", &nrolls) !=1 )

         printf ("\nI'm not even programmed to recognize what you entered, so I'm guessing\n"
                "that it wasn't even a number. You Sir/Madam, are retarded. Read the directions\n"
                "and try again.\n\n");

     else
        return nrolls;

   }//close while
}

And @jepthah, I wasn't specifying that I was going to look into recursion for this project. Just mentioning that I would check it out. I do agree with you that it's a simple program and I know I'm making it harder than it has to be, because only half of what I'm doing I know anything about. The rest is just experimentation and a rough learning experience. A lot of this hasn't been covered in my class, but it's really interesting and I'm doing my best.

It's taking the value for the scanf statement once and not asking for it again. I'm not sure how to address that. This for me is experimentation because it hasn't been covered in class for me.

Oh and if I come across as disrespectful or hard headed, that's truely not my intent. I am greatful for all the assistance because quite frankly I need as much as I can get. To quote Socrates, "I know nothing except the fact of my ignorance."

Edited 6 Years Ago by Zephraph: n/a

its all good. no apologies needed, i can be a bit terse.

while( 1 == 1) //That what you meant by infinite loop?

yes thats an infinite loop. while(1) would accomplish the same. I suggest you use the "break" statement to cause an early break out of the while loop. then return "nrolls" from the end of the function. the way you're doing it, works, but it's sloppy and some compilers will throw a warning. this and other types of bad coding practice are the source of many bugs. i've seen where oddly placed conditional returns have been the root cause of some nightmare debugging efforts.

also you should check that the value is indeed between 1-10, since that's a condition you specify, and zero or negative input will cause bigger problems later.

try this:

int nDice( void )
{
   int nrolls = 0;

   printf ("Please enter the numerical amount of dice you would like to roll (maximum 10):\n");

   while( nrolls < 1 || nrolls > 10) // force a meaningful value to be entered
   {
      if ( scanf("%d", &nrolls) !=1 )
         printf ("\nI'm not even programmed to recognize what you entered, so I'm guessing\n"
                "that it wasn't even a number. You Sir/Madam, are retarded. Read the directions\n"
                "and try again.\n\n");

      else if (nrolls < 1 || nrolls > 10)
         printf ("\nWrong value, jackass.  try again.\n\n");  // hey, you want insults, right?
   }

   return nrolls;
}

.

Edited 6 Years Ago by jephthah: n/a

This article has been dead for over six months. Start a new discussion instead.