在 [ C ] 中查找字符串函数

Find String Function in [ C ]

需要一个函数来检查我是否存在子字符串并提供我创建该函数的位置,我想知道 C 头文件中是否已经存在类似的东西以及它是如何工作的。

这个自己的函数给出了子字符串开始的位置你好世界!如果我搜索世界给 6 如果未找到字符串,则给出 -1

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

int findfstr(const char mainstring[], const char substring[]){
    // int = findstring(mainstring,substring) give position if found and -1 if not

    int main_length = strlen(mainstring); // Read the mainstring length
    int subs_length = strlen(substring); // Read the substring length
    int where = 0; // Set to 0 the var of start position
    int steps = (main_length - subs_length); //Retrive the numbers of the chars without substring
    int cicle = 0; // Set to 0 the var used for increment steps
    
    
    char found_string[subs_length]; // Set the Array to the substring length
    
    if ( subs_length <= main_length){ // If substring is bigger tha mainstring make error
        while (where == 0){ //loop until var "where are equal to 0"
            
            //Stop loop if and when  cicle is bigger than steps
            if (cicle >= steps && where == 0){ where = -1;} 
            
            //retrive the substring and store in found_string
            strncpy(found_string, mainstring+cicle, subs_length); 
            
            found_string[subs_length] = '[=10=]'; //Add terminator char to end string
            
            //If retrived string are equal to substring then set where with clicle value
            if ((strcmp(found_string, substring) == 0 )) { 
                    where = cicle;
                
            }
            cicle++; //add +1 to cicle
            
            
        }
    
    }else{ printf("\n substring is to big \n"); } //error message
    
    return where; 
}

int main(){

    int fs = 0;

    // This is how use the function
    fs = findfstr("Hello world!","world");


    if ( fs > 0 ){ printf("\n String found and start in: %d", fs);}
    if ( fs < 0 ){ printf("\n String not found value: %d", fs);}
return 0;

}

输出:

String found and start in: 6

I wanted to know if something similar already exists in the C

是的,有。

strstr 就是您要找的。参见 https://man7.org/linux/man-pages/man3/strstr.3.html

如果您想要从字符串开头开始的偏移量,只需使用指针算法即可。

类似于:

#include <stdio.h>
#include <string.h>
int main(void){
    char* str ="Hello";
 
    char* needle = strstr(str, "ell");  // Search for "ell" in str
    if (needle)
    {
        int offset = needle - str;  // Calculate the offset
        printf("offset is %d\n", offset);
    }
    else
    {
        // not found...
    }
    return 0;
}

输出:

offset is 1

有标准的 C 字符串函数 strstr 声明为

char *strstr(const char *s1, const char *s2);

实际上执行相同的任务。只有它的 return 类型与函数的 return 类型不同。

至于你的函数,它太复杂了,因为任何太复杂的函数至少都有一个可以调用未定义行为的错误。

例如,您在此声明中声明了一个可变长度数组

char found_string[subs_length];

这本身就是个坏主意,因为可能没有足够的内存来为大字符串分配这样的数组。

所以这个数组的有效索引范围是[0, subs_length)。但是,您使用值 subs_length 作为索引来访问数组

之外的内存
found_string[subs_length] = '[=12=]';

此外,用作 return 类型的类型 int 可能不够大,无法在大字符数组中存储位置。您必须改用类型 size_t

这是一个演示程序,展示了如何在不定义需要程序资源的中间可变长度数组的情况下更简单地定义函数。

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

char * findfstr( const char *s1, const char *s2 )
{
    const char *p = NULL;
    size_t n1 = strlen( s1 );
    size_t n2 = strlen( s2 );
    
    for ( ; p == NULL && !( n1 < n2 ); --n1 )
    {
        if ( strncmp( s1, s2, n2 ) == 0 )
        {
            p = s1;
        }
        else
        {
            ++s1;
        }
    }

    return ( char * )p;
}

int main(void) 
{
    char s1[] = "Hello World";
    const char *s2 = "Hello";
    
    char *p = findfstr( s1, s2 );
    
    if ( p != NULL ) printf( "%" PRIuPTR "\n", p - s1 );
    
    s2 = "World";
    
    p = findfstr( s1, s2 );
    
    if ( p != NULL ) printf( "%" PRIuPTR "\n", p - s1 );
    
    return 0;
}

程序输出为

0
6

要输出两个指针之间的差异,例如使用在 header <inttypes.h> 中声明的宏 PRIdPTRPRIuPTR。要声明一个保持两个指针之间差异的变量,请使用在 header <stddef.h>.

中声明的名称 ptrdiff_t

例如

#include <stddef.h>

//...

ptrdiff_t diff = p - s1;