First of all, I recommend that you give your macros and variables proper descriptive names. I recommend that you change the names like this:
a
to MAX_PLAYERS
b
to MAX_PLAYER_LENGTH
luff
to BUFFER_SIZE
ii
to num_players
minfo
to answer
As already pointed out in the comments section, the variable ii
(which should be renamed to num_players
) has a lifetime which lasts only one single loop iteration. This means that you are creating and initializing a new variable in every loop iteration. If you want it to remember its value from previous loop iterations, you must increase its lifetime to more than one loop iteration, by declaring and initializing it outside the loop.
The statement
if (minfo == 'n' || minfo == 'N') // looks for users input
{
break; // break if user selects n
}
is redundant, because the loop will break automatically if the while
condition is false.
Also, as already pointed out in the comments section, your while
condition is wrong, because it is always true:
} while (minfo == 'y' || 'Y');
The result of the ||
operation will be true if either if its operands is true. Since 'Y'
is non-zero, it is always true, so the ||
operation will also always be true. You should write
} while ( minfo == 'y' || minfo == 'Y');
instead.
Also, it is good programming practice to reduce the scope of variables to the minimum, so that you don't have too many variables active at once. That way, when debugging your program in a debugger, you have less variables to monitor. Since you are only using i
inside the loop, it would make sense to reduce the scope of that variable to the loop. Therefore, I recommend that you remove the line
int i = 0;
and change the line
for (i = 0; i < a; i++) {
to:
for ( int i = 0; i < a; i++ ) {
The line
strcpy( name[i], buffer );
is wrong, it should be:
strcpy( name[ii], buffer );
Additionally, the lines
scanf("%s", buffer);
strcpy(name[i], buffer);
are dangerous, because if the user enters too much input, then you will have a buffer overflow, which will invoke undefined behavior (i.e. your program may crash). Also, it is always a good idea to check the return value of scanf
, to make sure that the input conversion was successful, before attempting to use the result. Therefore, it would be better to change these lines to the following:
//the format string of scanf should contain the value BUFFER_SIZE - 1
if ( scanf( "%1023s", buffer ) != 1 )
{
fprintf( stderr, "Input conversion failure!\n" );
exit( EXIT_FAILURE );
}
if ( strlen( buffer ) >= MAX_PLAYER_LENGTH )
{
fprintf( stderr, "Input too long for buffer!\n" );
exit( EXIT_FAILURE );
}
strcpy( name[num_players], buffer );
Note that you must add #include <stdlib.h>
to the program, in order to be able to use the function exit
.
It would also be good to check the return value of scanf
in the following line:
scanf(" %c", &minfo);
The loop
for (i = 0; i < a; i++) {
does not make sense, because a
is MAX_PLAYERS
if you rename it as described above. You want the loop to iterate num_players
times, not MAX_PLAYERS
times. For example, you don't want it to print 10 players if the user only entered 3 players.
After making all of these changes, your program should look something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_PLAYERS 10
#define MAX_PLAYER_LENGTH 32
//if you change this value, then the scanf format string in the
//function main must also be changed, so that it contains one less
//than this value
#define BUFFER_SIZE 1024
int main( void )
{
char name[MAX_PLAYERS][MAX_PLAYER_LENGTH];
char buffer[BUFFER_SIZE];
char answer;
int num_players = 0;
do
{
printf( "Enter a name for player: " );
//the format string of scanf should contain the value BUFFER_SIZE - 1
if ( scanf( "%1023s", buffer ) != 1 )
{
fprintf( stderr, "Input conversion failure!\n" );
exit( EXIT_FAILURE );
}
if ( strlen( buffer ) >= MAX_PLAYER_LENGTH )
{
fprintf( stderr, "Input too long for buffer!\n" );
exit( EXIT_FAILURE );
}
strcpy( name[num_players], buffer );
if ( num_players == MAX_PLAYERS )
{
printf( "Stopping because of reaching %d players.\n", MAX_PLAYERS );
break;
}
num_players++;
printf( "Do you want to repeat the operation and add more? (Y/N):" );
} while ( scanf( " %c", &answer ) == 1 && answer == 'y' || answer == 'Y');
printf( "\nThe names entered are:\n" );
for ( int i = 0; i < num_players; i++ )
{
printf( "%s\n", name[i] );
}
return 0;
}
This program has the following behavior:
Enter a name for player: Mike
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Jimmy
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Bob
Do you want to repeat the operation and add more? (Y/N):n
The names entered are:
Mike
Jimmy
Bob
So, at first glance, it seems to work. However, with this input, it does not behave well:
Enter a name for player: Player1
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player2
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player3
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player4
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player5
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player6
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player7
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player8
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player9
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player10
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player11
Stopping because of reaching 10 players.
The names entered are:
Player1
Player2
Player3
Player4
Player5
Player6
Player7
Player8
Player9
Player10
As you can see, the message
Stopping because of reaching 10 players.
only appears after the user has already entered 11 players. This does not seem meaningful. It does not make sense for the program to allow entering an 11th name if the maximum number of players is 10, and the 11th name is discarded. It would be best if the program did not even ask the user if he wants to enter another name, if he has already reached the maximum. Therefore, it would make sense to move the lines
if ( num_players == MAX_PLAYERS )
{
printf( "Stopping because of reaching %d players.\n\n", MAX_PLAYERS );
break;
}
closer to the end of the loop, immediately before the line
printf( "Do you want to repeat the operation and add more? (Y/N):" );
After doing this, the behavior is now correct:
Enter a name for player: Player1
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player2
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player3
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player4
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player5
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player6
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player7
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player8
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player9
Do you want to repeat the operation and add more? (Y/N):y
Enter a name for player: Player10
Stopping because of reaching 10 players.
The names entered are:
Player1
Player2
Player3
Player4
Player5
Player6
Player7
Player8
Player9
Player10