LoginSignup
3
5

More than 5 years have passed since last update.

[C++] 文字列操作

Last updated at Posted at 2017-03-12

C# の文字列操作の気分で C++ にやってくると、C++ の文字列操作は メモリ操作(例えば主記憶装置上の操作)なことに気づく。

このサンプルコードに 表現の著作性はないが 気になるなら MIT License で。https://opensource.org/licenses/MIT

前準備

const char* a と size_t b がやってきた

#include <string> // std::string
// ↑ファイルの冒頭あたりに置く

std::string myString(a, b);

(Visual Studio 2015)
これで a, b で渡された変数は、std::string 型の文字列 myString 変数として使える。

文字列の配列(1)

#include <string> // std::string
#include <iostream> // std::cout
// ↑ファイルの冒頭あたりに置く

static std::string a[] = {"か","きく","けこ"};

// でいける。

std::string c = a[0] + a[1] + a[2];
std::cout << c << std::endl;

// 出力:
// かきくけこ

(Visual Studio 2015)

文字列の配列(2)

#include <string> // std::string
#include <iostream> // std::cout
// ↑ファイルの冒頭あたりに置く

std::string a[10] = {};

if ("" == a[0]) { std::cout << "空0" << std::endl; }
if ("" == a[1]) { std::cout << "空1" << std::endl; }
if ("" == a[2]) { std::cout << "空2" << std::endl; }
if ("" == a[3]) { std::cout << "空3" << std::endl; }
if ("" == a[4]) { std::cout << "空4" << std::endl; }
if ("" == a[5]) { std::cout << "空5" << std::endl; }
if ("" == a[6]) { std::cout << "空6" << std::endl; }
if ("" == a[7]) { std::cout << "空7" << std::endl; }
if ("" == a[8]) { std::cout << "空8" << std::endl; }
if ("" == a[9]) { std::cout << "空9" << std::endl; }

// 結果:
// 空0
// 空1
// 空2
// 空3
// 空4
// 空5
// 空6
// 空7
// 空8
// 空9

(Visual Studio 2015)
配列の要素数を指定しておけば、空文字列で埋めてくれる実装のようだ。

文字列連結(1)

#include <string> // std::string
#include <iostream> // std::cout
// ↑ファイルの冒頭あたりに置く

std::string a = "あいう";
std::string b = "えお";

// なら単に

std::string c = a + b;

// と書けばいける。

std::cout << c << std::endl;

// 出力:
// あいうえお

(Visual Studio 2015)

文字列連結(2)

#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く

static std::string a = "変";

static std::ostringstream s;
s << "あ" << 1 << " " << (3+7) << " " << false << a << std::endl;

// と書けば。

std::cout << s.str() << std::endl;

// 出力:
// あ1 10 0変

// false が 0 になっているのは面食らう。

(Visual Studio 2015)

文字列分割 半角スペース区切り

#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く

std::string a, b, c;
std::istringstream("さし す せそ") >> a >> b >> c;

// と書けば

std::cout << "a=[" << a << "]" << std::endl;
std::cout << "b=[" << b << "]" << std::endl;
std::cout << "c=[" << c << "]" << std::endl;

// 出力:
// a=[さし]
// b=[す]
// c=[せそ]

(Visual Studio 2015)
この書き方だと、全角スペースでは区切ってくれない。
もう少し調べる。

#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く

std::string a, b;
std::istringstream s("たち つ てと");
s >> a >> b;

// と書けば

std::cout << "a=[" << a << "]" << std::endl;
std::cout << "b=[" << b << "]" << std::endl;
std::cout << "s=[" << s.str() << "]" << std::endl;

// 出力:
// a=[たち]
// b=[つ]
// s=[たち つ てと]

(Visual Studio 2015)
ストリームで流しても、元の文字列は残っているようだ。
さらに 調べる。

#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く

std::string a, b, c, d, e, f, g;
std::istringstream s("な にぬ ねの はひ ふ へほ");
s >> a;
s >> b;
s >> c;
s >> d;
s >> e;
s >> f;
s >> g;

// こう書いて

std::cout << "a=[" << a << "]" << std::endl;
std::cout << "b=[" << b << "]" << std::endl;
std::cout << "c=[" << c << "]" << std::endl;
std::cout << "d=[" << d << "]" << std::endl;
std::cout << "e=[" << e << "]" << std::endl;
std::cout << "f=[" << f << "]" << std::endl;
std::cout << "g=[" << g << "]" << std::endl;
std::cout << "s=[" << s.str() << "]" << std::endl;

// 結果:
// a=[な]
// b=[にぬ]
// c=[ねの]
// d=[はひ]
// e=[ふ]
// f=[へほ]
// g=[]
// s=[な にぬ ねの はひ ふ へほ]

(Visual Studio 2015)
どこまでコピーを終えたか、は記憶されているようだ。

比較 等しい

#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く

std::string a = "あいう";

if      ("あ"         == a) { std::cout << "答1" << std::endl; }
else if ("あい"       == a) { std::cout << "答2" << std::endl; }
else if ("あいう"     == a) { std::cout << "答3" << std::endl; }
else if ("あいうえ"   == a) { std::cout << "答4" << std::endl; }
else if ("あいうえお" == a) { std::cout << "答5" << std::endl; }
else                       { std::cout << "答6" << std::endl; }

std::string unuse;
std::getline(std::cin, unuse);

// 結果:
// 答3

(Visual Studio 2015)
等号で比較できたが 本当にこれでいいのか知らない。

楽しいサンプル・プログラム

解析器

#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::istringstream, std::ostringstream

#include <vector> // 可変長配列

// 参照 : C++での文字列の使い方まとめ(string) (Futurismo) http://futurismo.biz/archives/1856
int main()
{
    // 与件
    std::istringstream data("--加納 こはだ かんぱち まぐろ --木曽 あなご かっぱ --久慈 たまご あかがい とろ いか");
    // データ構造: --人物 寿司ネタ(複数件)※繰り返し
    // 人物、寿司ネタは可変個数設定可能

    // 受け皿
    std::vector<std::string> persons; // 結果はこれらの配列に入れる
    std::vector<std::vector<std::string>> dishes;

    // 記憶
    // 別段用意無し

    // 解析器
    std::string a;
    while (data >> a) {
        if ("--"==a.substr(0,2))//先頭の2文字が「--」の場合
        {
            persons.push_back(a.substr(2)); // 最初の2文字「--」の次から
            dishes.push_back(std::vector<std::string>()); // リストの中にリストを準備
        }
        else { dishes[dishes.size() - 1].push_back(a); } // 要素数-1 で最後の要素

        std::cout << "a=[" << a << "]" << std::endl;
    }

    // 結果
    int i = 0;
    for(std::string person : persons)
    {
        for (std::string dish : dishes[i])
        {
            std::cout << "(" << i << ") person=[" << person << "] dish=[" << dish << "]" << std::endl;
        }
        i++;
    }

    std::cout << "Please, push any key." << std::endl;
    std::string unuse;
    std::getline(std::cin, unuse);
    return 0;
}

(Visual Studio 2015)
g++ だと 「while (data >> a) {」の判定で止まってくれないようだ?

3
5
0

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
5