【C言語】検索する文字列が何番目の位置にあるのか調べる方法

この記事では、標準ライブラリのstrstr関数を使った簡単な方法から、自分で検索機能を実装する方法、さらには応用的な検索方法までをわかりやすく解説します。

初心者の方でも理解できるように、サンプルコードとその解説を交えながら進めていきますので、ぜひ最後まで読んでみてください。

目次から探す

文字列検索の方法

C言語で文字列を検索する方法はいくつかありますが、ここでは標準ライブラリの関数を使った方法と、自分で実装する方法の両方を紹介します。

strstr関数の利用

C言語の標準ライブラリには、文字列を検索するための便利な関数が用意されています。

その中でも代表的なのがstrstr関数です。

strstr関数の基本的な使い方

strstr関数は、ある文字列の中から特定の部分文字列を検索するための関数です。

以下のように使用します。

#include <stdio.h>
#include <string.h>
int main() {
    char str[] = "Hello, world!";
    char substr[] = "world";
    char *pos = strstr(str, substr);
    if (pos != NULL) {
        printf("Found at position: %ld\n", pos - str);
    } else {
        printf("Not found\n");
    }
    return 0;
}

このコードでは、strstr関数を使ってstrの中からsubstrを検索しています。

見つかった場合、その位置を表示します。

strstr関数の戻り値の解釈

strstr関数は、検索に成功すると部分文字列が最初に現れる位置へのポインタを返します。

検索に失敗するとNULLを返します。

上記の例では、posNULLでない場合にその位置を計算して表示しています。

文字列検索の手動実装

標準ライブラリを使わずに、自分で文字列検索を実装する方法もあります。

これにより、より細かい制御が可能になります。

ループと条件分岐を使った検索

まず、ループと条件分岐を使って文字列を検索する基本的な方法を見てみましょう。

#include <stdio.h>
#include <string.h>
int main() {
    char str[] = "Hello, world!";
    char substr[] = "world";
    int str_len = strlen(str);
    int substr_len = strlen(substr);
    int found = 0;
    for (int i = 0; i <= str_len - substr_len; i++) {
        int j;
        for (j = 0; j < substr_len; j++) {
            if (str[i + j] != substr[j]) {
                break;
            }
        }
        if (j == substr_len) {
            printf("Found at position: %d\n", i);
            found = 1;
            break;
        }
    }
    if (!found) {
        printf("Not found\n");
    }
    return 0;
}

このコードでは、strの中からsubstrを手動で検索しています。

外側のループでstrの各位置をチェックし、内側のループで部分文字列が一致するかどうかを確認します。

部分文字列の比較方法

部分文字列の比較は、内側のループで行います。

str[i + j]substr[j]を比較し、一致しない場合は内側のループを抜けます。

すべての文字が一致した場合、部分文字列が見つかったことになります。

インデックスの計算方法

部分文字列が見つかった場合、その位置を表示するためにインデックスを計算します。

上記のコードでは、外側のループのインデックスiが部分文字列の開始位置になります。

これで、C言語で文字列を検索する基本的な方法を理解できたと思います。

標準ライブラリの関数を使う方法と、自分で実装する方法の両方を試してみてください。

応用例

複数の文字列を検索する方法

複数の文字列を検索する場合、strstr関数を繰り返し使用する方法が一般的です。

例えば、ある文字列の中に複数の異なる部分文字列が含まれているかどうかを調べる場合、以下のようなコードが考えられます。

#include <stdio.h>
#include <string.h>
int main() {
    char str[] = "This is a sample string for testing.";
    char *keywords[] = {"sample", "testing", "example"};
    int num_keywords = 3;
    for (int i = 0; i < num_keywords; i++) {
        char *pos = strstr(str, keywords[i]);
        if (pos != NULL) {
            printf("Keyword '%s' found at position %ld\n", keywords[i], pos - str);
        } else {
            printf("Keyword '%s' not found\n", keywords[i]);
        }
    }
    return 0;
}

このコードでは、keywords配列に含まれる各キーワードをstrstr関数で検索し、見つかった場合にはその位置を表示します。

大文字小文字を区別しない検索

C言語の標準ライブラリには大文字小文字を区別しない文字列検索関数は含まれていませんが、自分で実装することが可能です。

以下の例では、strcasestr関数を自作して大文字小文字を区別しない検索を行います。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
char *strcasestr(const char *haystack, const char *needle) {
    if (!*needle) {
        return (char *)haystack;
    }
    for (; *haystack; haystack++) {
        if (tolower((unsigned char)*haystack) == tolower((unsigned char)*needle)) {
            const char *h, *n;
            for (h = haystack, n = needle; *h && *n; h++, n++) {
                if (tolower((unsigned char)*h) != tolower((unsigned char)*n)) {
                    break;
                }
            }
            if (!*n) {
                return (char *)haystack;
            }
        }
    }
    return NULL;
}
int main() {
    char str[] = "This is a Sample String for Testing.";
    char keyword[] = "sample";
    char *pos = strcasestr(str, keyword);
    if (pos != NULL) {
        printf("Keyword '%s' found at position %ld\n", keyword, pos - str);
    } else {
        printf("Keyword '%s' not found\n", keyword);
    }
    return 0;
}

このコードでは、strcasestr関数を使用して大文字小文字を区別しない検索を行い、キーワードが見つかった位置を表示します。

正規表現を使った高度な検索

C言語で正規表現を使用するには、POSIXライブラリのregex.hを利用します。

以下の例では、正規表現を使って文字列を検索する方法を示します。

#include <stdio.h>
#include <regex.h>
int main() {
    char str[] = "This is a sample string for testing.";
    char pattern[] = "s[a-z]*e";
    regex_t regex;
    int reti;
    // 正規表現のコンパイル
    reti = regcomp(®ex, pattern, REG_EXTENDED);
    if (reti) {
        fprintf(stderr, "Could not compile regex\n");
        return 1;
    }
    // 正規表現のマッチング
    reti = regexec(®ex, str, 0, NULL, 0);
    if (!reti) {
        printf("Pattern '%s' found in string\n", pattern);
    } else if (reti == REG_NOMATCH) {
        printf("Pattern '%s' not found in string\n", pattern);
    } else {
        char msgbuf[100];
        regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
        fprintf(stderr, "Regex match failed: %s\n", msgbuf);
        return 1;
    }
    // 正規表現の解放
    regfree(®ex);
    return 0;
}

このコードでは、regcomp関数で正規表現をコンパイルし、regexec関数で文字列に対してマッチングを行います。

マッチング結果に応じて、パターンが見つかったかどうかを表示します。

以上のように、C言語では標準ライブラリや自作関数、POSIXライブラリを活用して、さまざまな方法で文字列検索を行うことができます。

これらの方法を組み合わせることで、より高度な文字列操作が可能になります。

目次から探す