类 在 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:
- 定义一个可以记住P1..9的class
- 为那个 class 定义一个构造函数,在那里你给它所有的数据
- 为它定义方法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
。
我知道肯定遗漏了一些明显的东西,但我仍然很难理解 类。我有一个指针,我确定那是错误的,但我不知道如何。此外,当我尝试打印其中一个变量时,它只显示第一个字符而不是两个字符,我不知道如何解决这个问题。
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:
- 定义一个可以记住P1..9的class
- 为那个 class 定义一个构造函数,在那里你给它所有的数据
- 为它定义方法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
。