1

This is a self-help program I made for useful break activities. At the end of it need to type a number, then press "enter" to restart. I'd rather have to only type anything, or any number.

#include <stdio.h>
#include <stdlib.h>

main()
{
  int i;

  srand((unsigned)time(NULL));

  i = rand();

  int k;
  k = (int)i%22;
  printf("\n\n");

   switch(k){


            case 0: printf("%\t Weather"); printf(" weather"); break;                        
            case 1: printf("\t Hand exercises ok"); break;

            case 2: printf("\t BR break"); break;

            // etc etc            
            case 15: printf("\t ~~ DOODLE ON PAPER ## "); break;
            case 16: printf("\t Practice Mental Math "); break;
            case 17: printf(" \tgo to SNOPES.com\t"); break;

            case 18: printf("\t Browse JAVA API"); break;
            case 19: printf("\t Left handed writing"); break;
            case 20: printf("\tGo outside OUTSIDE\t"); break;
            case 21: printf("\tCall M&K\t"); break;
            case 22: printf("TRASH CAN BBALL\t"); break;


            }

            printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

        long g;

        scanf("%d", &g);

        if(g >0){
                 system("cls");
                 main();
                 }


     system("pause");
}

I use this as a simple Windows App. If there are other issues/problems I'm totally open to criticism as I'm still new to C. I appreciate any tips or advice.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
Caffeinated
  • 11,982
  • 40
  • 122
  • 216
  • Calling `main()` isn't allowed from a C program. – Carl Norum Mar 04 '12 at 05:13
  • 1
    Well it compiled and worked... Isn't main just a function? Stylistically it's bad..i know – Caffeinated Mar 04 '12 at 05:13
  • 1
    Lots of undefined behaviour may "compile and work" - that doesn't make it a good idea. – paxdiablo Mar 04 '12 at 05:15
  • For a toy program like this, it's probably not worth worrying about. – rob mayoff Mar 04 '12 at 05:15
  • @CarlNorum - OK so it's inefficient. http://stackoverflow.com/questions/7810814/calling-main-function-more-than-once-is-a-good-practice-in-c – Caffeinated Mar 04 '12 at 05:15
  • @paxdiablo - What's the worst-case situation for me? Like what damage can be wrought here by my sloppiness? I do get worried about C – Caffeinated Mar 04 '12 at 05:18
  • 2
    In theory, the compiler's allowed to generate code that does anything, such as erasing your hard drive or going on a murderous rampage. In practice, that sort of thing only happens when targetting embedded devices. – rob mayoff Mar 04 '12 at 05:19
  • 1
    I suppose it is technically *allowed*, but I'm with the others who say it's probably not a great idea. – Carl Norum Mar 04 '12 at 05:19

3 Answers3

4

If you have access to the conio library, you can use kbhit() to catch a keypress:

#include <conio.h>

int main(void) {
  while (1) {
    /* ... */

    if(kbhit())
    {
       break;
    }
  }
}
rjz
  • 16,182
  • 3
  • 36
  • 35
  • You are Awesome, Thank You Very Much! conio.h is my new friend – Caffeinated Mar 04 '12 at 05:18
  • 1
    If `conio` is your friend, you're no friend of mine :-) This is inherently unportable. – paxdiablo Mar 04 '12 at 05:23
  • @paxdiablo - Ouch! Well OK fair point, what should I do to make this portable. – Caffeinated Mar 04 '12 at 05:24
  • Is there a portable conio equivalent? Will curses work on Windows? – Agnel Kurian Mar 04 '12 at 05:25
  • @paxdiablo - I did get a weird error that says: `stray '\160' in program` – Caffeinated Mar 04 '12 at 05:26
  • 1
    I don't know of a portable `conio`...there are a variety of `kbhit()` alternatives of varying reliability, though. – rjz Mar 04 '12 at 05:28
  • 1
    @Adel, I don't think that's anything to do with using conio, that's a funny character that you've managed to slip into your source code. As to a portable equivalent to kbhit, there isn't one in ISO. POSIX has a way of doing it but, provided you understand the portability issues, you can use kbhit just fine (I _did_ put a smiley at the end of that comment above) – paxdiablo Mar 04 '12 at 05:30
  • @paxdiablo - Aah I see now, that's cool. Hey no offense taken at all, And thanks a lot for the helpful info about kbhit and ISO! – Caffeinated Mar 04 '12 at 05:34
1

main is a function like any other. There is nothing special about it except the C Runtime's startup function (usually called 'start()' sets up parameters and calls it. Go nuts.

Especially in your case where you didn't care about argc/argv.

Anyways - your real problem is that stdin is line oriented by default - so any getc/getchar/scanf is going to be buffered until a carriage return. There are various ways of undoing this based on the OS.

setvbuf() and friends can change the buffering, but it may not work depending on your OS because the underlying file handles of the system may remain buffered.

Some OS's have other functions like kbhit(); (not ansi) or the like. Sorry it's not a solid answer - what's your OS?

Joe
  • 2,946
  • 18
  • 17
1

First off, you shouldn't be calling main at any point in your code. If you want to restart, simply code up a loop that continues until the termination condition. I can't recall whether recursively calling main is valid according to the standard but, even if it was, you risk crashing due to uncontrolled recursion.

If you want to allow empty entry (just the ENTER key) to terminate input, you can use fgets to get a line (empty or not), then evaluate that.

I always point people towards my robust user input function and, if you use that, you can simply code up something like:

// Force initial entry into loop
int rc = RC_NO_INPUT;
char buff[] = {`x', '\0`};
:
// Run loop until empty input.
while ((rc == OK) && (*buff != '\0')) {
    // Do whatever you need to do here.

    // Get input, 'while' loop will check it.
    rc = getLine ("ENTER to exit, anything else to continue: ",
        buff, sizeof (buff));
}
Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953