こんにちは、ミミです。
いつもお世話になっています。
CString文字列 山田 太郎を、 (全角スペース)を区切りで2行に分割したいのですが、
下記のコードにより、一通りの事はできましたが、応用が利きません。
sName.Replace( , \r\n);
MessageBox(sName, 分割後の氏名 ,MB_OK);
ですと、万一、区切り記号である が複数あった場合、
の数分、改行マークに変換されてしまうことになってしまいます。
どんなに があったとしても、最初の のみ改行に変換できるようにするには、
どうすればよいのでしょうか。
(運用でカバーしてしまえばそれまでなのですが..。)
> ですと、万一、区切り記号である が複数あった場合、
> の数分、改行マークに変換されてしまうことになってしまいます。
あらかじめ__(全角スペースのつもり)を_に変換しておけば良いのでは?
長さが変わらなくなるまで。
CString::Find を使って、最初に現れる全角空白の位置を求められます。
既に色々あがってますが、
この手の処理って方法は山ほどありますよ。
επιστημηさんの方法が一番正論だと私も思います。
あとは、文字列の中身を一文字づずつチェックして最初の
全角スペースを置き換えるコードを自分で書いたっていいと
思います。コード的にはたいした事は無いし、
何より、ロジックの勉強になると思いますから。
ロジックの勉強は必要ないということでしたら
επιστημηさんの方法でやってみてはどうでしょう。
あと、一足飛びにその状態に出来る関数を求めるのではなくて
関数を組み合わせて同じ処理を実現する発想の転換が必要なの
ではないかなと質問を読んでいて感じました。
CStringのメンバー関数の説明を見ながら、組み合わせで何とか
ならないか、考える事も必要だと思いますよ。
遅くなってしまい、申し訳ありません。
たいちうさん、επιστημηさん、PATIOさん、
ご返信ありがとうございます。
例えば sName = 山田_太郎 では (※以後、_は全角SPを示します)
int nKaigyoLen = sName.Find(_T( ),0);
は 4 となりました。
よって、
sName1 = sName.Left(nKaigyoLen);
sName2 = sName.Right(sName.GetLength() - sName1.GetLength() - 2);
より、分割はできました。 ^^^^ 区切り記号分の
減算
ですが、このままでは、山田___太郎などの時に対処できません。
そこで、色々と模索して、
CString sEditName = "; // 姓と名を分割してここに退避
bool bDiv = false; // 既に分割済みか(初期値はfalse)
int nMojiLen = sName.GetLength();
for(int k=0; k<=nMojiLen; k+=2){ // sNameに山田_太郎が入ってます
if(sName.Mid(k,2) == ){ // 1文字(マルチバイト)抽出
if(!bDiv){ // 初回に限り、
sEditName += \n; // 改行付加
bDiv=true;
}
continue; // ループ継続
}
sEditName += sName.Mid(k,2);
}
を作ってみました。
見事に意図する処理が実現できました。
処理が処理なだけに、Replaceの様なラクができるのかと思っていましたが、実際はそうではな
い事に、
そして、組み合わせで処理を考えていくことが大切なんだなという事を今回学習できました。
皆様、ありがとうございました。
今後もよろしくお願いいたします。
> ですが、このままでは、山田___太郎などの時に対処できません。
…なぜ? 最初に現れた全角空白を境に左と右に分けるんだから、これでよくはない?
# …… 僕、なにか勘違いしてるかしら?
#include <afxwin.h> // CString
#include <iostream> // cout, endl
int main() {
const CString input = 山田 太郎;
const CString delimitor = ;
const int pos = input.Find(delimitor);
if ( pos >= 0 ) {
const CString result = input.Left(pos) + \n
+ input.Right(input.GetLength()-pos-delimitor.GetLength());
std::cout << '[' << static_cast<const char*>(result) << ']' << std::endl;
}
return 0;
}
CString str = 山田 太郎;
int nPos = str.Find( );
if(nPos>=0){
str.Delete(nPos,2);
str.Insert(nPos,'\n');
}
# テストしてません
# \r\nがいつの間にか\nになってますがなぜ?
επιστημηさんへ
最初の私の発言した内容が不十分で、結果、混乱を招かしてしまい、大変申しわけなく思いま
す。
例えば
山田_太郎 や 山田___太郎
は、
山田
太郎
と表示させたいのです。
επιστημηさんの1回目の書込みで教えてくれました Find()を使い、
sName1 = sName.Left(nKaigyoLen);
sName2 = sName.Right(sName.GetLength() - sName1.GetLength() - 2);
と考え、実行してみましたが、
山田___太郎では、最初に現れた文字でインデックス値が返るとの事より、
山田
__太郎
となりました。
「初回の_で改行する」という意味では、2回目に教えていただいたコードズバリなのです
が、複数の_は、初回だけ改行で後は無視
>どんなに があったとしても、最初の のみ改行に変換できるようにするには、
という事を考え、
> ですが、このままでは、山田___太郎などの時に対処できません。
と判断してしまい、別手段を用いました。
以後は文書表現に気をつけます。
>が、複数の_は、初回だけ改行で後は無視
じゃ、初回だけ変更して。
sName1 = sName.Left(nKaigyoLen);
sName2 = sName.Right(sName.GetLength() - sName1.GetLength() - 2);
sName2.Replace( ,"); ←これ追加
おっちゃんさんへ
>>が、複数の_は、初回だけ改行で後は無視
>じゃ、初回だけ変更して。
正直、盲点でした。
そうですよね、初回だけ変換、そして、2個目以降の を
無視するという意味では、
2行目の文字列(先頭に が入っていても)に対して、
Replace( ,")で一括置換・・、すばらしいです。
全然予想もつきませんでした。
諸先輩方には遠く及ばない自分を再認識しています。
本当にみなさん、ありがとうございました。
(\r\nも\nも表示の上では同じだと思ってました...。)