【问题标题】:Redefiniton of an int error重新定义一个 int 错误
【发布时间】:2013-08-20 18:44:14
【问题描述】:

我在一边自学 C++,我意识到这个问题对某些人来说似乎是补救性的。在我制作的游戏中,作为学习过程的一部分,我希望用户能够选择一个难度,并且当他们选择一个或另一个时,随机数值范围会发生变化。顺便说一下,我使用的编译器是 x-Code。代码如下:

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int secretNumber;

int main() //integrate difficulty chooser where easy is a number b/w 1 and 10, norm 1 and 50, and hard is 1 and 100
{
    srand(static_cast<unsigned int>(time(0))); //seeds random number by time read on system

    int guess;
    int choice;

    char again = 'y';

    cout << "\tWelcome to Guess My Number\n\n";
    cout << "Please choose a difficulty:\n";
    cout << "1 - Easy\n";
    cout << "2 - Normal\n";
    cout << "3 - Hard\n";
    cin >> choice;

    while (again =='y')
    {
        int tries = 0;
        int secretNumber;
        do
        {                
            cout << "Enter a guess: ";
            cin >> guess;
            ++tries;

            switch (choice)
            {
                case 1:
                    cout << "You picked Easy.\n";
                    int secretNumber = rand() % 10 + 1;
                    break;            
                case 2:
                    cout << "You picked Normal.\n";
                    int secretNumber = rand() % 50 + 1;
                    break;
                case 3:
                    cout << "You picked Hard.\n";
                    int secretNumber = rand() % 100 + 1;
                    break;                    
                default:
                    cout << "You have made an illegal choice.\n";
            }

            if (guess > secretNumber)
            {
                cout << "\nToo high!";
            }
            else if (guess < secretNumber)
            {
                cout << "\nToo low!";
            }
            else if (guess == secretNumber && tries == 1)
            {
                cout << "\nThat's unbelievable! You guessed it in exactly 1 guess";
            }
            else
            {
                cout << "\nGreat job, you got it in just " << tries << " guesses!\n";
            }

        }
        while(guess != secretNumber);

        cout << "Do you want to play again y/n: ";
        cin >> again;
    }

    return 0;

}

在我尝试重新定义 secretNumber 的值的情况 2 和 3 中发生 2 个错误。

【问题讨论】:

  • 我不太确定问题是什么...?
  • 您是否打算在每次猜测后改变数字,对还是错?因为这就是它现在正在做的事情。 switch (choice) 语句应该在内部循环之外,如果您希望每场比赛一个数字,而不是每次猜测。

标签: c++ int redefinition


【解决方案1】:

case 块不会打开不同的范围,而是同一个块的一部分。您的代码(仅考虑范围)看起来类似于:

int secretNumber;
{
int secretNumber = rand() %  10 + 1;
...
int secretNumber = rand() %  50 + 1;
...
int secretNumber = rand() % 100 + 1; 
}

在同一个作用域中声明了三个不同的同名变量,这在语言中是不允许的。请注意,switch 中的所有三个声明也会隐藏在外部作用域中声明的变量,这可能不是您想要的。

【讨论】:

  • 我以为你不能在switch语句中声明变量,但我显然没有完全理解switch语句的局限性?请解释。现在看到这个stackoverflow.com/questions/1231198/…,但这是客观的。
  • @user2672165:这很复杂;你可以直接在 switch 中使用变量,因为 switch 只是一个带有特殊标签和内置 if/goto 的块。但是就像 gotos 一样,你不能跳过变量的定义进入它的范围——这实际上使变量在最后一种情况之外是非法的。 (当您为定义变量的每个案例使用大括号时,这种怪异几乎消失了,这为变量创建了一个新范围;跳过案例然后跳过整个范围,所以你很好。)
  • 是的,您可以定义块级变量,但在这种情况下您不需要它。在 switch 语句级别,您只能声明一次变量。
  • @user2672165:您可以定义变量,但每个案例都不是一个范围,而是所有案例都是同一范围的一部分,因此您不能使用相同的名称声明不同的变量。除了我的印象是你不想想要在那里定义4个变量,而只是使用外部块中的那个,你可以通过重命名来测试不同变量的创建secretNumbersecretNumber# 其中#case 中的数字。这将毫无问题地编译。
  • @DavidRodríguez-dribeas:在 C++ 中?几乎不。 int main(int argc, char**) { switch (argc) { case 0:; int a = 1; break; case 1: break; } 拒绝在 GCC 或 clang 中编译。 “跳转到 case 标签跨越 int a 的初始化”,GCC 说。
【解决方案2】:

看起来你有一些其他语言的背景——可能是一种函数式语言,也可能是一些 JavaScript。

C++ 的一个关键特性是作用域。变量(命名值持有者)在它们所在的范围内具有生命周期,并且变量仅在它们定义的范围内可见。 (不要与对象混淆,通过指针和分配可以将对象从堆栈中取出并放入堆内存中,只有当变量及其地址超出范围时,如果它们没有正确释放,就会丢失)。

{
    int i = 1;
}
std::cout << "i is " << i << std::endl; // compiler error, i does not exist here.
void foo() {
    int i = 1;
}
void bar() {
    foo();
    std::cout << i << std::endl;  // compiler error, i does not exist here.
}

此外,除非修饰为“const”,否则 C++ 变量是可变的 - 它们可以更改。

int i = 1;
i = 2;
std::cout << i << std::endl; // writes 2, not 1. 

所以:您的代码不是“重新定义”secretNumber,它是 shadowing 之前的定义,在当前范围内隐藏它。因此,当您为内部版本分配值时,范围外代码可见的“secretNumber”不会受到影响。

#include <iostream>

int main()
{
    int foo = 1; // outer foo
    std::cout << "Originally, foo = " << foo << std::endl;

    {
        int foo = 2; // inner foo
        std::cout << "Inside the inner scope, foo = " << foo << std::endl;
    }

    // inner foo doesn't exist here, so it references outer foo.
    std::cout << "But the original foo still exists, " << foo << std::endl;
}

您实际上想要做的只是为您在外部范围中声明的原始 secretNumber 变量分配一个新值,因为这是唯一可用于该范围内代码的名为“secretNumber”的变量。

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int secretNumber;

int main() //integrate difficulty chooser where easy is a number b/w 1 and 10, norm 1 and 50, and hard is 1 and 100
{
    srand(static_cast<unsigned int>(time(0))); //seeds random number by time read on system

    int guess;
    int choice;

    char again = 'y';

    cout << "\tWelcome to Guess My Number\n\n";
    cout << "Please choose a difficulty:\n";
    cout << "1 - Easy\n";
    cout << "2 - Normal\n";
    cout << "3 - Hard\n";
    cin >> choice;

    while (again =='y')
    {
        int tries = 0;
        int secretNumber;
        do
        {                
            cout << "Enter a guess: ";
            cin >> guess;
            ++tries;

            switch (choice)
            {
                case 1:
                    cout << "You picked Easy.\n";
                    secretNumber = rand() % 10 + 1;
                    break;            
                case 2:
                    cout << "You picked Normal.\n";
                    secretNumber = rand() % 50 + 1;
                    break;
                case 3:
                    cout << "You picked Hard.\n";
                    secretNumber = rand() % 100 + 1;
                    break;                    
                default:
                    cout << "You have made an illegal choice.\n";
            }

            if (guess > secretNumber)
            {
                cout << "\nToo high!";
            }
            else if (guess < secretNumber)
            {
                cout << "\nToo low!";
            }
            else if (guess == secretNumber && tries == 1)
            {
                cout << "\nThat's unbelievable! You guessed it in exactly 1 guess";
            }
            else
            {
                cout << "\nGreat job, you got it in just " << tries << " guesses!\n";
            }

        }
        while(guess != secretNumber);

        cout << "Do you want to play again y/n: ";
        cin >> again;
    }

    return 0;

}

这也是许多 C++ 程序员选择使用前缀和后缀符号来区分某些类型的变量的原因之一:

#include <iostream>

class Foo {
public:
    int m_i;  // member variable, m_xxx
    Foo(int); // constructor taking an int.
};

static int s_i;

Foo::Foo(int i_)   // arguments use _ suffix
{
    int i = i_;    // local value of i
    i *= 3;
    m_i = i;       // we're assigning it the local value, not the argument.
}

int main()
{
    int i = 1;
    Foo foo(2);
    s_i = 3;

    std::cout << "i = "<<i<<", foo.m_i = "<<foo.m_i<<", s_i = "<<s_i<< std::endl;
}

现场演示:http://ideone.com/dSTwPT

【讨论】:

    【解决方案3】:

    您收到编译时错误,因为您在同一范围内(case 语句块级范围)重新声明了同一变量。您需要在所有 case 语句中删除 secretNumber 之前的 int 。否则,在 while 循环块级别声明的 secretNumber 变量将保持未定义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多