【问题标题】:Finding the last occurrence of a string in a sentence in C在C中的句子中查找字符串的最后一次出现
【发布时间】:2020-02-19 11:24:41
【问题描述】:

我正在练习,我遇到了一个练习。练习说我要手动编写一个函数来查找字符串中最后一次出现的索引。现在,我知道这可能以前被问过,但我找不到我的代码有什么问题。它适用于几乎所有实例,但当单词最后一次出现在字符串的开头时则不适用。

我的尝试:我使用指针来存储句子和我们正在寻找的单词的 ends 的地址。然后我使用了一个while循环来遍历字符串。如果当前字符与我们正在搜索的单词的 last 字符匹配,我们进入另一个比较两者的 while 循环。如果指向单词开头的指针和我们用来遍历单词的指针相等,则找到该单词。

这里有一些代码:


#include <stdio.h>

int find_last( char *str,  char *word)
{
    char *p, *q;

    char *s, *t;

    p=str;                            /* Pointer p now points to the last character of the sentence*/
    while(*p!='\0') p++;
    p--;

    q = word;
    while(*q!='\0') q++;             /* Pointer q now points to the last character of the word*/
    q--;

    while(p != str) {
        if(*p == *q) {
            s=p;                        /* if a matching character is found, "s" and "t" are used to iterate through */
            /* the string and the word, respectively*/
            t=q;

            while(*s == *t) {
                s--;
                t--;
            }

            if(t == word-1) return s-str+1;  /* if pointer "t" is equal by address to pointer word-1, we have found our match. return s-str+1. */
        }
        p--;
    }
    return -1;
}

int main()
{
    char arr[] = "Today is a great day!";

    printf("%d", find_last(arr, "Today"));

    return 0;
}

所以,这段代码应该返回0,但它返回-1

它适用于我测试的所有其他实例!在 CodeBlocks 中运行时,输出符合预期 (0),但使用任何其他在线 IDE,我发现输出仍然是 -1。

【问题讨论】:

  • while(*s == *t) { s--; t--; } - 你不能那样做,你不知道什么时候结束。
  • @Srilakshmikanthanp 等等,现在当我在 CodeBlocks 上尝试它时,它也适用于我。但是,当使用我的大学提供的在线云 IDE 时,它无法按预期工作!
  • 我还希望那些对问题投反对票的人提供这样做的理由。我遵循了为提问而制定的所有准则,据我所知,我是准确且非常清楚的。
  • @johndoe 就我而言,我认为这项任务对于初学者来说并不容易。 SO也不明白为什么您的问题被否决了,尽管您描述了问题并提供了演示问题的代码。我赞成你的问题。:)
  • @VladfromMoscow 嘿,非常感谢!向新人提问会变得非常令人沮丧。再次感谢您!

标签: c arrays find c-strings substr


【解决方案1】:

对于初学者,函数的参数应具有限定符 const,其返回类型应为 size_tptrdiff_t

例如

ptrdiff_t find_last( const char *str,  const char *word );

在任何情况下,函数都应至少声明为

int find_last( const char *str,  const char *word );

该函数应模拟标准 C 函数 strstr 的行为。也就是说,当第二个参数是空字符串时,函数应该返回 0。

如果任何一个参数是空字符串,那么由于这些语句,您的函数具有未定义的行为

p=str;                            /* Pointer p now points to the last character of the sentence*/
while(*p!='\0') p++;
p--;
^^^^

q = word;
while(*q!='\0') q++;             /* Pointer q now points to the last character of the word*/
q--;
^^^^

如果str指向的字符串只包含一个符号,那么你的函数返回-1,因为循环的条件

while(p != str) {

独立于两个字符串是否相等而评估为假。

这个循环

        while(*s == *t) {
            s--;
            t--;
        }

再次可以调用未定义的行为,因为可以访问字符串单词之前的内存。

还有这句话

if(t == word-1) return s-str+1;

同样可以调用未定义的行为。

函数可以定义为如下演示程序所示。

#include <stdio.h>

int find_last( const char *str,  const char *word )
{

    const char *p = str;

    int found = !*word;

    if ( !found )
    {
        while ( *p ) ++p;

        const char *q = word;

        while ( *q ) ++q;

        while ( !found && !( p - str < q - word ) )
        {
            const char *s = p;
            const char *t = q;

            while ( t != word && *( s - 1 ) == *( t - 1) )
            {
                --s;
                --t;
            }

            found = t == word;

            if ( found ) p = s;
            else --p;
        }
    }

    return found ? p - str : -1; 
}

int main(void) 
{
    const char *str = "";
    const char *word = "";

    printf( "find_last( str, word ) == %d\n", find_last( str, word ) );

    word = "A";

    printf( "find_last( str, word ) == %d\n", find_last( str, word ) );

    str = "A";

    printf( "find_last( str, word ) == %d\n", find_last( str, word ) );

    str = "ABA";

    printf( "find_last( str, word ) == %d\n", find_last( str, word ) );

    str = "ABAB";

    printf( "find_last( str, word ) == %d\n", find_last( str, word ) );

    str = "ABCDEF";

    printf( "find_last( str, word ) == %d\n", find_last( str, word ) );

    str = "ABCDEF";
    word = "BC";

    printf( "find_last( str, word ) == %d\n", find_last( str, word ) );

    return 0;
}

程序输出是

find_last( str, word ) == 0
find_last( str, word ) == -1
find_last( str, word ) == 0
find_last( str, word ) == 2
find_last( str, word ) == 2
find_last( str, word ) == 0
find_last( str, word ) == 1

【讨论】:

    猜你喜欢
    • 2012-03-23
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 2018-08-24
    相关资源
    最近更新 更多