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文字の長さを割り当てた後、入力にcinを使用して、pCharが5文字を含む文字配列になるようにします。
だが(重要なポイント)
coutを出力に使用すると、文字が文字化けします。入力した文字も出力できますが、文字化けがたくさん続きます。以下に示すように:
fqwerと入力すると、出力の最初の数文字もfqwerになりますが、文字化けした文字が続きます。

1.2問題の原因:

費用-はい、それはカウトです!
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に転送します。入力後にEnterキーを押すと、coutは5文字を順番に直接読み取り、pCharに格納します。入力長がpCharの長さよりも長い場合でも、pCharには5文字しか格納されません。

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が「\ 0」を格納するためにメモリを割り当てるときにcharメモリを割り当てる必要があります。これにより、coutは、直接出力するときに「\ 0」を読み取ったときに出力の終わりを判断するため、表示されません。文字化け。
プログラムの出力は次のとおりです。
ここに画像の説明を挿入します
個人的には、coutに制御を渡すことは非常に危険な動作であると感じています。この点を説明するための関連する例はまだ考えていませんが、人々がコンピューターを制御しているので、制御は間違いなくしたがって、作成者は、ソリューション2の最後にヌル文字を追加する方がよいと考えています。

ピット2:

2.1問題の説明:

演算子オーバーロード添え字演算子を使用する場合、オブジェクトが2次元配列の場合はどうなりますか?

実際、これは問題ではありませんが、ピットを踏んだときに作者が遭遇した非常に興味深い問題です。私が書いたプログラムは正常に出力できますが、私自身の理解では出力されません。
プログラムコードは次のとおりです。

#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

コードのクラスAに2次元配列のメンバー変数があります。次に、C ++を実装して、添え字演算子をオーバーロードして2次元配列の値を取得します。これは:

class A{
    
    };
type c = A[i][j];

この種の操作は、クラスAの使用を非常に便利にします。したがって、添え字演算子はオーバーロードする必要があります。
ただし、添え字演算子は単項演算子であり、入力パラメーターは1つだけです。じゃあ何をすればいいの?2次元配列は1次元配列と見なすことができますが、1次元配列の要素はポインタです。その後、問題は簡単に処理でき、リロードできます。
次のように:

	int* operator[](int iIndex)
	{
    
    
		return _ia[iIndex];
	}

コード内の_iaはクラスAの2次元配列であるため、オーバーロードされた添え字演算子の場合、最初に整数を渡して2次元配列の行要素を取得し、行要素はint型のポインターです。ポインタを取得したら、リロードしてください!
コードは次のように表示されます。

	int operator[](int* jIndex)
	{
    
    
		return *jIndex;
	}

(手動で面白い<-<-)

添え字演算子を2回オーバーロードし、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はクラスAのインスタンス化されたオブジェクトであるため、testa [i]はクラスAのオーバーロードされた演算子を呼び出し、返される結果はint型のポインターであり、このポインターはtestaのメンバー変数_iaの要素でもあります。次に、(_ ia [i])[j]は、_iaのi番目の行とj番目の列の値を出力します。
クラスAのオーバーロードについて

	int operator[](int* jIndex)
	{
    
    
		return *jIndex;
	}

この添え字演算子は実際には役に立たない、それはまったくたわごとです
ここに画像の説明を挿入します
=======================分割線-ピットに遭遇した後、更新================= ================================================== ================================================== ================================================== ================================================== =============================================== ===

おすすめ

転載: blog.csdn.net/GeomasterYi/article/details/106728267
おすすめ