0

Okay everyone first ever post, I am new to C go easy on me please and I am trying to create a few loops in C.

I am trying to create a loop that will continue to loop only if the user types y. I am stuck on adding data into the first for loop that doesn't work right. For the for-loop how can I only added information into name one time but have the array increment with data?

at the end, a user will have the option to add information 10 times, how can I only add the data from the arrays if a user only selects Y for yes X amount of times like 2.

I hope someone can understand what I asking, thanks!!!!!

#include <stdio.h>
#include <string.h>

#define a 10
#define b 32
#define luff 1024

int main() {
    char name[a][b];
    char buffer[luff];
    int i = 0;
    char minfo;

    do {
        // for(i=0; i < a; i++){
        printf("enter a name for player\n");
        scanf("%s", buffer);
        strcpy(name[i], buffer);

        int ii = 0;

        if (ii > 9) {  // if more than 10 users will end
            printf("Excited player input ammount of 10\n\n");
            break;
        }
        ii++;
        printf("\nDo you want to repeat the operation and add more? (Y/N): \n\n");
        scanf(" %c", &minfo);
        if (minfo == 'n' || minfo == 'N')  // looks for users input
        {
            break;  // break if user selects n
        }
        //}
    } while (minfo == 'y' || 'Y');

    for (i = 0; i < a; i++) {
        printf("The array els are %s and\n", name[i]);
    }
    return 0;
}
jps
  • 20,041
  • 15
  • 75
  • 79
anti443
  • 11
  • 1
  • 2
    First, you need to tidy up your code formatting (particularly the indentation), to make it clearer. Next, how will `ii` ever be anything other than `0` immediately after the `int ii=0;` line? – Adrian Mole Jul 03 '22 at 04:18
  • @AdrianMole Hey Adrian I have a ii++; if i am correct wouldn't that add +1 to ii and if ii > 9 it will break? – anti443 Jul 03 '22 at 04:23
  • 2
    No. The `ii` variable is local to its enclosing loop, and it is reset (to zero) each time that loop runs. In fact, it's *technically* a new (different) variable on each loop. Maybe you meant to declare it outside the `do { ... }` loop? – Adrian Mole Jul 03 '22 at 04:29
  • ahhh I see, so it will always return back to 0, big oof. Okay I am going to fix that right now. Do you have any other suggestions. just double checking do you understand what I am asking? – anti443 Jul 03 '22 at 04:38
  • Check the return value from `scanf()` to ensure you got `1`. If you get EOF then you need to bail out. If you get `0`, then there's something in the input that isn't recognizable as part of a number — you probably need to read characters up to the next newline (or EOF): `int c; while ((c = getchar()) != EOF && c != '\n') ;` (where the final semicolon should be on a line of its own as it is the complete body of the loop). – Jonathan Leffler Jul 03 '22 at 04:49
  • See also [Rules on using `scanf()` successfully](https://stackoverflow.com/questions/72178518/how-can-i-fix-the-scanf-to-take-data-into-the-array) and even [A Beginner's Guide Away From `scanf()`](http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html). – Jonathan Leffler Jul 03 '22 at 04:50
  • 1
    Also, `while (minfo == 'y' || 'Y');` will always be true (because `'Y'` is non-zero). You need: `while (minfo == 'y' || minfo == 'Y');` – Adrian Mole Jul 03 '22 at 04:51
  • @JonathanLeffler thank you for the information I am looking at it right now! – anti443 Jul 03 '22 at 05:13
  • @AdrianMole omg, lol you're right, I can't believe I missed that in the while loop. Well as you can see I am new.. thank you :) – anti443 Jul 03 '22 at 05:14
  • I usually find it clearer to have `for(;;)` "forever" loop, and have all end conditions use `break`, if loop end condition is complex like here. – hyde Jul 03 '22 at 06:11

1 Answers1

1

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
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39