C++学习过程中的坑——持续更新
作者:互联网
这是我在学习C++的过程中遇到的坑
坑1:
1.1 问题描述:
在用new运算符给字符数组分配内存的时候,使用cout输出时会出现乱码,代码如下:
#include <iostream>
using namespace std;
int main()
{
char* pChar;
pChar = new char[5];
int i = 0;
while (i < 5)
{
cin >> pChar[i];
i++;
}
cout << pChar << endl;
return 0;
}
pChar是一个字符指针,使用new运算符分配5个char长度之后,使用cin进行输入,这样pChar就是一个包含5个char的字符数组。
但是(重点来了)
在使用cout进行输出的时候,会出现乱码,虽然也能输出我们输入的字符,但是后面会跟一堆乱码。如下图:
1.2问题原因:
cout——没错,就是cout!
C++中,cout在对字符数组进行输出的时候,判断输出结束的标识是空字符,即’\0’。但是我们在输入的时候,pChar数组结尾并没有空字符,所以cout无法判断什么时候输出结束。也就是说,在输出完了pChar之后,由于找不到结尾的空字符,cout还是会接着输出pChar+4后面紧跟着的内存中的数据,那一块内存中谁都不知道有什么,可能什么都没有。所以会出现乱码。
如下图中的输出结果:
1.3解决方法
1.3.1 去掉循环输入
可以将代码改成这样:
#include <iostream>
using namespace std;
int main()
{
char* pChar;
pChar = new char[5];
cout << "请输入5个字符:";
cin >> pChar;
for (int i = 0; i < 5; i++)
{
cout << "pChar[" << i << "]" << "的值为:" << pChar[i] << "------";
cout << "pChar[" << i << "]" << "的地址为:" << &pChar + i << endl;
}
cout << "pChar的最后一个元素的后面一个内存的地址为:" << &pChar + 5 << ", 其值为:" << pChar + 5 << endl;
cout <<"直接输出pChar的结果为:"<< pChar << endl;
return 0;
}
这样的输出结果为:
原因分析:
不使用循环输入,直接将判断权交给cout。当我们在输入之后按下回车,cout会直接顺序读取5个字符存入到pChar中,即使输入长度大于pChar的长度,也还是只取5个存入到pChar中。
1.3.2 循环输入时加入空字符
代码如下:
#include <iostream>
using namespace std;
int main()
{
char* pChar;
pChar = new char[6];
cout << "请输入5个字符:";
for (int i = 0; i < 5; i++)
cin >> pChar[i];
pChar[5] = '\0';
for (int i = 0; i < 5; i++)
{
cout << "pChar[" << i << "]" << "的值为:" << pChar[i] << "------";
cout << "pChar[" << i << "]" << "的地址为:" << &pChar + i << endl;
}
cout << "pChar的最后一个元素的后面一个内存的地址为:" << &pChar + 5 << ", 其值为:" << pChar + 5 << endl;
cout <<"直接输出pChar的结果为:"<< pChar << endl;
return 0;
}
加入空字符的时候,需要在new分配内存的时候多分配一个char内存,用来存储‘\0’,这样cout在直接输出的时候读到‘\0’就会判断输出结束,因而不会出现乱码。
程序输出结果如下:
个人觉得,将控制权交给cout是一件非常不安全的行为,笔者暂时还未想出相关例证来说明这一点,但是既然是人控制计算机,控制权肯定应该在人的手中,因此笔者认为,解决方法2在末尾加入空字符更好。
坑2:
2.1 问题描述:
在使用运算符重载下标运算符时,如果对象是一个二维数组怎么办?
其实这不算一个问题,只是笔者在踩坑的时候遇到的一个非常有趣的问题,自己写的程序能正常输出,但是并不是按照自己的理解来输出。
程序代码如下:
#include <iostream>
using namespace std;
class A
{
public:
int _ia[3][4];
void putData()
{
for (int i = 0; i < 3; i++)
{
for(int j=0;j<4;j++)
cin >> _ia[i][j];
}
}
int* operator[](int iIndex)
{
return _ia[iIndex];
}
int operator[](int* jIndex)
{
return *jIndex;
}
};
int main()
{
A testa;
testa.putData();
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
cout << testa[i][j]<<"\t";
cout << endl;
}
return 0;
}
// 1 2 3 4 5 6 7 8 9 10 11 12
代码中 class A里有一个二维数组的成员变量,现在想通过重载下标运算符来实现C++对二维数组那样取值。即:
class A{};
type c = A[i][j];
这种操作会使得对于 class A的使用变得十分方便。因此必须重载下标运算符。
但是下标运算符是一个一元运算符,输入参数只有一个。那么怎么办呢?都知道二维数组可以看成是一维数组,只不过该一维数组的元素是一个指针。那么问题好办了,重载!
如下:
int* operator[](int iIndex)
{
return _ia[iIndex];
}
代码中的_ia是 class A 中的二维数组,因此对于重载的下标运算符,首先传入一个整型取得该二维数组的行元素,该行元素是一个int类型的指针。取得该指针之后,那么接着重载啊!
代码如下:
int operator[](int* jIndex)
{
return *jIndex;
}
(手动滑稽 <-<-)
第二次重载下标运算符,传入一个int类型的指针,输出该类型的值。写到这里我自己都笑了。。
好嘛,看起来正常,实际上一点都不正常,某些大佬可能看一眼就觉得看起来都不正常。
但是程序能够正常输出,输出部分代码如下:
A testa;
testa.putData();
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
cout << testa[i][j]<<"\t";
cout << endl;
}
既然程序看起来都不正常,那为什么还能正常输出呢?
原因如下:
testa是class A的实例化对象,因此testa [ i ]是调用A类里的重载运算符,返回结果是一个int类型的指针,而且这个指针还是testa的成员变量 _ia的元素。再然后,(_ia [ i ])[ j ]输出的就是_ia的第 i 行第 j 列的值。
至于class A中重载的
int operator[](int* jIndex)
{
return *jIndex;
}
这个下标运算符,实际上没啥用,根本就是SHIT
=======================分割线——以后遇到坑接着更新====================
标签:pChar,char,cout,输出,int,运算符,更新,学习,C++ 来源: https://blog.csdn.net/GeomasterYi/article/details/106728267