在较大的字符串中查找子字符串的位置

时间:2016-11-13 22:24:27

标签: c string function for-loop substring

我创建了一个函数,该函数应该在较大的字符串中找到子字符串的第一个字符的数字位置。我输出有一些问题,我不太清楚为什么。这些问题包括每次返回-1而不是子串的整数位置。我已经调试过,无法追踪功能出错的地方。

这是函数应该执行的方式:如果我的字符串是“狗很快”并且我正在搜索子字符串“dog”,则该函数应返回4.感谢chqrlie对循环的帮助。

这是功能:

int findSubString(char original[], char toFind[]) {

    size_t i, j;
    int originalLength = 0;
    int toFindLength = 0;

    originalLength = strlen(original) + 1;
    toFindLength = strlen(toFind) + 1;

    for (i = 0; i < toFindLength + 1; i++) {
        for (j = 0; j < originalLength + 1; j++) {
            if (toFind[j] == '\0') {
                return i;
            }
            if (original[i + j] != toFind[j]) {
                break;
            }
        }
        if (original[i] == '\0') {
            return -1;
        }
    }
}

无法修改功能参数,这是一项要求。任何帮助表示赞赏!

3 个答案:

答案 0 :(得分:1)

你的循环是颠倒的。外环应该从零到originalLength的位置,包括在内;嵌套循环应该将位置从零走到toFindLength,包括在内。

originalLengthtoFindLength都应该设置为strlen返回的值,而不是strlen加1,因为空终结符位置不是一个好的开始。

最后,您将从外部循环中返回-1。这太早了 - 只有在完成外部循环后才应该返回-1

答案 1 :(得分:1)

您的循环计数器测试不正确:错误的上限和限制关闭一个。请注意,当您点击'\0'终结符时退出两个循环时,实际上不需要进行测试。

这是一个更简单的版本:

int findSubString(const char *original, const char *toFind) {
    for (size_t i = 0;; i++) {
        for (size_t j = 0;; j++) {
            if (toFind[j] == '\0') {
                return i;
            }
            if (original[i + j] != toFind[j]) {
                break;
            }
        }
        if (original[i] == '\0') {
            return -1;
        }
    }
}

计算字符串长度以减少病理情况下的比较次数(如findSubString("aaaaaaaaaaa", "aaaaaaaaaaaa");

)有一个小优势
int findSubString(const char *original, const char *toFind) {
    size_t originalLength = strlen(original);
    size_t toFindLength = strlen(toFind);

    if (toFindLength <= originalLength) {
        for (size_t i = 0; i <= originalLength - toFindLength; i++) {
            for (size_t j = 0;; j++) {
                if (toFind[j] == '\0') {
                    return i;
                }
                if (original[i + j] != toFind[j]) {
                    break;
                }
            }
        }
    }
    return -1;
}

答案 2 :(得分:1)

循环中的这些语句

       if (toFind[j] == '\0') {
            return i;
        }

导致未定义的行为,因为字符串toFind可能比字符串original短。

同样适用于此循环

        if (original[i + j] != toFind[j]) {
            break;
        }

因为i + j可能大于字符串original的长度。

如果要在其中找到子字符串,则无需扫描字符串original的所有字符。

此外,您应检查字符串original的长度是否不小于字符串toFind的长度。

如果您只想在字符串toFind中找到字符串original的第一个字符,则使用标准C函数strchr就足够了。如果要在字符串toFind中找到整个字符串original,则可以使用另一个C标准函数strstr

如果您想自己编写函数以在其他字符串中查找字符串,那么它可以查找以下方式

我声明了这个函数

long long int findSubString( const char original[], const char toFind[] );

然而,您可以根据自己的喜好编写声明,例如

int findSubString( char original[], char toFind[] );

但在这种情况下,您应该声明函数局部变量success,如

int success = -1;

并使用格式说明符"%d"而不是"%lld"输出结果。

你在这里。

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

long long int findSubString( const char original[], const char toFind[] )
{
    size_t n = strlen( original );
    size_t m = strlen( toFind );

    long long int success = -1;

    if ( !( n < m ) )
    {
        n = n - m + 1;

        for ( size_t i = 0; success == -1 && i < n; i++ )
        {
            size_t j = 0;
            while ( j < m && original[i+j] == toFind[j] ) j++;

            if ( j == m ) success = i;
        }
    }

    return success;
}

int main(void) 
{
    printf( "%lld\n", findSubString( "The dog was fast", "dog" ) );

    return 0;
}

它的输出是

4