環境
M1 MacBook
Sonoma 14.6.1
何につまづいたのか
文字列の連結をC++で実装する時につまづきました。クエリを受け取り、それに応じて文字列を生成してスタックするという処理です。
どこでつまづいたのか
...
string ans = "";
string S = flw[i];
for (const auto &v: S)
ans += v + " ";
out.push_back(ans);
...
上が該当のコードです。outにスタックされた文字列は、処理の最後にまとめて出力されます。しかしながら、このプログラムを実行しても、何も出力されませんでした。
原因
原因は、文字型と文字列型の混同でした。C++は、文字列同士を「+」演算子で連結できます。
string a = "abc" + "def";
cout << a << endl;
abcdef
しかしながら、私は次の様なコードを書いてしまいました。
...
ans += v + " ";
...
2024/10/18 修正
この時、vがstring型であれば、問題なく連結されます。しかし、vはchar型でしたので、意図しない動作が発生しました。
しかし、上の実装を見るとわかりますように、for文で文字列型の要素である文字型を取り出していますので、この式は「文字型」と「文字列型」の連結を行おうとしてしまいます。本来であれば、コンパイラがエラーを示してくれるはずですが、for文内部でauto型を使ってしまったせいで、コンパイラも気が付かなかった様です。
(コンパイラは正しく型推論を行なっています)
改善
2024/10/18 修正
to_string関数を用いてstring関数を用いて文字型を文字列型に変換しました。これで、文字が問題なく連結されるようになりました。
ans += string(1, v) + " ";
未だわからないところ・予想など
コメントより、上記のコードは問題なく動作するとの指摘を受けましたので、一度実験を行いました。
string ans = "";
const char &v = 'a';
const char* space = " ";
space += v;
ans += space;
cout << ans << endl;
$ ./a.out
$ ?
文字がうまく連結されませんでした。もしかしたら、コメント投稿者の方と環境が異なったり、私のプログラムがよくないのかもしれません。ただ、まだ気になりましたので、もう少し実験を行いました。
出力結果に「?」と表示されたところが気になりました。文字型に間違えて数字を足しますと、時々文字がずれて、このような結果になります。もしかしたら、文字同士がASCIIの数字で足し算されているのではないかと予想しました。
実験1
print(" " + 'a');
print(" " + 97);
$ ./a.out
[空白]
[空白]
実験2
print("" + 'a');
print("" + 97);
$ ./a.out
???????<
???????<
あくまでも知識不足の私の予想なのですが、もしかしたら文字が整数値に変換されてしまい、上のような挙動が起きたのではないかと思います。整数を文字列に足すことで、ポインタ操作が行われてしまったのかもしれません。いずれにせよ、未だよくわからない領域です。引き続き、勉強してまいります。
参考