检查 Char Array 是否包含特殊序列而不使用 C 中 Unix 上的字符串库

Check if Char Array contains special sequence without using string library on Unix in C

假设我们有一个字符数组和一个序列。接下来我们要检查 char 数组是否包含特殊序列 WITHOUT <string.h> LIBRARY:如果是 -> return true;如果没有 -> return 错误。

bool contains(char *Array, char *Sequence) {
     // CONTAINS - Function
     for (int i = 0; i < sizeof(Array); i++) {
         for (int s = 0; s < sizeof(Sequence); s++) {
             if (Array[i] == Sequence[i]) {
            
                 // How to check if Sequence is contained ?  
             }
         }
     }
    return false;
}
// in Main Function
char *Arr = "ABCDEFG";
char *Seq = "AB";
bool contained = contains(Arr, Seq);
if (contained) {
    printf("Contained\n");
} else {
    printf("Not Contained\n"); 
}

任何想法、建议、网站...?

提前致谢, 问候,来自 ∆

这不是最有效的算法,但我不想对您的代码进行太多更改。

size_t mystrlen(const char *str)
{
    const char *end = str;
    while(*end++);

    return end - str - 1;
}

bool contains(char *Array, char *Sequence) {
     // CONTAINS - Function
     bool result = false;
     size_t s, i;

     size_t arrayLen = mystrlen(Array);
     size_t sequenceLen = mystrlen(Sequence);

    if(sequenceLen <= arrayLen)
    {
        for (i = 0; i < arrayLen; i++) {
            for (s = 0; s < sequenceLen; s++) 
            {
                if (Array[i + s] != Sequence[s]) 
                {
                    break;
                }
            }
            if(s == sequenceLen) 
            {
                result = true;
                break;
            }

        }
    }
    return result;
}

int main()
{
    char *Arr = "ABCDEFG";
    char *Seq = "AB";
    bool contained = contains(Arr, Seq);
    if (contained) 
    {
        printf("Contained\n");
    } 
    else 
    {
        printf("Not Contained\n"); 
    }
}

最简单的方法是简单的搜索功能:

for (i = 0; i < lenS1; i++) {
    for (j = 0; j < lenS2; j++) {
        if (arr[i] != seq[j]) {
            break; // seq is not present in arr at position i!
        }
    }
    if (j == lenS2) {
        return true;
    }
 }

请注意,您不能使用 sizeof,因为您寻求的值在 运行 时未知。 Sizeof 将 return 指针大小,因此无论您使用什么字符串,几乎可以肯定总是四个或八个。您需要显式计算字符串长度,这在 C 中是通过知道字符串的最后一个字符为零来完成的:

lenS1 = 0;
while (string1[lenS1]) lenS1++;
lenS2 = 0;
while (string2[lenS2]) lenS2++;

一个明显而简单的改进是将 i 限制在 0 和 lenS1 - lenS2 之间,如果 lenS1 < lenS2,立即 return false。显然,如果您在到达 'L' 时还没有在“WELCOME”中找到“HELLO”,那么在剩下的四个字符 COME 中就不可能包含五个字符的 HELLO:

if (lenS1 < lenS2) {
    return false; // You will never find "PEACE" in "WAR".
}
lenS1minuslenS2 = lenS1 - lenS2;

for (i = 0; i < lenS1minuslenS2; i++)

进一步改进取决于您的用例

在大量数组中寻找相同的序列,总是在同一个数组中寻找不同的序列,在大量不同的数组中寻找大量不同的序列 - 所有这些都需要不同的优化。

字符在数组和序列中的长度和分布也很重要,因为如果您知道在一个长字符串中只有(比方说)三个 E,并且您知道它们在哪里,您就需要搜索对于 HELLO,只有三个地方适合使用 HELLO。所以你不需要扫描整个“我们祝你圣诞快乐,我们祝你圣诞快乐,新年快乐”字符串。实际上你可能会注意到数组中没有 L 并且立即 return false.

一般用例的平衡选项(它确实有病理情况)可能由Boyer-Moore string matching algorithm提供(C源代码和解释在link).这有一个设置成本,所以如果你需要在 非常大的文本 中寻找不同的 短字符串 ,这不是一个好的选择(有并行搜索版本,适用于其中一些情况。

基本上这是strstr

const char* strstrn(const char* orig, const char* pat, int n)
{
    const char* it = orig;
    do
    {
        const char* tmp = it;
        const char* tmp2 = pat;
        if (*tmp == *tmp2) {
            while (*tmp == *tmp2 && *tmp != '[=10=]') {
                tmp++;
                tmp2++;
            }
            if (n-- == 0)
                return it;
        }
        tmp = it;
        tmp2 = pat;
    } while (*it++ != '[=10=]');
    return  NULL;
}

上述returns n 匹配字符串中的子串。