Error: expected declaration specifiers or '...' before string constant [puts() and gets() statement errors

Error: expected declaration specifiers or '...' before string constant [puts() and gets() statement errors

在编译我的 Dice Roll 程序后,我得到了这个错误。代码有什么问题?

同样在我使用 gets() 而不是 scanf() 命令之前,但正因为如此我得到了这个错误 - 传递 'gets' 的参数 1 使指针来自整数而不进行强制转换 所以我删除了 gets() 命令并使用了 scanf,然后没有关于 scanf() 的错误。

出现这两个错误的原因是什么?


好的,根据答案我知道了我应该如何使用 gets() 命令以及为什么我不应该使用它而应该使用 scanf()。所以,我做了改变。 虽然我遇到了两个新错误,但这一次与我使用的 delay() 命令有关。

错误:未定义延迟引用 |错误:ld 返回了 1 个退出状态|


好的,所以我通过使用 windows.h 库中的 Sleep() 命令而不是 Delay() 命令解决了我的最后一个错误。程序已编译。 但是程序中仍然存在运行时错误,它在获得 roll1 之前运行良好,但随后它只打印下两个语句并终止程序而没有输入猜测。

跳过printf("Will it be Higher/Lower or the same? (press H/L/S)\n");之后的所有代码,直接结束程序


好的所以我解决了上面的问题,在 scanf(" %c", &nextGuess); 语句中的 "%c" 之前添加了一个空格。 (小事xD) 现在唯一的问题是我的 toupper() 命令不起作用。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <windows.h>


int main()
{
    int i, roll1=0, roll2=0, NumberOfRolls, RandomNUM1[50], RandomNUM2[50];
    char nextGuess;

    puts("Welcome to the Dice Roll Game");
    puts("How many times do you want to roll a dice?");
    scanf("%d", &NumberOfRolls);

    for( i=1; i<=NumberOfRolls; i++ ) {
        RandomNUM1[i] = ( rand()%6 ) + 1;
        roll1 += RandomNUM1[i];
    }

    printf("\nYou Got %d in your first roll!\n", roll1);
    Sleep(3000);
    printf("\nLet's see if you can guess the value of next roll.\n");
    printf("Will it be Higher/Lower or the same? (press H/L/S)\n");
    scanf(" %c", &nextGuess);
    toupper(nextGuess);

        for( i=1; i<=NumberOfRolls; i++ ) {
        RandomNUM2[i] = ( rand()%6 ) + 1;
        roll2 += RandomNUM2[i];
    }

    if(nextGuess=='H'){
        if(roll1<roll2){
            printf("You are such a player, you guessed it right! It's %d", roll2);
        }
        else if(roll1>roll2){
            printf("Uh-Oh! Bad Luck! First roll was higher, It's %d", roll2);
        }
        else if(roll1==roll2){
            printf("Uh-Oh! Bad Luck! Both the rolls are same, It's %d", roll2);
        }

    }

    if(nextGuess=='L'){
        if(roll1>roll2){
            printf("You are such a player, you guessed it right! It's %d", roll2);
        }
        else if(roll1<roll2){
            printf("Uh-Oh! Bad Luck! First roll was lower, It's %d", roll2);
        }
        else if(roll1==roll2){
            printf("Uh-Oh! Bad Luck! Both the rolls are same, It's %d", roll2);
        }

    }

    if(nextGuess=='S'){
        if(roll1==roll2){
            printf("You are such a player, you guessed it right! It's %d", roll2);
        }
        else if(roll1>roll2){
            printf("Uh-Oh! Bad Luck! First roll was higher, It's %d", roll2);
        }
        else if(roll1<roll2){
            printf("Uh-Oh! Bad Luck! Second roll is higher, It's %d", roll2);
        }

    }

        return 0;
}

gets 函数从 stdin 读取一个字符串(直到下一个换行符),因此它要求一个指向它所在内存区域的字符指针 (char*)可以把读到的所有字符包括字符串终止符。你犯的错误是向该函数传递了一个指向 int 的指针,因此 不仅你得到了一个编译器错误 因为你试图将一个 int 指针传递给 gets (为此有 none 隐式转换),但即使它编译了,它也不会像你预期的那样工作,因为它会把所有字符(大小为 一个字节 - 大多数时候)在该内存区域编码为字符。这意味着当您尝试使用指向 int 的指针取消引用一个时,字符是 "read like they were an int"!

有一个示例(假设 1 字节字符、4 字节 int 和一个小字节序机器,并且存在从 int* 到 char* 的隐式转换 ,它不存在但希望会从不存在):

int num
gets(&num);

如果我在stdin中输入123,num的内存区指针足够大,可以包含字符串,但它会包含(十进制表示):

0x31|0x32|0x33|0x00

因为字符串是3个字符长,'1'的ASCII码是0x31,'2'是0x32,'3'是0x33,以'\0'结束!! 然后,当你尝试取消引用它时,你会得到这个 int (二进制表示 - 假设是一个小端机器):

00000000|00110001|00110010|00110011

不是 int 值 123,而是 3224115。 不是你想要的。

当您使用 scanf 函数时,您向该函数传递了一个 格式字符串 ,它 告诉它如何解释传递给的下一个参数它 并在读取的字符串与您指定的正确类型 之间执行适当的转换。这意味着您在编写格式字符串时仍然应该注意您告诉 scanf 函数的内容(如果您告诉它读取一个字符串并向它传递一个指向 int 的指针,程序可能会崩溃) , 但如果您正确编写格式字符串,它会为您执行适当的转换。

这就是为什么使用 scanf 一切都完美无缺(您正在读取一个 int 并且指定“%d”作为格式字符串),而使用 gets 它不会编译以避免 严重错误.

我还想评论一下这个答案的一些要点:

  • 该示例仅用于教学目的,所提供的代码确实不起作用。事实上,我 假设 它编译是为了教学目的;显然,该示例中提供的代码 无法编译
  • 如果在该示例中,我们输入的字符串大于 3 个字符(如果包含空终止符则为 4 个字符)或 int (char) 类型包含少于(多于)4 (1) 个字节,则程序会崩溃,因为我们损坏了其他内存区域
  • 该参考在技术方面比我更专业,所以这里是 gets 函数和 scanf 函数的链接:gets, scanf (and the ASCII Table 也很有用)
  • 您可以将 gets 函数与 atoi 函数一起使用来解析从 gets 中读取的字符串(使用指向足够大的可用内存区域的 char 指针以包含字符串,很难将 (*)) 分配给 int,但 scanf 是最好的方法。

(*) 请记住:如果您分配的内存区域包含 20 个字符,则用户将输入 21 个字符。 atoi 函数失败,但最糟糕的是你有缓冲区溢出(如果你的程序在 root 权限下运行,这可能是一个高安全问题)。

你有一只流浪狗,

main 的第 2 行,您声明 char nextGuess, 而不是 char nextGuess;

编译器告诉您在 , 之后需要说明符或 ...,因此您要么添加这些,要么以 ;.

正确结束该行

对于您提到的另一个问题:

passing argument 1 of 'gets' makes pointer from integer without a cast

因为 gets 参数应该是 char *str 而你没有提供它。

您可以解决这个问题,例如:

char tmp_NumberOfRolls[10];
gets(tmp_NumberOfRolls);  
NumberOfRolls = atoi(tmp_NumberOfRolls);

但我更喜欢 scanf 解决方案

PS:(在现在编辑的代码版本中)***//Error Line*** 不是注释(至少不是全部)因为*** 仍然算作代码的一部分,并且会导致错误。要么将 // 向左移动一点,要么将整个部分用 /* ... */

括起来