The first thing you need to remember is to never use gets again, more on that here.
The second is to not mix gets (or rather fgets, which is what you should use to replace gets) and scanf.
The root of your problem is that in the second loop, gets reads the newline character left in the buffer by the scanf at the end of the loop, making it seems as though it was skipped, it was not, if you print b[2].name you'll see that it has a newline character.
Your code should look more like this:
void clear_buffer(){ //helper function to clear buffer when needed
    int c;
    while((c = getchar()) != '\n' && c != EOF){}
    printf("Bad input, try again: ");
}
//...
int main(void)
{
    int i;
    bk b[100];
    for (i = 0; i < 3; i++)
    {
        printf("Enter name of book %d: ", i);
        while(scanf(" %99[^\n]", b[i].name) != 1){ // mind the space before specifer
            clear_buffer(); 
        }
        printf("Enter price of book %d: ", i);
        while(scanf("%f", &b[i].price) != 1){
            clear_buffer(); // if the value was not parsed correctly, ask again
        }
        printf("Enter pages of book %d:", i);
        while(scanf("%d", &b[i].pages) != 1){
            clear_buffer();
        }
    }
    //...
    //rest of the code
}
The code has some improvements:
- Using - scanf(" %99[^\n]", b[i].name)makes sure that there will be no buffer overflow, it will read, at most 99 caracters, reserving a space for the null terminator, which is something- getscannot do, that's why it was removed from the language, though some compiler still support it, I can't immagine why.
 
- I'm checking if the - scanfreally parses the values, if not, let's say someone inputs a character instead of a digit, it asks again, instead of entering an infinite loop which is what would happen before.
 
- for (i = 0; i < 3; i++)makes sure the array is being populated from index 0, the way you have it, it will not use the first element of the array, you'll have to fix the- printfaccordingly..