C++ Builder 10.2 Tokyo > 文字列操作 > L"1,1,2,2,3,3,1,1,2,2" を L"2,2,3,3,1,1,3,3,2,2"へ置換 (1->2, 2->3, 3->1の置換を行う)

```txt:動作環境
RAD Studio 10.2 Tokyo Update 3
```

### 処理概要

- L"1,1,2,2,3,3,1,1" を L"2,2,3,3,2,2,"へ置換
    - 変換テーブル（例: 下記)に基づき置換

| 変換元 | 変換先 |
|:-:|:-:|
| 1  | 2  |
| 2  | 3  |
| 3  | 1  |


### 実装

```Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TButton *Button1;
	void __fastcall Button1Click(TObject *Sender);
private:	// ユーザー宣言
    String __fastcall obtainReplacedString(String srcCsv, String fromCsv, String toCsv);
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <memory>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	String srcstr = L"1,1,2,2,3,3,1,1,2,2";  // 変換対象csv
	String fromTBL = L"1,2,3";  // 変換元table
	String toTBL   = L"3,2,1";  // 変換先table

	String res = obtainReplacedString(srcstr, fromTBL, toTBL);
}

String __fastcall TForm1::obtainReplacedString(String srcCsv, String fromCsv, String toCsv)
{
	//前提条件:
	// fromStrとtoStrは同じインデックスに変換元と変換先の文字列が格納されている

	// 1. 前処理

	std::unique_ptr<TStringList> srcSL(new TStringList);
	std::unique_ptr<TStringList> fromSL(new TStringList);
	std::unique_ptr<TStringList> toSL(new TStringList);
	srcSL->StrictDelimiter = true;
	srcSL->Delimiter = ',';
	srcSL->DelimitedText = srcCsv;
	fromSL->StrictDelimiter = true;
	fromSL->Delimiter = ',';
	fromSL->DelimitedText = fromCsv;
	toSL->StrictDelimiter = true;
	toSL->Delimiter = ',';
	toSL->DelimitedText = toCsv;

	if (fromSL->Count != toSL->Count) {
		return L"";   // error (変換テーブルの不整合)
	}

	// 2. 置換処理
	String res = L"";
	for(int si=0; si < srcSL->Count; si++) { // si: srcSL index
		String tostr = L"";  // 置換先の文字列
		if (res.Length() > 0) {
			res += L",";
		}
		for(int fi=0; fi < fromSL->Count; fi++) {  // fi: fromTBL index
			if (srcSL->Strings[si] == fromSL->Strings[fi]) {
				tostr = toSL->Strings[fi];  // 前提: fromSLとtoSLは同じインデックスが対応
				break;
			}
		}
		if (tostr.Length() > 0) {
			res += tostr;
		} else {
			res += srcSL->Strings[si];
		}
	}
	return res;
}
//---------------------------------------------------------------------------
```

### 結果

`String res = obtainReplacedString(srcstr, fromTBL, toTBL);`の後でブレークした場合

- srcCsv
    - { u"1,1,2,2,3,3,1,1,2,2" }
- res
    - { u"3,3,2,2,1,1,3,3,2,2" }


意図したとおりに置換されている。

### 関連

- [System.Classes.TStrings.StrictDelimiter](http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TStrings.StrictDelimiter)

> If StrictDelimiter is False, spaces and non-printable character are also used as delimiters. 

以下の処理で使用予定。

- [C++ Builder 10.2 Tokyo > JSON > 複数のValueを置換する | 問題点 > 意図しない置換 (連鎖的な失敗)](https://qiita.com/7of9/items/ef41f94502ab5cadbf5c)