rainit2006 / C-Program

C# Program knowledge
0 stars 0 forks source link

字符串处理 #29

Open rainit2006 opened 6 years ago

rainit2006 commented 6 years ago

字符串处理大全 http://blog.csdn.net/cabinriver/article/details/8938726

对char* 的处理

rainit2006 commented 6 years ago

String、string、CStringの違い 「String」 System::String のことであろうと思われます。それは通常の C++ とは異なる言語になります。C++/CLI と言います。 C++/CLI はC# や VB.NET 等と連携する際に使用する言語です。それで、System::String^ 型(トラッキング ハンドルを表す ^ 記号が付きます)は C# の string 型、VB.NET の String 型 と同一物となります。 なお、System::String における文字型は wchar_t (Unicode 文字)です。

「string」 std::string のことであろうと思われます。それは C++ の標準ライブラリ内にある文字列クラスです。普通に C++ でプログラムを作る場合は std::string か std::wstring を使用します。std::basic_string でも良いです。

std::string の文字は char、std::wstring なら wchar_t となります。std::basic_string とすると TCHAR です。

「CString」 MFC の CString クラスの事であろうと思われます。MFC はご存知でしょうか。昔流行りました。C++ の言語が持つ力だけでは不足してたわけなんですよ。え?std::string を使えば良いじゃないかって?いや、それは Visual C++ 2.0 から使えるようになったのです。1.0、1.5 の時は使えなかったのです。ていうか16ビット版の Visual C++ は 1.51 で終わり。ですので std::string など夢のまた夢。ですから1990年代は CString の使用例が多かったんですよね。

その後、若干下火になりましたが GUI アプリケーションの一つの実現方法として今でも使える形になっています。使えるというか、密かに進化してます。マイクロソフト社自身が使ってるのかもしれません。

CString の文字は TCHAR 型になります。テンプレートになっていますので、CStringA とか CStringW とかの形で char、wchar_t の文字にも使えます。

rainit2006 commented 6 years ago
rainit2006 commented 6 years ago

【C++】string型をcharに変換/コピーする方法 http://marycore.jp/prog/cpp/convert-string-to-char/

http://marycore.jp/prog/cpp/convert-char-to-string/ char* → std::string方法

const char *cstr = "abc";
std::string str = std::string(cstr);

または
const char *cstr = "abc";
std::string str(cstr);  // コンストラクタ呼び出し
std::string str{cstr};  // 統一初期化(Uniform initialization)
std::string str = cstr; // 暗黙のコンストラクタ呼び出し & 初期化

std::string str;        // デフォルトコンストラクタ呼び出し
str = cstr;             // 暗黙のコンストラクタ呼び出し & コピー代入

std::string → const char*

std::string str("abc");
const char* cstr = str.c_str(); // "abc"

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー 【C++】CString型をcharに変換/コピーする方法

これで、char型の文字列「test」がCString型の変数にコピーされます。
CStringは「=」の演算子をオーバーロードしていて、実際にはmemcpyされているからです。

- CStringからcharに変換

void xxx() { CString str = "test";

char *p = new char[str.GetLength()+1];
strcpy( p, str );

delete [] p;

}


単純にstrcpyできます。コピー先のバッファサイズには気をつけましょう。
rainit2006 commented 6 years ago

_T("")マクロについて http://vllv.us/Junk/_T/

Visual Studio2003までは標準設定がマルチバイトだったのでWindowsAPIや DirectX用の関数の引数に文字列を受け渡す時は TestFunc("文字列"); みたいな感じでオッケーでした。 しかし、Visual Studio2005からはこれではダメなんです。 標準設定がユニコード設定なので多くの関数において文字列は


TestFunc( L"文字列" );
TestFunc( _T("文字列") );
TestFunc( _TEXT("文字列") );

```のいずれかで受け渡さなないとダメです。

一番上のL"文字列"はユニコード限定の文字列ですよ、という意味を表すマクロなので設定をマルチバイトに変更するとエラーになります。
_Tマクロはユニコード設定とマルチバイト設定の差異を解消するためのマクロで
ユニコード設定ならL"文字列"として展開し、 マルチバイト設定なら従来どおり"文字列"とLは付加せずに展開されます。
_Tと_TEXTは同じマクロなので通常は短い_Tが使われます。
rainit2006 commented 6 years ago

忘れられがちな終端文字の存在

実は先の例のchar Alpha[ 26 ] = "abcdefghijklmnopqrstuvwxyz";は本来は[ 26 ]ではなく なるべくならAlpha[ 27 ]などと一つ余分に領域を確保すべきです。 なぜかというと『 終端文字 ¥0 』の存在の為です。 C言語ではあらゆる文字列にはその終わりを示す記号があります。それが¥0です。 実は文字列は確保した段階で自動的にそれが挿入されており、文字列を代入する場合はコピー先領域にも 終端文字の為の余分な領域が必要になります。 以下簡単なサンプルです。

 char str[ 4 ] = "abc";   //代入する文字列の総バイト数より+1余分に確保(バイト数とは半角英数字を1、日本語などの全角文字を2として足し算した合計)
 char str[ 6 ] = "abcde";  //5バイト + 1 = 6
 char str[ 7 ] = "あいう";  //6バイト + 1 = 7
 char str[ 6 ] = "あabc";  //5バイト + 1 = 6

 WCHAR str[ 4 ] = L"abc";   //3文字 + 1 = 4
 WCHAR str[ 5 ] = L"あabc";  //4文字 + 1 = 5(WCHARはバイト数ではなく文字数で数える)
 WCHAR str[ 6 ] = L"12345";  //5文字 + 1 = 6

(特にVisual Studio 2010からはこうしないと設定によってはエラーになるらしいので一応頭に入れておくと良いでしょう)

rainit2006 commented 6 years ago

image image

両対応がない時は自分で作る

上の表を見て分かる通り、マルチバイトのstd::coutやユニコードのstd::wcoutはしっかりと存在しています。が、残念なことに両対応のstd::tcoutなどは存在しません。そこでマクロを利用し自分で作ってみましょう。ユニコード設定の時は_UNICODEが自動的に定義されるのでそれを利用するのが簡単です。 以下のように定義すると、設定に応じ自動的にどちらを使うかを選んでくれるようになります。

// tcoutを定義
#if defined(UNICODE) || defined(_UNICODE)
  #define tcout std::wcout
#else
  #define tcout std::cout
#endif
rainit2006 commented 6 years ago

// マルチバイトの例

include

int main() { char * Text = "マルチバイト文字列"; printf( "%s", Text ); }

// ユニコードの例

include

include

include

int main() { setlocale( LC_ALL, "Japanese"); //ロケール(地域言語)を日本語でセット WCHAR * Text = L"ユニコード文字列"; wprintf( L"%s", Text ); }

// 両対応の例

include

include

include

include

int main() { setlocale( LC_ALL, "Japanese"); //ロケール(地域言語)を日本語でセット TCHAR * Text = _T("開発環境の設定に応じた文字列"); _tprintf( _T("%s"), Text ); }

『setlocale( LC_ALL, "Japanese"); 』の部分: ユニコードとはUniversal Codeの略で文字通り世界中の国々の言語をサポートした規格です。 ですから最初にこれから使う言語が何の言語であるかを明確にしておく必要があります。 それをしないと上のコードだと実行結果は???????とかになってしまいます。 特にファイル入出力とコンソールへの入出力の際にユニコードを使うのなら『setlocale』が必須です。 とはいえプログラムの初めに一度だけ呼び出せばOKです。

ユニコード文字列からマルチバイト文字列への変換 関数で受け取ったユニコード文字列をマルチバイト文字列に変換したり、あるいはその逆をしたいことがあります。 WideCharToMultiByte という専用の関数があるのですが、使い方が面倒な割りに小回りが利かないので、そういう時はマルチバイトであろうとユニコードであろうと代入後に勝手に変換してくれる ATLのCString型 が便利です。

include するだけで使えます。


// ユニコード文字列からマルチバイト文字列へ変換して結合するプログラム
#include <windows.h>
#include <atlstr.h>

// ユニコード文字列からマルチバイト文字列への変換
void func( WCHAR * wideStr )
{
    CStringA mbStr = "マルチバイト文字列";
    mbStr += wideStr;
    MessageBoxA( NULL, mbStr, NULL, MB_OK );
}

int main()
{
    func( L"ユニコード文字列" );
}

// 設定に応じて呼び出す関数を代えるプログラム

#include <windows.h>
#include <tchar.h>

// メッセージボックスを表示
void func( TCHAR * tempStr )
{
    // ユニコード設定なら_UNICODEが定義されるのでそれを利用して場合分け
    #ifdef _UNICODE
        MessageBoxW( NULL, tempStr, NULL, MB_OK );  //ユニコード関数
    #else
        MessageBoxA( NULL, tempStr, NULL, MB_OK );  //マルチバイト関数
    #endif
}

int main()
{
    func( _T("両対応の文字列") );
}

CString型の危険性(C++ユーザー向きの説明) ATLのCString型はC++で標準化されたSTLのstring型やwstring型に比べて安全性に問題があります。 普通に使う分にはいいのですが、マルチスレッドの際に同時アクセスがあることを想定していない型なので そういう環境ではいきなりPCがクラッシュしてしまう可能性もあります。

rainit2006 commented 6 years ago

结构体保存成char*, 再从char里读成struct

//vics_merge_info是一个struct。

vics_merge_info b = vVicsInfo[0];
char info[sizeof(vics_merge_info)];     
memcpy(info, (char*)&b, sizeof(vics_merge_info));

vics_merge_info c;
memcpy(&c, info, sizeof(vics_merge_info));

另一个例子

        string line = "95"; //head info.
        vics_merge_info b = vVicsInfo[0];
        char info[sizeof(vics_merge_info)];     
        memcpy(info, (char*)&b, sizeof(vics_merge_info));
        line.append(info);
        line.append(info);

        vics_merge_info c, d;
        string subLine = line.substr(2);
        memcpy(&c, info, sizeof(vics_merge_info));
        memcpy(&d, info, sizeof(vics_merge_info));
rainit2006 commented 6 years ago

struct 封装成 json 形式 http://www.cppblog.com/wanghaiguang/archive/2013/12/26/205020.html http://blog.csdn.net/u011261430/article/details/77713299

要点: Jsoncpp的lib工程编译选项要和VS工程中的编译选项保持一致。如lib文件工程编译选项为MT(或MTd),VS工程中也要选择MT(或MTd),否则会出现编译错误问题,debug和release下生成的lib文件名字不同,注意不要看错了,当成一个文件来使用

引用

#include "json/json.h"
#pragma comment(lib,"json/json_vc71_libmtd.lib")  //debug用

。。。。。。。。

for (int i = 0; i < vVicsInfo.size(); i++)
        {
                Json::Value new_item;
                new_item["provideTime"] = vVicsInfo[i].provideTime;
                new_item["mesh"] = vVicsInfo[i].mesh;
                new_item["linkLayer"] = vVicsInfo[i].linkLayer;
                new_item["linkNo"] = vVicsInfo[i].linkNo;
                new_item["linkKubun"] = vVicsInfo[i].linkKubun;
                new_item["providedType"] = vVicsInfo[i].providedType;
                new_item["jumLevel"] = vVicsInfo[i].jumLevel;
                new_item["routeTime"] = vVicsInfo[i].routeTime;
                arrayObj.append(new_item);  // 插入数组成员
        }
        Json::FastWriter fastWriter;
        string obj = fastWriter.write(arrayObj);
rainit2006 commented 6 years ago
rainit2006 commented 6 years ago

int main() { const std::string str("123"); auto num = std::atoi(str.c_str()); std::cout << typeid(num).name() << " : " << num << std::endl; }



还有其他的很多种方法,详细请看:
http://nekko1119.hatenablog.com/entry/2013/08/17/144722
rainit2006 commented 6 years ago

有效无效的判断 if (tb_fesimo.Text.Trim() == string.Empty) { MessageBox.Show("Fesimo Path is invalid"); return; }

rainit2006 commented 6 years ago

csv文件读取每一行里的内容

自定义实现split处理。


std::vector<std::string> split(const std::string &str, char sep)
{
    std::vector<std::string> v;        // 分割結果を格納するベクター
    auto first = str.begin();              // テキストの最初を指すイテレータ
    while (first != str.end()) {         // テキストが残っている間ループ
        auto last = first;                      // 分割文字列末尾へのイテレータ
        while (last != str.end() && *last != sep)       // 末尾 or セパレータ文字まで進める
            ++last;
        v.push_back(std::string(first, last));       // 分割文字を出力
        if (last != str.end())
            ++last;
        first = last;          // 次の処理のためにイテレータを設定
    }
    return v;
}

在main函数里

               string line;
        getline(fesimoFile, line);
        vector<string> strvec = split(line, ',');