繁体   English   中英

Dice Game C ++错误未声明的标识符/代码检查

[英]Dice Game c++ error undeclared identifier/code review

我正在研究每个人最喜欢的C ++项目简介。 骰子游戏。 我很难理解C ++如何来回发送信息以及如何在单独的文件中使用函数和类。 我最大的问题是为什么我在每个变量上都得到未声明的标识符?

直方图

#pragma once
#include "stdafx.h"
#include "histogram.cpp"
#include <cstdlib>
#include <stdio.h>
#include <iostream>

typedef unsigned int uint;

uint rolls = 0, i = 0, die1 = 0, die2 = 0, output = 0, show = 0;
uint frequency[12] = { 0 };

class Dice
{
public:

    void inline rollDie(uint rolls)
    {
        for (i = 1; i <= rolls; i++) {
            die1 = 1 + rand() % 6;
            die2 = 1 + rand() % 6;
            ++frequency[die1 + die2];
        }
    }
}; 

直方图

#include "stdafx.h"
#include "histogram.h"

using namespace std;

class theHisto 
{
public:

    void printHisto()
    {
        for (int i = 1; i < 12; i++)
        {
            //Output some asterisks for the histogram
            for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--)
                cout << "*";
            cout << endl;
        }
    }
};

main.cpp

#include "stdafx.h"
#include "histogram.h"
#include "histogram.cpp"

using namespace std;

uint main()
{
    cout << "How many times would you like to roll the dice?";
    cin >> rolls;
    Dice myDice;
    myDice.rollDie(rolls);
    theHisto mytheHisto;
    mytheHisto.printHisto();
}

抱歉,如果这很麻烦,但是当我将代码复制到“在此处输入代码”框中时,它只是显示为常规文本,因此我不得不将每行缩进4个空格,因此格式可能会略有偏离。

首先,不要#include "histogram.cpp" ,这是所有问题的根本原因。 特别:

  1. 编译器将从main.cpphistogram.cpp ,最有可能是main.cpp 然后,它将通过预处理每个.cpp文件并包括#include指令指定的每个文件,来从每个.cpp文件创建一个单个转换单元
  2. 在预处理main.cpp ,它将遇到#include "histogram.h" 这告诉预处理器将文件histogram.h粘贴到main.cpp的顶部(遇到该行)。 然后它将继续使用histogram.h的内容进行预处理,直到到达从文件粘贴的代码的末尾,然后移至main.cpp的下一行。
  3. 在预处理从histogram.h粘贴的代码时,它将遇到#include "histogram.cpp" 这告诉预处理器将histogram.cpp文件粘贴到那里,就像histogram.h 然后它将继续使用histogram.cpp的内容进行预处理,直到到达从文件粘贴的代码的末尾,然后移至从histogram.h粘贴的下一行。
  4. #pragma once将防止stdafx.hhistogram.hhistogram.cpp多次复制粘贴,并且预处理将正常完成。 [请注意, #pragma once或可能不会防范main.cpp中的#include "histogram.cpp" ,因为它位于histogram.h而不是main.cpp 同样,如果stdafx.h包含任何内容,则可能会遇到相同的问题。 我将假定它为空,并且是您的IDE自动插入的,因此在翻译单元的顶部仅会提及一次。]现在,将使用以下文件开始编译:

     // Contents of "stdafx.h" here. using namespace std; class theHisto { public: void printHisto() { for (int i = 1; i < 12; i++) { //Output some asterisks for the histogram for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--) cout << "*"; cout << endl; } } }; // Contents of <cstdlib> here. // Contents of <stdio.h> here. // Contents of <iostream> here. typedef unsigned int uint; uint rolls = 0, i = 0, die1 = 0, die2 = 0, output = 0, show = 0; uint frequency[12] = { 0 }; class Dice { public: void inline rollDie(uint rolls) { for (i = 1; i <= rolls; i++) { die1 = 1 + rand() % 6; die2 = 1 + rand() % 6; ++frequency[die1 + die2]; } } }; // Contents of "histogram.cpp" may also be here. using namespace std; uint main() { cout << "How many times would you like to roll the dice?"; cin >> rolls; Dice myDice; myDice.rollDie(rolls); theHisto mytheHisto; mytheHisto.printHisto(); } 

请注意,如果可以的话, histogram.cpp的主体现在位于histogram.h的主体之前 ,表示:

  • 在声明之前使用frequency
  • 在声明之前使用rolls
  • 在遇到#include <iostream>之前使用std::cout
  • 在遇到#include <iostream>之前使用std::endl
  • 如果编译器不按照您期望的方式执行#pragma once ,则将重新定义theHisto类。

因此,您会收到“使用的未定义变量”错误。

相反,您希望编译器同时编译histogram.cppmain.cpp ,并在链接阶段将它们组合在一起。 进行此操作时,由于您已经在每个.cpp文件的开头#include "stdafx.h" ,因此无需在histogram.h进行相同的操作。


接下来, theHisto应该被定义histogram.h ,不histogram.cpp

// histogram.h

#pragma once
// #include "stdafx.h"
// #include "histogram.cpp"
#include <cstdlib>
#include <stdio.h>
#include <iostream>

typedef unsigned int uint;

uint rolls = 0, i = 0, die1 = 0, die2 = 0, output = 0, show = 0;
uint frequency[12] = { 0 };

class Dice
{
public:
    void inline rollDie(uint rolls)
    {
        for (i = 1; i <= rolls; i++) {
            die1 = 1 + rand() % 6;
            die2 = 1 + rand() % 6;
            ++frequency[die1 + die2];
        }
    }
};

class theHisto
{
public:
    void printHisto();
};

和...

// histogram.cpp

#include "stdafx.h"
#include "histogram.h"

using namespace std;

void theHisto::printHisto()
{
    for (int i = 1; i < 12; i++)
    {
        //Output some asterisks for the histogram
        for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--)
            cout << "*";
        cout << endl;
    }
}

由于可以在多个编译单元中定义全局变量,因此可以解决错误,但会导致链接错误。 要解决此问题,您可以在histogram.h中将它们声明为extern ,然后在一个.cpp文件中定义它们。

// histogram.h

#pragma once
// #include "stdafx.h"
// #include "histogram.cpp"
#include <cstdlib>
#include <stdio.h>
#include <iostream>



typedef unsigned int uint;

extern uint rolls, i, die1, die2, output, show;
extern uint frequency[12];

class Dice
{
public:
    void inline rollDie(uint rolls)
    {
        for (i = 1; i <= rolls; i++) {
            die1 = 1 + rand() % 6;
            die2 = 1 + rand() % 6;
            ++frequency[die1 + die2];
        }
    }
};

class theHisto
{
public:
    void printHisto();
};

和...

// histogram.cpp

#include "stdafx.h"
#include "histogram.h"

using namespace std;


uint rolls = 0, i = 0, die1 = 0, die2 = 0, output = 0, show = 0;
uint frequency[12] = { 0 };


void theHisto::printHisto()
{
    for (int i = 1; i < 12; i++)
    {
        //Output some asterisks for the histogram
        for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--)
            cout << "*";
        cout << endl;
    }
}

和...

// main.cpp

#include "stdafx.h"
#include "histogram.h"
// #include "histogram.cpp"
using namespace std;

// You could define your variables here, instead of in "histogram.cpp", if you wanted.

uint main()
{
    cout << "How many times would you like to roll the dice?";
    cin >> rolls;
    Dice myDice;
    myDice.rollDie(rolls);
    theHisto mytheHisto;
    mytheHisto.printHisto();
}

这将解决链接错误,并允许您的代码进行编译。 请注意,编译器的命令行应同时指定main.cpphistogram.cpp ,并且可能看起来像这样(假设使用Visual Studio,因为stdafx.h )。

cl /EHsc main.cpp histogram.cpp

另外,通过将theHisto::printHisto()定义为内联,可以完全消除histogram.cpp

// histogram.h

#pragma once
// #include "stdafx.h"
// #include "histogram.cpp"
#include <cstdlib>
#include <stdio.h>
#include <iostream>



typedef unsigned int uint;

extern uint rolls, i, die1, die2, output, show;
extern uint frequency[12];

class Dice
{
public:
    void inline rollDie(uint rolls)
    {
        for (i = 1; i <= rolls; i++) {
            die1 = 1 + rand() % 6;
            die2 = 1 + rand() % 6;
            ++frequency[die1 + die2];
        }
    }
};

using namespace std;

class theHisto
{
public:
    void printHisto()
    {
        for (int i = 1; i < 12; i++)
        {
            //Output some asterisks for the histogram
            for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--)
                cout << "*";
            cout << endl;
        }
    }
};

和...

// main.cpp

#include "stdafx.h"
#include "histogram.h"
// #include "histogram.cpp"
using namespace std;



uint main()
{
    cout << "How many times would you like to roll the dice?";
    cin >> rolls;
    Dice myDice;
    myDice.rollDie(rolls);
    theHisto mytheHisto;
    mytheHisto.printHisto();
}

再次假定使用Visual Studio,将使用以下内容编译该文件:

cl /EHsc main.cpp

前两个都可以解决您的问题。 我建议使用前者,因此您也可以将Dice::rollDie()移至histogram.cpp ,就像我对theHisto::printHisto()所做的那样。 只需记住不要#include任何.cpp文件,除非1)它们包含它们依赖的任何代码之后 ,以及2)您仅#include它们在一个文件中,该文件应具有标题保护。 [请注意,如果您知道自己在做什么,以及如何安全地打破第二条规则,则可以采取许多疯狂的技巧。]通常最好告诉编译器将每个.cpp文件作为一个单独的翻译单元进行处理。 ,而不仅仅是将它们组合成一个单一的大块。


[另见对此答案的第一条评论,其中包含进一步的建议; 它们不必使您的代码正常工作,但会很有用。 如果有的话,最有可能中断的是main()的返回类型; 尽管unsigned int可以隐式转换为int ,但并非每个编译器都同意main()返回unsigned int而不是int 。]

这是我在您的代码中看到的一些问题。 我不知道这是否可以解决您的问题,因为您没有发布错误消息。

  1. 方法main()应该返回int
  2. frequency阵列太小。 否则, die1die2值太大。 取决于您要如何看待它。
  3. 您正在混合使用C ++和C标头。 包含cstdio而不是stdio.h 最好不要使用cstdiocstdlib 您不需要它们。
  4. 只需将unsigned用作数据类型,而不是您自己定义的uint
  5. 您没有初始化随机数生成器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM