3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C++の文字列処理が酷いので、なんとかした案件

Last updated at Posted at 2020-05-10

c++の文字列処理酷くないですか?

最初の過ち

char配列に格納された文字列をstringに変換する処理を書いていました。
char配列に入れる文字列は、shortの配列に格納されたbit列を、reinterpret_castで持ってきたものです。

hoge.cpp
int num = 32;

//文字を入れるための、可変長のデータ領域を確保
char *char_array1 = new char[num]{0};
char *char_array2 = new char[num]{0};

//配列に文字を格納する
for(auto i = 0; i < num; i++) {
    char_array1[i] = '0' + i; //
}
for(auto i = 0; i < num; i++) {
    char_array2[i] = '0' + i; //
}

// char_array1をstring型に変換したい
std::string output_string = char_array1;

//char_array1だけを出力したい
std::cout << output_string << "\n";
//出力: 0123456789:;<=>?@ABCDEFGHIJKLMNO0123456789:;<=>?@ABCDEFGHIJKLMNO

こちらのソースコードを実行すると、char_array1の内容だけを出力したいにもかかわらず、char_array2の内容も出力されてしまう。

原因は、char_arrayにNULL終端が無いために、stringに変換する時に次の領域まで見てしまっています。

多くのC言語のchar配列文字の関数は、NULL終端をデータ列の最後と認識します。

std::string output_string = char_array1;

2つの配列の領域が連続しているため、char_array2の内容まで出力処理が走ってしまいます。

二つ目の過ち

それならばと、下記のコードのように、stringに変換する時に配列に対して十分に大きい要素数を指定するようにしました。

std::string output_string(char_array1,100);
# 出力結果
0123456789:;<=>?@ABCDEFGHIJKLMNO0123456789:;<=>?@ABCDEFGHIJKLMNO�����������������U����������\220U�

何か変なものが出力についてきます。
これは、要素数を指定した事で、char配列にNULLが入っていたとしても、それがそのままNULLを含んだ文字が出力されていました。

考察

そもそも、char[]にはサイズを持っていないので、NULL終端をつけるにも、終端を見つけるのができない?
Cでは、配列を扱うときはサイズも一緒に扱うのは常識だが、文字列扱うたびに、配列サイズも同時に受け渡すのは少し面倒。
あと、newした配列をdeleteしないといけないのも、よくよく考えると面倒。

私が考えた最強の文字配列

std::vector<char> vsting;

vectorで管理すればいいじゃーん
配列長を管理しなくてもいいし、
new使わないから解放しなくてもいいしー

Stringでも同じことができるけど、メモリー領域が連続している保証は無いし、NULL文字の扱いがちょっと危険だなと思ったので

vectorで書き直すと、下記のようになります。

hoge.cpp
int num = 32;

//文字を入れるための、可変長のデータ領域を確保
std::vector<char> char_array1(num);
std::vector<char> char_array2(num);

//配列に文字を格納する
for(auto i = 0; i < num; i++) {
    char_array1[i] = '0' + i; //
}
for(auto i = 0; i < num; i++) {
    char_array2[i] = '0' + i; //
}

// char_array1をstring型に変換したい
//要素数の入力不要!!
std::string output_string(char_array1.begin(),char_array1.end());

//char_array1だけを出力できる。
std::cout << output_string << "\n";
//出力: 0123456789:;<=>?@ABCDEFGHIJKLMNO

参考文献

3
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?