2.12.5. 文字列#

2.12.5.1. char 型#

C 言語では、文字を取り扱う場合に char 型を利用します。char 型の変数のサイズは 1 バイトと決められているため、1 つの変数には 1 文字しか保存できません。

#include <stdio.h>

int main(void) {
    char a = 'D';
    char b = 'N';
    char c = 'A';

    printf("%c%c%c\n", a, b, c);
    // DNA

    return 0;
}

複数個の文字からなる文字列を扱う場合は、char 型の配列を利用します。この場合、配列のサイズは変数を宣言するときに決める必要があります。char 型の配列に文字列を格納する場合、文字列の最後にヌル文字 \0 を入れる必要があります。次のようにダブルクオーテーションマークで変数を作成する場合は、自動的にヌル文字が文字列の終端に挿入されますが、シングルクオーテーションマークの場合は自動的に挿入されません。

#include <stdio.h>

int main(void) {
    char str1[] = "DNA";
    char str2[] = {'R', 'N', 'A', '\0'};

    printf("%s\n", str1);
    printf("%lu\n", sizeof(str1));
    // DNA
    // 4
    
    printf("%s\n", str2);
    printf("%lu\n", sizeof(str2));
    // RNA
    // 4

    return 0;
}

2.12.5.2. char 型ポインター#

文字列を扱う方法として、char 型の配列のほかに char 型のポインターを利用することもできます。

#include <stdio.h>

int main(void) {
    const char* char_ptr = "DNA";

    printf("%s\n", char_ptr);
    // DNA

    return 0;
}

2.12.5.3. string 型#

C++ では string 型を利用すると、char 型の配列やポインターよりも文字列の取り扱いが便利になります。

#include <stdio.h>
#include <string>
#include <iostream>

int main(void) {
    std::string str1 = "DNA";
    std::string str2 = "RNA";
    std::string str3 = str1 + str2;
    
    std::cout << str3 << std::endl;
    // DNARNA

    return 0;
}

2.12.5.4. char 型から string 型への変換#

char 型配列から string 型に変換するときは、配列のサイズを指定する必要があります。次の例では、sizeof 関数を利用して char 型配列のサイズを取得しています。

#include <stdio.h>
#include <string>
#include <iostream>

int main(void) {
    char arr[] = "CGTCAAACGG";

    std::string dna_seq(arr, sizeof(arr) / sizeof(arr[0]));

    std::cout << dna_seq << std::endl;
    // CGTCAAACGG

    return 0;
}

char 型ポインターから string 型に変換するときは、string 型のコンストラクタを利用します。

#include <stdio.h>
#include <string>
#include <iostream>

int main(void) {
    const char* char_ptr = "CGTCAAACGG";

    std::string dna_seq = std::string(char_ptr);

    std::cout << dna_seq << std::endl;
    // CGTCAAACGG

    return 0;
}

2.12.5.5. string 型の文字列操作#

2.12.5.5.1. 文字列へのアクセス#

C++ の string 型の文字列中の文字にアクセスするには、変数に添字を指定します。一文字目の添字は 0 から始まります。

#include <stdio.h>
#include <string>
#include <iostream>

int main(void) {
    std::string seq = "CGTCAAACGG";

    std::cout << seq[0] << std::endl;
    // C
    std::cout << seq[1] << std::endl;
    // G

    return 0;
}

2.12.5.5.2. 文字列の長さ#

C++ の string 型の文字列の長さは、size() 関数を利用して調べることができます。

#include <stdio.h>
#include <string>
#include <iostream>

int main(void) {
    std::string seq = "CGTCAAACGG";
    int seq_len = seq.size();

    std::cout << seq_len << std::endl;
    // 10

    return 0;
}

2.12.5.5.3. 文字列の結合#

複数の C++ の string 型の文字列を結合するには、+ 演算子を利用します。

#include <stdio.h>
#include <string>
#include <iostream>

int main(void) {
    std::string exon_1 = "CGTCAAACGC";
    std::string exon_2 = "CGCCCGATAG";
    std::string exon_3 = "AACCAATTGT";
    std::string mRNA = exon_1 + exon_2 + exon_3;

    std::cout << mRNA << std::endl;
    // CGTCAAACGCCGCCCGATAGAACCAATTGT

    return 0;
}

文字列の検索

複数の C++ の string 型の文字列の中から特定の文字列を検索するとき、前から検索する場合は find 関数、後ろから検索する場合は rfind 関数を利用します。

#include <stdio.h>
#include <string>
#include <iostream>

int main(void) {
    std::string seq = "CGTATACAAACCGGAGCGAAAAC";
    
    std::string::size_type trip_A_1 = seq.find("AAA");    
    if (trip_A_1 != std::string::npos) {
        std::cout << trip_A_1 << std::endl;
        // 7
    } else {
        std::cout << "AAA not found." << std::endl;
    }

    std::string::size_type trip_A_2 = seq.rfind("AAA");    
    if (trip_A_2 != std::string::npos) {
        std::cout << trip_A_2 << std::endl;
        // 19
    } else {
        std::cout << "AAA not found." << std::endl;
    }

    return 0;
}

2.12.5.6. 文字列の置換#

C++ の string 型の文字列の置換には replace 関数を利用します。開始位置と文字数を指定して置換する場合は、次のように記述します。

#include <stdio.h>
#include <string>
#include <iostream>

int main(void) {
    std::string seq = "CGTCAACGTAACCTGC";
    
    seq.replace(0, 3, "AAAAAAAAAA");
    
    std::cout << seq << std::endl;
    // AAAAAAAAAACAACGTAACCTGC

    return 0;
}

特定の文字列のみを別の文字列に置換する場合の例を以下に示します。次の例では、文字列中のすべての T を U に置換しています。

#include <stdio.h>
#include <string>
#include <iostream>

std::string replace_with_str (std::string str, std::string str_from, std::string str_to) {
    std::string::size_type pos = 0;
    while (pos = str.find(str_from, pos), pos != std::string::npos) {
        str.replace(pos, str_from.length(), str_to);
        pos += str_to.length();
    }
    return str;
}

int main(void) {
    std::string seq = "CGTCAACGTAACCTGC";
    std::string seq2 = replace_with_str(seq, "T", "U");
    
    std::cout << seq << std::endl;
    // CGTCAACGTAACCTGC
    std::cout << seq2 << std::endl;
    // CGUCAACGUAACCUGC

    return 0;
}