Problems Using scanf

Hi all,
I have recently been coding a very simple game for my own amusement and have run across a problem. I have fairly little experience using c++ though I have been taught the basics through a lecture course. In this course I was told for the sake of simplicity to assume the user will always follow instructions. I would however, like to be able to "error-proof" my use of the scanf function in the below switch statement to prevent the code looping if, for example, the user inputs a character rather than an integer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
int main(void)
{
	FILE* input_file;
	int zombie_initiative=0, zombie_numbers=0, survivor_numbers, flee=0;
	int menu=0, count, count_rows=0, count_columns=0, zombie_count=0, survivor_count=0, end_of_file, initiative_count;
	char input_text[100];
	double zombie[] = {10, 1, 50, 0, 7, 1, 3, 0};
	double george[] = {20, 1, 50, 3, 5, 0, 3, 5};

	/* Pre-combat initialisation */
	printf("Performing pre-combat initialisation, please stand by.\n------------------------------------------------------\n");
	
	zombie_numbers=1; /* Defines how many zombies there are in this group. For the purpose of this example, it's already been set */
	survivor_numbers=1; /* Defines how many survivors fight. Also set for the example. */

	srand(time(NULL)); 

	for(count=0; count<zombie_numbers; count++)
	{
		zombie_initiative = (rand() % 11);
		zombie[7] = zombie_initiative;
		printf("\nZombie number %d has an initiative of %d.\n\n",zombie_count, zombie_initiative);

		zombie_stats(zombie, input_text, zombie_count); /* Prints the list of Zombie stats with table headers */
	}

	for(count=0; count<survivor_numbers; count++)
		survivor_stats(george, input_text, survivor_count); /* Prints the list of Survivor stats with table headers */

	printf("Initialisation complete.\n------------------------\n\n");

	do{
		for(initiative_count=10; initiative_count>-1; initiative_count--)
		{
			if(george[7]==initiative_count)
			{
				do{
					printf("1. Attack\n2. Flee\n3. Check Current Status\n4. Use Item\n\n");
					scanf("%d",&menu);
					printf("\n");
					switch(menu)
					{
						case 1:
																		if(george[0]>0)
										survivor_attack(george, zombie);

									if(zombie[0]<1)
										zombie_numbers--;

									break;
						case 2:
									survivor_numbers--;
									flee++;

									break;
						case 3:
									for(count=0; count<zombie_numbers; count++)
										zombie_stats(zombie, input_text, zombie_count); /* Prints the list of Zombie stats with table headers */

									count=0;

									for(count=0; count<survivor_numbers; count++)
										survivor_stats(george, input_text, survivor_count); /* Prints the list of Survivor stats with table headers */

									break;
						case 4:
									printf("This has yet to be implemented. Please return from whence ye came.\n\n");

									break;
						default:
									printf("Invalid choice.\n\n");

									break;
					}
				}while(menu==3 || menu==4);
			}
			else if(zombie[7]==initiative_count)
			{
				if(zombie[0]>0 && flee==0)
					zombie_attack(zombie, george);

				if(george[0]<1)
					survivor_numbers--;
			}
		}
	}while(zombie_numbers>0 && survivor_numbers>0);

	if(zombie_numbers<1)
		printf("You have survived another fight.\n");
	else if(survivor_numbers<1 && flee==0)
		printf("You have been defeated.\n");
	else if(zombie_numbers>0 && survivor_numbers<1 && flee!=0)
		printf("You manage to escape.\n");

	printf("\n");

	return 0;
}


If somebody could please help me to implement such a system, I would really appreciate it! Many thanks in advance.
I'd suggest you use C++'s stream operators >> instead of scanf. As far as I know, scanf is a C function.

Instead of FILE *, you could try using std::fstream
If you use C++, you can accept the user input as a string and check if they have followed correct procedure. If they haven't, you can clear the string and make them enter their choice again, otherwise, you can easily turn the string into a number and use it as normal.
Unfortunately, I've never been taught a thing about stream operators. Might be worth looking into though, if it'll simplify all my code.
Thanks for the advice Mats. If you wouldn't mind, could you explain how you might go about doing that?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>

int main(void)
{
    for (;;)
    {
        int menu;

        printf( "\n1. Attack\n2. Flee\n3. Check Current Status\n4. Quit\n\n");

        int fieldsExtracted;
        if (1 != (fieldsExtracted = scanf("%d", &menu)) || menu < 1 || menu > 4 )
        {
            printf("ERROR: ");

            if (fieldsExtracted == 1)
                printf("Option %d is not a valid option.\n\n", menu);
            else
            {
                printf("Invalid input.\n\n");
                scanf("%*[^\n]");  // remove junk from input stream.
            }

            continue;
        }

        switch (menu)
        {
        case 1:
            printf("You attack!\n");
            break;

        case 2:
            printf("You flee!\n");
            break;

        case 3:
            printf("You check your status!\n");
            break;

        case 4:
            printf("You quit!  Byebye!\n");
            return 0;
        }
    }
}
Hmm well actually, if you use strings, there is no need to use numbers at all. You could do something like this, which will accept user input in a more user friendly manner, while rejecting incorrect inputs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <string>

using namespace std;

int main()
{
    int x = 0, y = 0; //Character stats or whatever. 
    string input = "";
    bool gamerunning = 1;
    while(gamerunning == 1)
    {
        input = ""; 
        cout << "Enter your move: (run, fight, use item)\n"; 
        getline(cin,input); //This gets all data inputted by the user until it hits a newline. 
        if(input == "run" || input == "Run") 
        {
            cout << "You run!\n";
        }
        else if(input == "fight" || input == "Fight")
        {
            cout << "You fight the zombie!\n";
        }
        else if(input == "use item" || input == "Use item" || input == "Use Item")
        {
            cout << "You use your wand of create monster.\n";
        }
        else if(input == "quit" || input == "Quit")
        {
            gamerunning = 0; //Which will cause the while loop to exit, exiting the game main loop.
        }
        else
        {
            cout << "Unrecognized input!\n";
        }
    }
    return 0;
}
Last edited on
Topic archived. No new replies allowed.