【问题标题】:Return a pointer to the first appearance of a word appearing inside a given C-string返回一个指针,指向出现在给定 C 字符串中的单词的第一次出现
【发布时间】:2021-02-14 21:29:14
【问题描述】:

我在弄清楚如何返回指向给定 C 字符串中单词的第一个字符的指针时遇到了问题。问题是这样的:编写函数 findFirst()。该函数有两个参数:一个 const char * s1 指向 C 风格字符串中的第一个字符,以及一个 const char * s2。如果 s2 没有出现在 s 中,则返回指向 s2 第一次出现在 s1 中的指针和 nullptr (0)。

这是我的代码:

#include <cstddef>  // size_t for sizes and indexes
#include <iostream>
using namespace std;

const char* findFirst(const char *s1, const char *s2)
{
    while (*s1)     // go through each element in s1
    {
      ++s1;
        if (*s1 == *s2)
        {
          while(*s2)
          {
            ++s1;
            ++s2;
            if (*s1 == *s2 && *s2 == '\0' - 1)
                return s1;
          }
        }
    }
    return nullptr;
}

int main() 
{
  const char * b = findFirst("Find me in this line", "me"); 
  cout << b << endl;
}

【问题讨论】:

  • *s2 == '\0' - 1???您是否想查明s2 是否指向空字符之前的最后一个字符?
  • @iTnewbie 使用标准C函数strstr就够了。
  • 您的问题之前好像是answered
  • 您的问题是什么?这个实现是否可行?不,它不会;当然不是针对所有情况,交互式 调试器 会很快揭示原因。随着循环的进行,只要观察s1s2 所指的内容就可以提供大量信息,我强烈建议您这样做。

标签: c++ pointers c-strings


【解决方案1】:

这基本上是在重新做strstr函数。

您可以找到解决方案here

引自链接问题:

功能描述如下:

strstr() 函数定位s2指向的字符串中的字符序列(不包括终止空字符)在s1指向的字符串中的第一次出现。

strstr 函数返回一个指向已定位字符串的指针,如果未找到该字符串,则返回一个空指针。如果 s2 指向长度为零的字符串,则函数返回 s1。


char *findFirst(const char *s1, const char *s2)
{
    const char *a;
    const char *b;

    b = s2;

    if (*b == 0) {
        return (char *) s1;
    }

    for ( ; *s1 != 0; s1 += 1) {
        if (*s1 != *b) {
            continue;
        }

        a = s1;
        while (1) {
            if (*b == 0) {
                return (char *) s1;
            }
            if (*a++ != *b++) {
                break;
            }
        }
        b = s2;
    }

    return NULL;
}

【讨论】:

  • 使用时是什么意思:for( ; *s1 != 0; s1 += 1)
  • @iTnewbie 这是一个 for 循环。我们进入s1的每个元素
【解决方案2】:

对于初学者,您可以使用标准 C 函数 strstr 来完成该任务。

如果你需要自己编写一个类似的函数,那么它可以用不同的方式实现。例如

#include <iostream>
#include <cstring>

const char * findFirst( const char *s1, const char *s2 )
{
    bool found = false;
    
    size_t n1 = std::strlen( s1 );
    size_t n2 = std::strlen( s2 );
    
    if ( !( n1 < n2 ) )
    {
        for ( const char *last = s1 + n1 - n2 + 1; !found && s1 != last;  )
        {
            size_t j = 0;
            
            while ( s2[j] && s2[j] == s1[j] ) ++j;
            
            if ( !( found = s2[j] == '\0' ) ) ++s1;
        }
    }

    return found ? s1 : nullptr; 
}

int main() 
{
    std::cout << findFirst( "Find me in this line", "me" ) << '\n';
    
    return 0;
}

程序输出是

me in this line

在for循环中代替这些语句

size_t j = 0;

while ( s2[j] && s2[j] == s1[j] ) ++j;

if ( !( found = s2[j] == '\0' ) ) ++s1;

你可以使用唯一的语句

if ( !( found = memcmp( s1, s2, n2 ) == 0 ) ) ++s1;

如果您不允许使用标准 C 字符串函数,那么函数 strlen(您应该重命名为例如 string_length)可以通过以下方式实现

size_t string_length( const char *s )
{
    size_t n = 0;

    while ( s[n] ) ++n;

    return n;
}

至于你的函数实现,甚至是第二条语句

while (*s1)     // go through each element in s1
{
  ++s1;
  //...

例如,如果第二个字符串与第一个字符串的开头重合,则函数会出错,因为您增加了指针 s1

【讨论】:

  • 我的教授不允许使用任何库成员函数,如 strlen()、strstr() 等。
  • @iTnewbie 你可以自己写一个类似strlen的函数。
猜你喜欢
  • 1970-01-01
  • 2019-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
相关资源
最近更新 更多