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***
不是注释(至少不是全部)因为***
仍然算作代码的一部分,并且会导致错误。要么将 //
向左移动一点,要么将整个部分用 /* ... */
括起来
在编译我的 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***
不是注释(至少不是全部)因为***
仍然算作代码的一部分,并且会导致错误。要么将 //
向左移动一点,要么将整个部分用 /* ... */