类 在 C++ 中和打印字符

Classes in C++ and Printing Char

我知道肯定遗漏了一些明显的东西,但我仍然很难理解 类。我有一个指针,我确定那是错误的,但我不知道如何。此外,当我尝试打印其中一个变量时,它只显示第一个字符而不是两个字符,我不知道如何解决这个问题。

class Pieces
{
    public:
        char P1;
        char P2;
        char P3;
        char P4;
        char P5;
        char P6;
        char P7;
        char P8;
        char P9;
        void Board(char P1, char P2, char P3, char P4, char P5, char P6, char P7, char P8, char P9);
        void Board();
        
};

void Pieces::Board()
{
    cout << "    A   B   C \n";
    cout << " 1  B1  B2  B3\n";
    cout << " 2  .   .   . \n";
    cout << " 3  W1  W2  W3\n";
}

void Pieces::Board(char P1, char P2, char P3, char P4, char P5, char P6, char P7, char P8, char P9)
{
    cout << "    A   B   C \n";
    //cout << " 1  ", P1, "  ", P2, "  ", P3, "\n";
    cout << P1;
    cout << P1;
    cout << "\n";
    //cout << " 2  ", P4, "  ", P5, "  ", P6, "\n";
    //cout << " 3  ", P7, "  ", P8, "  ", P9, "\n";
}

int main()
{
    Pieces IDK;
    IDK.P1 = *"B1";
    IDK.P2 = *"B2";
    IDK.P3 = *"B3";
    IDK.P4 = *". ";
    IDK.P5 = *". ";
    IDK.P6 = *". ";
    IDK.P7 = *"W1";
    IDK.P8 = *"W2";
    IDK.P9 = *"W3";

    cout << IDK.P1;

    IDK.Board();
    IDK.Board(IDK.P1, IDK.P2, IDK.P3, IDK.P4, IDK.P5, IDK.P6, IDK.P7, IDK.P8, IDK.P9);
}

char就是简单的放一个字符。如果需要多个字符,可以使用字符数组或 std::string。当您使用双引号 "AB" 时,它表示一个 const char* 或常量字符数组。您只能在 char 类型变量中保留一个字符或 1 个字节的数据。这就是为什么您只看到第一个字符的原因。你用单引号描述一个字符 'A'.

在看板功能中

cout << P1
cout << P2
cout << P3

去做

我不会谈论打字错误,因为已经有其他答案解决了它,我将专注于对我来说最大的问题:你没有正确使用 classes。

class 的要点是拥有“可以自己做事的东西”,所以你不应该不断地给他们所有他们需要的数据,你想一次性提供数据永远不必再考虑它。对于您的应用程序,您可以像这样构建 class:

  1. 定义一个可以记住P1..9的class
  2. 为那个 class 定义一个构造函数,在那里你给它所有的数据
  3. 为它定义方法class这样你就可以打印其中已有的数据

它可能看起来像这样:

#include <string>

class Board
{
    public:
        Board();
        Board(char P1, char P2, char P3, char P4, char P5, char P6, char P7, char P8, char P9);
        void printBoard();

    private:
        char P1;
        char P2;
        char P3;
        char P4;
        char P5;
        char P6;
        char P7;
        char P8;
        char P9;
};

Board::Board()
{
    P1 = P2 = P3 = P4 = P5 = P6 = P7 = P8 = P9 = 0;
}

Board::Board(char piece1, char piece2, char piece3, char piece4, char piece5, char piece6, char piece7, char piece8, char piece9)
{
    P1 = piece1;
    P2 = piece2;
    P3 = piece3;
    P4 = piece4;
    P5 = piece5;
    P6 = piece6;
    P7 = piece7;
    P8 = piece8;
    P9 = piece9;
}

void Board::printBoard()
{
    std::string val;

    cout << "    A   B   C \n";

    val = " 1  ";
    if(P1 == 0)
        val += "B1";
    else
        val += std::to_string(P1);

    if(P2 == 0)
        val += "B2";
    else
        val += std::to_string(P2);

    if(P3 == 0)
        val += "B3";
    else
        val += std::to_string(P3);

    val += '\n';
    cout << val;


    val = " 2  ";
    if(P4 == 0)
        val += ". ";
    else
        val += std::to_string(P4);

    if(P5 == 0)
        val += ". ";
    else
        val += std::to_string(P5);

    if(P6 == 0)
        val += ". ";
    else
        val += std::to_string(P6);

    val += '\n';
    cout << val;


    val = " 3  ";
    if(P7 == 0)
        val += "W1";
    else
        val += std::to_string(P7);

    if(P8 == 0)
        val += "W2";
    else
        val += std::to_string(P8);

    if(P9 == 0)
        val += "W3";
    else
        val += std::to_string(P9);

    val += '\n';
    cout << val;
}

然后你会像这样使用它:

int main ()
{
    Board a;
    Board b('a','b','c','d','e','f','g','h','i');

    a.printBoard();
    b.printBoard();

    return 0;
}

编辑:尽管我使用了您的方法,但请注意,char 数组或 std::string 对象可以使代码更短且更易于管理。

我试着让这很简单:

IDK.P1 = *"B1";

在这一行中,您将几个字符分配给一个字符。 P1 属于 char 类型,它只包含一个字符。 char 是一种包含单个字节的类型,意味着是一个 ASCII 编码字符。 B1是两个字符。

在 C 风格的编程中,您将使用已弃用的指针数组 (char*) 来保存多个字符。它将是一个以终止符号 ([=23=]).
结尾的数组(内存中连续的几个值) 但请注意,我编写 C 风格是有原因的 - 在 C++ 中,您不会使用它。

现在,至于语法 *"B1",它的作用是:"B1" 以指向字符数组的指针开始。星取消引用该指针。由于指向数组的指针指向它的第一个元素,因此取消引用恰好为您提供了该元素,在您的情况下它包含值 B。
像这样的语法非常不寻常,我不知道你是怎么使用它的。

无论如何,将两个字符存储在一个 char 中是不可能的。
您可能只想通过

std::string P1;

在你的 class 中,并像

一样分配它
IDK.P1 = "B1";

我注意到的另一件事是你的方法

void Pieces::Board(char P1, char P2, char P3, char P4, char P5, char P6, char P7, char P8, char P9)
{
    cout << "    A   B   C \n";
    //cout << " 1  ", P1, "  ", P2, "  ", P3, "\n";
    cout << P1;
    cout << P1;
    cout << "\n";
    //cout << " 2  ", P4, "  ", P5, "  ", P6, "\n";
    //cout << " 3  ", P7, "  ", P8, "  ", P9, "\n";
}

不分配任何值。它接受的参数在调用后被遗忘。它不会改变你的class的成员变量。我怀疑你好像觉得same name = overtaken,如果是这样,那不是。


至于这个:

    char P1;
    char P2;
    char P3;
    char P4;
    char P5;
    char P6;
    char P7;
    char P8;
    char P9;

如果你写了一个程序,你发现你做了一些非常重复的事情,就像这样,那么通常你做的方式很麻烦。
在这种情况下,您可以简单地使用一个数组:

std::array<char, 9> P;

然后像这样称呼它

Pieces pieces;
pieces.P.at(0) = 'a';

IDK.Board(IDK.P1, IDK.P2, IDK.P3, IDK.P4, IDK.P5, IDK.P6, IDK.P7, IDK.P8, IDK.P9);

这一行是关于您的代码的另一件很奇怪的事情。你用它自己的成员变量调用对象。它已经 知道 它是自己的成员。另外,Board 对于打印数据的东西来说是一个不好的名字。在动作完成后命名。试试这个:

无效Pieces::print_board() { cout << " A B C \n"; cout << " 1 " << P1 << " " << P2 << " " << P3 << "\n"; cout << " 2 " << P4 << " " << P5 << " " << P6 << "\n"; cout << " 3 " << P7 << " " << P8 << " " << P9 << "\n"; }

(我这里也把逗号换成了流操作符。)


这是您的代码的返工:

class Board // I renamed it to Board, because that is what it represents
{
public:

    Board() {} 
    // constructor that already takes in the state of the board,
    // using a member initializer list,
    // see https://en.cppreference.com/w/cpp/language/constructor
    Board(const std::array<std::string, 9>& pieces) : pieces(pieces) {} 
    void print() const; // if something prints, let's name it like that

    std::array<std::string, 9> pieces;  
};

void Board::print() const
{
    // I use for-loops here because while you could do your block right now,
    // it would become really cumbersome in a bigger grid
    
    cout << "    A   B   C \n";
    for(size_t i=0; i<3; i++)
    {
        cout << " " << (i+1) << "  ";
        for(size_t j=0; j<3; j++)
        {
            cout << pieces.at(i*3+j) << "  ";
        }
        cout << endl;
    }
}

int main()
{
    Board board({"B1", "B2", "B3", ". ", ". ", ". ", "W1", "W2", "W3"});
    board.print();

    /* alternatively:
    Board board;
    board.pieces.at(0) = "B1";
    ...
    board.print();
    */
}

(给它一个 运行: http://www.cpp.sh/4vv3s)

请注意,我们可能想要添加检查是否所有“片段”的长度都是二,否则打印会错位。或者更好的是,为片段使用适当的类型,例如 enum class,以及将其值转换为字符串的函数。

由于这些片段形成一个网格,我们可能希望使用二维数组 std::array<std::array<std::string, 3>, 3> pieces;,并使用 board.pieces.at(0).at(0) = "B1"; 等访问器。但我暂时忽略了它。

如果您需要动态大小,请使用 std::vector 而不是 std::array