Instead of reading input using scanf(), you could read full lines (up to a limited length) using fgets(). If you use Linux or Mac OS X, then you could use getline() to get unlimited length lines even easier.
Anyway, here is one very useful thing you could consider. I hope it is not too complicated.
A helper function, get_line(), reads a line of input into an internal buffer (specially kept existing between function calls: static). It then removes any leading and trailing whitespace (think accidental spaces) and the newline characters, and returns a pointer to the string. (It can also save the length of the line into a size_t variable, if asked.)
Code:
#include <stdio.h>
#include <string.h>
char *get_line(FILE *const input, size_t *const length)
{
static char buffer[1024];
char *p;
size_t n;
/* Read a new line of input. */
p = fgets(buffer, sizeof buffer, input);
if (!p)
return NULL;
/* Skip leading whitespace characters. */
p += strspn(p, "\t\n\v\f\r ");
/* Find the newline char(s), */
n = strcspn(p, "\n\r");
/* Backtrack any whitespace characters, */
while (n > 0 &&
(p[n-1] == '\t' || p[n-1] == '\v' ||
p[n-1] == '\f' || p[n-1] == ' '))
n--;
/* and trim them out. */
p[n] = '\0';
/* Length requested? */
if (length)
*length = n;
/* We can return p only because it points to a buffer
* that is marked static. Otherwise the buffer contents
* would vanish when this function returns. */
return p;
}
Now, if you wanted to start a game by asking the players names, you could do it like this:
Code:
#define MAX_PLAYERS 32
int main(void)
{
char *player_name[MAX_PLAYERS];
int players = 0;
char *line;
size_t len;
do {
printf("Enter player %d name, or an empty line if no more players:\n", 1 + players);
line = get_line(stdin, &len);
if (!line || !len)
break;
player_name[players] = strdup(line);
if (!player_name[players]) {
printf("Ouch; I ran out of memory. Sorry.\n");
exit(1);
}
players++;
} while (players < MAX_PLAYERS);
if (players < 1) {
printf("No players? Okay.\n");
exit(0);
}
if (players >= MAX_PLAYERS) {
printf("All player seats are now taken!\n");
}
/* Rest of main() ... */
Since the name is a full line, you can have spaces in players' names. Useful if you have two or more with similar/same first names!
Because the line buffer is reused for each line, you need to use strdup() to save the persons name for future use. Technically, we should also call free() to free each one after we no longer need them, but since the operating system will do that when the program exits, we don't need to bother with that for the names.
If you were to ask (and save) a player for a number between 1 and 10, inclusive, you could do it like this:
Code:
int player_number[MAX_PLAYERS];
int player;
player = 0;
do {
printf("Your turn, %s. Input a number between 1 and 10, inclusive.\n", player_name[player]);
line = get_line(stdin, NULL);
if (!line) {
printf("Aborted.\n");
exit(1);
}
if (sscanf(line, "%d", &player_number[player]) < 1) {
printf("%s is not a number to me, %s. Try again, please.\n", line, player_name[player]);
continue;
}
if (player_number[player] < 1) {
printf("%s is too small, %s. It must be 1 or greater. Try again, please.\n", line, player_name[player]);
continue;
}
if (player_number[player] > 10) {
printf("%s is too large, %s. It must be 10 or less. Try again, please.\n", line, player_name[player]);
continue;
}
printf("%s chose number %d.\n", player_name[player], player_number[player]);
/* Advance to next player, but go back to 0 at players.
* % means "the remainder of left side, when divided by right side",
* also known as the modulus operator.
*/
player = (player + 1) % players;
/* but only do one round; stop when player == 0. */
} while (player != 0);
After the round, you have the numbers they chose in player_number[0 .. players-1]. It is not a for loop, as you couldn't then retry as easily. Since we only move to the next player at the very end of the loop body, we can retry by simply using continue, which just skips to the start of the next iteration. (If we use a for loop, the loop variable would have been updated -- giving us the next player instead.)