首页 > 解决方案 > 如何找到一个字符数组出现在另一个字符数组中的次数?

问题描述

我得到了 2 个数组sirsub. 我应该通过使用库中的函数并删除第一个字母来找到sub包含的次数。例如,是和是。我可以看到第一个与第三个字母一起出现 biginning 并且我从中删除了那个字母,所以下次我搜索时我会得到不同的外观。但是我对管理, where是一个指针 这一事实感到非常困惑。是表示可以找到的次数的变量。sirstrstr<cstring>siromtatatatarshtasubtatsubsirsubsirxx=strstr(sir, sub);nrsubsir

首先,我尝试这样做forfor(i=x; i<strlen(sir); i++) sir[i]=sir[i+1];但我得到了错误invalid comparison between 'char*' to 'int'。然后,在互联网上查看了一些代码后,我尝试这样编写:for(char *x; *x!='\0'; *x++) *x=*(x+1);我没有收到任何错误,但我也没有得到任何结果。

#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
ifstream f("info.in");
char sub[20], sir[100];
char* x;
int main()
{
    int nr=0, i;
    f >> sub;
    f >> sir;
    cout << sir;
    x = strstr(sir, sub);
    while (x) {
        nr++;
        for (char* x; *x != '\0'; *x++)
            *x = *(x + 1);
        x = strstr(sir, sub);
    }
    cout << nr;
    return 0;
}

在我的例子sub中是tatsiromtatatatarshta,答案应该是 3,你可以tatomtatatatarshta3 次中找到。正如我所说,我的代码没有得到任何结果。

标签: c++

解决方案


在 C++ 中使用 C 字符串是可能的,但不推荐。管理 C 字符串的存储和处理它们并不是那么容易且容易出错。

C++ 有一个很好的替代品:std::string. 它提供了类似的功能,但承担了应用程序员的内存管理负担。

为什么 OPs 老师坚持教 C 字符串处理... Kate Gregory:停止教C。

话虽如此,我不明白为什么 OP 认为sir. C弦的“强度”是——它只是从一个char*点开始。如果该指针增加 n 次,则字符串将在 nchar秒后开始。(当然,您必须关心 0 终止符。将指针移到它后面可能会导致未定义行为。)

所以,我会这样做:

#include <iostream>
#include <cstring>

int main()
{
    const char *const sir = "omtatatatarshta";
    const char *const sub = "tat";
    int nr = 0;
    for (const char *x = sir;; ++nr) {
      x = strstr(x, sub);
      if (!x) break;
      ++x; // inc. x to prevent double matching the same
    }
    std::cout << "nr: " << nr << '\n';
    return 0;
}

输出:

nr: 3

Live Demo on coliru

查看 OP 公开的代码,我认为仍然存在误解指针的工作原理。(我记得我也需要一段时间来理解它们。)

for (char* x; *x != '\0'; *x++)
        *x = *(x + 1);

这已破了。

  1. for (char *x;x... 引入了一个仅存在于for循环中的新局部变量。已经存在x的就黯然失色了。(它仍然存在,但在for循环内部无法访问。)

  2. for (char *x;声明x但没有定义它——它是未初始化的。x可能有任何任意内容,即它可以指向任何地方。因此,读取的内容x是未定义的行为(坏)。

  3. for (char* x; *x != '\0'; *x++)*x++“读取”内容x并在之后增加指针x。这不是直接错误,但没有理由读取x. x++(甚至更好++x)就足够了。

我将此代码修复为(我相信的)OP打算做的事情:

for (; *x != '\0'; ++x) *x = *(x + 1);

此外,我添加了一些打印调试以使内部发生的情况可视化:

#include <iostream>
#include <cstring>

int main()
{
    char sir[] = "omtatatatarshta";
    const char *const sub = "tat";
    int nr = 0;
    std::cout << "sir: '" << sir << "'\n";
    char *x = strstr(sir, sub);
    while (x) {
      ++nr;
      std::cout << "Hit " << nr << '\n';
      for (; *x != '\0'; ++x) *x = *(x + 1);
      std::cout << "sir: '" << sir << "'\n";
      x = strstr(sir, sub);
    }
    std::cout << "nr: " << nr << '\n';
    return 0;
}

输出:

sir: 'omtatatatarshta'
nr: 1
sir: 'omatatatarshta'
nr: 2
sir: 'omaatatarshta'
nr: 3
sir: 'omaaatarshta'
nr: 3

Live Demo on coliru

笔记:

请注意我sir在第一个和第二个示例中声明的方式不同。

在第一个例子中:const char *const sir = "omtatatatarshta";

sir是指向 a 的const指针(由于*constconst char。该声明强制指针和内容都不能更改。指针用常量 string 的地址初始化"omtatatatarshta"

与此相反,xhas 类型const char*。它是指向常量内容的非常量指针。内容没有被触及,因此它可以被限制为只读。指针被分配(由strstr())。因此它可能不是const

在第二个例子中:char sir[] = "omtatatatarshta";.

由于sir要更改的内容,它必须是一个数组。


推荐阅读