在阅读“Pselection”错误后尝试打印“Cselection”时,似乎出现了分割,我不明白为什么

brjng4g3  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(76)

这是一个程序,从用户输入他的名字和选择出石头,布和剪刀。它有一个函数generateRandomNumber(int n),产生0,1或2。根据数字,计算机被分配其选择,并将它们的选择进行比较,看看谁赢得了这一轮。重复3次,得分最高的人获胜。但似乎存在分割错误当尝试打印计算机的选择比较之前的选择。我不明白这个错误背后的原因。请帮助我修复代码。
源代码:

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

int generateRandomNumber(int n)
{
    srand(time(NULL));
    return rand() % n;
}

int main()
{
    int num;
    char PlayerName[50];
    char Pselection[8], Cselection[8];

    printf("Enter Name of Player:\n");
    fgets(PlayerName, sizeof(PlayerName), stdin);
    PlayerName[strcspn(PlayerName, "\n")] = '\0'; // Remove the newline character

    printf("Player 1: %s \nPlayer 2: Computer\n", PlayerName);

    int Cpoints = 0, Ppoints = 0;
    for (int i = 0; i < 3; i++)
    {
        printf("The Game of Rock, Paper, and Scissors begins:\n Enter your selection:\n");
        scanf("%s", Pselection);

        num = generateRandomNumber(3);
        if (num == 0)
            strcpy(Cselection, "rock");
        else if (num == 1)
            strcpy(Cselection, "paper");
        else if (num == 2)
            strcpy(Cselection, "scissors");
        printf("Compueter: %s\n", *Cselection);
        if (strcmp(Cselection, Pselection) == 0)
        {
            continue;
        }
        else if (strcmp(Cselection, "rock") == 0 && strcmp(Pselection, "paper") == 0)
            Ppoints++;
        else if (strcmp(Cselection, "paper") == 0 && strcmp(Pselection, "rock") == 0)
            Cpoints++;
        else if (strcmp(Cselection, "scissors") == 0 && strcmp(Pselection, "paper") == 0)
            Ppoints++;
        else if (strcmp(Cselection, "paper") == 0 && strcmp(Pselection, "scissors") == 0)
            Cpoints++;
        else if (strcmp(Cselection, "scissors") == 0 && strcmp(Pselection, "rock") == 0)
            Ppoints++;
        else if (strcmp(Cselection, "rock") == 0 && strcmp(Pselection, "scissors") == 0)
            Cpoints++;

        else
            printf("\t*******\tSelection Error! Please check your selection and try again.\t*******\t\n");
            
        
        printf("score: %d-%d", Ppoints, Cpoints);

    }

    if (Ppoints >= Cpoints)
        printf("The score is %d-%d \nCongratulations! %s is the winner!\n", Ppoints, Cpoints, PlayerName);
    else
        printf("The score is: %d-%d \nBetter Luck Next Time! The computer won.\n", Ppoints, Cpoints);

    return 0;
}

字符串
错误信息:

‘__builtin_memcpy’ writing 9 bytes into a region of size 8 overflows the destination [-Wstringop-overflow=]


我试着打印一些打印C选择的变体,但是输入P选择后输出停止。

9bfwbjaz

9bfwbjaz1#

你犯了两个错误。
第一个错误:

printf("Compueter: %s\n", *Cselection);

字符串
你不应该用“你”。
第二个错误:

char Pselection[8], Cselection[8];


你有一个输入选项“scissors”。为了能够将它存储到一个数组中,你需要9个插槽。你必须将'\0'字符视为它的一部分。
一个代码,将工作:

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

int generateRandomNumber(int n){
    srand(time(NULL));

    return rand() % n;
}

int main(){
    int i;
    int num;
    int Cpoints, Ppoints;
    char PlayerName[50];
    char Pselection[8], Cselection[8];

    printf("Give a Name: ");
    fgets(PlayerName, sizeof(PlayerName), stdin);
    PlayerName[strcspn(PlayerName, "\n")] = '\0';

    printf("\nPlayer 1: %s\nPlayer 2: PC\n\n", PlayerName);

    Cpoints = 0;
    Ppoints = 0;
    puts("The Game of Rock, Paper, and Scissor begins.\nMay the Odds be in your Favor!\n");
    for (i=0; i<3; i++){
        puts("Make a Choice (rock, paper, scissor):");
        printf("%s: ", PlayerName);
        scanf("%s", Pselection);
    
        num = generateRandomNumber(3);
        if (num == 0)
            strcpy(Cselection, "rock");
        else if (num == 1)
            strcpy(Cselection, "paper");
        else if (num == 2)
            strcpy(Cselection, "scissor");
        
        printf("PC: %s\n", Cselection);
    
        if (strcmp(Cselection, Pselection) == 0);
        else if (strcmp(Cselection, "rock") == 0 && strcmp(Pselection, "paper") == 0) Ppoints++;
        else if (strcmp(Cselection, "paper") == 0 && strcmp(Pselection, "rock") == 0) Cpoints++;
        else if (strcmp(Cselection, "scissor") == 0 && strcmp(Pselection, "paper") == 0) Ppoints++;
        else if (strcmp(Cselection, "paper") == 0 && strcmp(Pselection, "scissors") == 0) Cpoints++;
        else if (strcmp(Cselection, "scissor") == 0 && strcmp(Pselection, "rock") == 0) Ppoints++;
        else if (strcmp(Cselection, "rock") == 0 && strcmp(Pselection, "scissors") == 0) Cpoints++;
        else printf("\t*******\tSelection Error! Please check your selection and try again.\t*******\t\n");
        
        printf("Score: %d/%d\n\n", Ppoints, Cpoints);
    }

    if (Ppoints >= Cpoints)
        puts("Congratulations! You Won!");
    else
        puts("Better Luck Next Time! PC Won!");

    return 0;
}

mu0hgdu0

mu0hgdu02#

  1. scanf("%s", Pselection);在阅读字符串时总是使用最大字段宽度,以避免缓冲区溢出,在这种情况下,即使预期输出“剪刀”也会发生。sizeof "scissors" == sizeof Pselection + 1
    您也可以像前面一样使用fgets(),但是如果您没有读取换行符(这是输入"scissors\n"所期望的),则需要刷新stdin。
int flush() {
   for(;;) {
     int c = getchar();
     if(c == EOF || c == '\n')
         return c;
   }
}

 // ...
 char Pselection[sizeof "scissors"]
 char Cselection[sizeof "scissors"];
 // ...
     fgets(Pselection, sizeof Pselection, stdin);
     size_t j = strcspn(Pselection, "\n");
     if(j + 1 == sizeof Pselection) flush();
     Pselection[j] = '\0';

字符串

  1. strcpy(Cselection, "scissors")是一个类似上面的缓冲区溢出。
  2. Compueter应该是Computer吗?
  3. printf("Compueter: %s\n", *Cselection);应该是Cselection
    1.没有理由在每个随机数上重置种子。将srand(time(NULL));generateRandomNumber()移动到main()
    1.考虑对多行输出使用字符串串联:
printf(
       "Player 1: %s \n"
       "Player 2: Computer\n",
       PlayerName
);


1.考虑将用户选择Map到枚举,而不是将计算机选择Map到字符串。例如:

enum selection { ROCK, PAPER, SCISSORS };

selection getSelection() {
     for(;;) {
        char Pselection[sizeof "scissors"];
        fgets(Pselection, sizeof Pselection, stdin);
        size_t j = strcspn(Pselection, "\n");
        if(j + 1 == sizeof Pselection) flush();
        Pselection[j] = '\0';
        if(!strcmp(Pselection, "rock"))
           return ROCK;
        if(!strcmp(Pselection, "paper"))
           return PAPER;
        if(!strcmp(Pselection, "scissors"))
           return SCISSORS;
        fprintf(stderr, "Selection Error!\n");
     }
}


1.考虑使用一个规则表,而不是如果所有这些条件,以找出什么样的分数为一个给定的回合。我可能会这样做,从球员的Angular ,而不是计算机:

signed char rules[3][3] = {
         {0, -1, 1},
         {1, 0, -1},
         {-1, 1, 0}
   };
   signed char score = rules[getSelection()][generateRandomNumber(3)];
   if(score > 0)
       Ppoints+;
   else if(score < 0)
       Cpoints++;

相关问题