【问题标题】:Function to find a string within a larger string在较大字符串中查找字符串的函数
【发布时间】:2025-11-24 00:20:10
【问题描述】:

这里是我用来实现这个程序的完整代码。一切似乎都可以编译和运行,但是一旦它运行我的 find 方法,程序似乎停止并且不执行说明 main.cpp 文件中匹配子字符串的最后一行。任何帮助都非常感谢!

.h 文件:

#include <iostream>
using namespace std;

class MyString
{
    public:
            MyString();
            MyString(const char *message);
            MyString(const MyString &source);
            ~MyString();
            const void Print() const;
            const int Length() const;
            MyString& operator()(const int index, const char b);
            char& operator()(const int i);

            MyString& operator=(const MyString& rhs);
            bool operator==(const MyString& other) const;
            bool operator!=(const MyString& other) const;
            const MyString operator+(const MyString& rhs) const;
            MyString& operator+=(const MyString& rhs);
            friend ostream& operator<<(ostream& output, const MyString& rhs);
            const int Find(const MyString& other);
            MyString Substring(int start, int length);

    private:
            char *String;
            int Size;


   };

  istream& operator>>(istream& input, MyString& rhs);

.cpp 文件:

   #include <iostream>
  #include <cstdlib>
  #include "MyString.h"

  using namespace std;

  //default constructor that sets the initial string to the value "Hello World"
 MyString::MyString()
 {
    char temp[] = "Hello World";

    int counter(0);
    while(temp[counter] != '\0')
    {
            counter++;
    }
    Size = counter;
    String = new char [Size];
    for(int i=0; i < Size; i++)
            String[i] = temp[i];

 }

 //alternate constructor that allows for setting of the inital value of the string
 MyString::MyString(const char *message)
{
    int counter(0);
    while(message[counter] != '\0')
    {
            counter++;
    }
    Size = counter;
    String = new char [Size];
    for(int i=0; i < Size; i++)
            String[i] = message[i];
  }

    //copy constructor
  MyString::MyString(const MyString &source)
  {

     int counter(0);
    while(source.String[counter] != '\0')
    {
            counter++;
    }
    Size = counter;
    String = new char[Size];
    for(int i = 0; i < Size; i++)
            String[i] = source.String[i];
  }

 //Deconstructor
 MyString::~MyString()
{
    delete [] String;
 }

//Length() method that reports the length of the string
const int MyString::Length() const
{
    int counter(0);

    while(String[counter] != '\0')
    {
            counter ++;
    }
    return (counter);
 }

/*Parenthesis operator should be overloaded to replace the Set and Get functions of    your previous assignment. Note that both instances should issue exit(1) upon violation of the string array bounaries.
*/
 MyString& MyString::operator()(const int index, const char b)
{
    if(String[index] == '\0')
    {
            exit(1);
    }
    else
    {
            String[index] = b;
    }
}

char& MyString::operator()(const int i)
{
    if(String[i] == '\0')
    {
            exit(1);
    }
    else
    {
            return String[i];
    }
}
 /*Assignment operator (=) which will copy the source string into the destination string. Note that size of the destination needs to be adjusted to be the same as the source.
 */
   MyString& MyString::operator=(const MyString& rhs)
  {
    if(this != &rhs)
    {
            delete [] String;
            String = new char[rhs.Size];
            Size = rhs.Size;

            for(int i = 0; i < rhs.Size+1 ; i++)
            {
                    String[i] = rhs.String[i];
            }
    }

    return *this;
  }
 /*Logical comparison operator (==) that returns true iff the two strings are identical in size and contents.
 */
  bool MyString::operator==(const MyString& other)const
  {
    if(other.Size == this->Size)
    {
            for(int i = 0; i < this->Size+1; i++)
            {
                    if(&other == this)                               

                        return true;
            }
    }
    else
            return false;
    }

 //Negated logical comparison operator (!=) that returns boolean negation of 2
    bool MyString::operator!=(const MyString& other) const
  {
    return !(*this == other);
  }

 //Addition operator (+) that concatenates two strings
 const MyString MyString::operator+(const MyString& rhs) const
 {
    char* tmp = new char[Size + rhs.Size +1];

    for(int i = 0; i < Size; i++)
    {
            tmp[i] = String[i];
    }
    for(int i = 0; i < rhs.Size+1; i++)
    {
            tmp[i+Size] = rhs.String[i];
    }
    MyString result;

    delete [] result.String;
    result.String = tmp;
    result.Size = Size+rhs.Size;

    return result;
 }
 /*Addition/Assigment operator (+=) used in the following fashion: String1 += String2 to operate as String1 = String1 + String2
*/
MyString& MyString::operator+=(const MyString& rhs)
{
    char* tmp = new char[Size + rhs.Size + 1];

    for(int i = 0; i < Size; i++)
    {
            tmp[i] = String[i];
    }        for(int i = 0; i < rhs.Size+1; i++)
    {
            tmp[i+Size] = rhs.String[i];
    }

    delete [] String;
    String = tmp;
    Size += rhs.Size;

    return *this;
 }
 istream& operator>>(istream& input, MyString& rhs)
{
    char* t;
    int size(256);
    t = new char[size];
    input.getline(t,size);

    rhs = MyString(t);
    delete [] t;

    return input;
 }

 ostream& operator<<(ostream& output, const MyString& rhs)
{
    if(rhs.String != '\0')
    {
            output << rhs.String;
    }
    else
    {
            output<<"No String to output\n";
    }

    return output;
 }

  const int MyString::Find(const MyString& other)
 {
       int nfound = -1;

    if(other.Size > Size)
    {
            return nfound;
    }
    int i = 0, j = 0;
    for(i = 0; i < Size; i++)
    {
            for(j = 0; j < other.Size; j++)
            {
                    if( ((i+j) >= Size) || (String[i+j] != other.String[j]) )
                    {
                            break;
                    }

            }

            if(j == other.Size)
            {
                    return i;
            }

    }

    return nfound;
    }
  /*MyString::Substring(start, length). This method returns a substring of the original string that contains the same characters as the original string starting at location start and is as long as length.
 */

 MyString MyString::Substring(int start, int length)
 {
    char* sub;
    sub = new char[length+1];


    while(start != '\0')
    {
            for(int i = start; i < length+1; i++)
            {
                    sub[i] = String[i];
            }
    }
    return MyString(sub);
 }

 //Print() method that prints the string
 const void MyString::Print() const
 {

    for(int i=0; i < Size; i++)
    {
            cout<<String[i];
    }
    cout<<endl;
  }

main.cpp 文件:

  #include <cstdlib>
  #include <iostream>
 #include "MyString.h"


  using namespace std;

 /*
 *
 */
int main (int argc, char **argv)
{

 MyString String1; // String1 must be defined within the scope

 const MyString ConstString("Target string");          //Test of alternate constructor

  MyString SearchString;  //Test of default constructor that should set "Hello World". W/o ()
 MyString TargetString (String1); //Test of copy constructor


  cout << "Please enter two strings. ";
 cout << "Each string needs to be shorter than 256 characters or terminated by /\n." << endl;
 cout << "The first string will be searched to see whether it contains exactly the second string. " << endl;

  cin >> SearchString >> TargetString; // Test of cascaded string-extraction operator


 if(SearchString.Find(TargetString) == -1) {
      cout << TargetString << " is not in " << SearchString << endl;
   }
   else {
    cout << TargetString << " is in " << SearchString << endl;
    cout << "Details of the hit: " << endl;
    cout << "Starting poisition of the hit: " << SearchString.Find(TargetString) << endl;
    cout << "The matching substring is: " << SearchString.Substring(SearchString.Find(TargetString), TargetString.Length());
  }
 return 0;
}

【问题讨论】:

  • 启动你的调试器并进入它。
  • 试试for(int j = 0; j &lt; end; j++)你不需要减1
  • 既然这是作业,我不/不应该给你答案,我可以告诉你if(String[i] != other.String[j]) 背后的逻辑有点错误或不完整。虽然我可能是错的 :) 如果您需要任何帮助,请告诉我。
  • 好像改了之后还是一样的结果。
  • @samy.vilar 我确实需要帮助,我正在尝试用逻辑思考。我需要的是在第一个字符串中搜索第二个字符串,我所能想到的就是将第二个字符的第一个字符与第一个字符进行比较,然后继续直到找到匹配项。如果未找到匹配项,则返回 -1,但一旦找到匹配项,则比较两个字符串中的下一个字符,直到达到 second-1 的长度,然后返回字符串 1 中子字符串的起始位置。将其转换为语法是个问题。

标签: c++ string oop function


【解决方案1】:

看起来内循环的不变量是 j 介于 0 和 end-2 之间。因此 j 永远不会等于 end(“匹配”条件)。

【讨论】:

    【解决方案2】:

    您的 found 逻辑似乎有问题。

    您的 for 循环定义为 for(int j = 0; j &lt; end -1; j++)

    然后你测试if(j == end)

    j 在这个 for 循环中永远不能等于 end。考虑一下您在 if 语句中实际尝试测试的内容。

    【讨论】:

      【解决方案3】:

      我认为您需要在循环之外声明 i 和 j。
      我想你的意思是j &lt; end 而不是j &lt; end - 1
      我认为你需要if((i+j&gt;=end1) || String[i+j] != other.String[j]) 而不仅仅是if(String[i+j] != other.String[j])

      if(j == end) 需要在内部循环之外。

      这是一个类似的实现。

      #include <string>
      #include <iostream>
      using namespace std;
      
      class MyString
      {
          private:
              string String;
              unsigned int Size;
          public:
              MyString() {
                  this->String = "";
                  this->Size = 0;                    
              }
              MyString(string initial_value) {
                  this->String = initial_value;
                  this->Size = initial_value.length();
              }        
      
              const int Find(const MyString& other);       
      };
      
      const int MyString::Find(const MyString& other)
      {                  
          if (other.Size > Size)
              return -1; // if the substring is greater then us, there's no way we can have it as a substring
          int i = 0, j = 0;
          for (i = 0; i < Size; i++)
          {
              for (j = 0; j < other.Size; j++)  
                  if ( ((i + j) >= Size) || (String[i + j] != other.String[j]) ) // if they don't match, offset exceeded Size, break
                      break ;
              if (j == other.Size) // We went through the entire substring, didn't hit break so j == Other.size
                  return i; // return index
          }
      
          return -1; // if we never return anything means, we didn't find it, so return -1
      }
      
      int main()
      {
          string temp1, temp2;
          getline(std::cin, temp1, '\n');
          getline(std::cin, temp2, '\n');
          MyString main_string(temp1), sub_string(temp2);
      
          cout << main_string.Find(sub_string) << endl;
          return 0;
      }
      
      
      MyString MyString::Substring(int start, int length)
      {
          char* sub = new char[length + 2]; // 2 byte buffer to be safe
      
          int i = 0;
          for (i = 0; i < length; i++)           
              sub[i] = String[start + i]; 
          sub[i] = '\0'; // always null terminated to be safe!           
      
          return MyString(sub);
       }
      

      如果有任何错误或问题,我很抱歉,没有测试过。

      【讨论】:

      • 我在这个实现中看到的一个问题是程序实际上停止了,一旦这个函数运行,我必须控制 C 来中止它。对此有什么想法吗?
      • 你的意思是程序没有停止?您是否正确初始化了变量?比如尺寸
      • 对!它不会停止。大小被定义为类中的私有 int。我很困惑它可能是什么,这使程序无法结束。
      • 抱歉那个错字......因为我不知道你是如何实现你的 cals 的,这只是我为了测试按预期工作的功能而临时想到的。
      • 是的,它确实有效,这就是为什么我对程序停止的原因如此困惑。如果我发布我的整个代码,你能看看它并告诉我哪里出错了。一切都编译并运行,这只是一个问题。我求求你了,漂亮吗???
      【解决方案4】:

      与其他人所说的一样,在您的 Substring 方法中,您有以下代码:

       while(start != '\0')
       {
           for(int i = start; i < length+1; i++)
           {
               sub[i] = String[i];
           }
      }
      

      花点时间回顾一下 while 循环的逻辑,然后问自己“我想在这里实现什么,这段代码实际上做了什么?”

      【讨论】:

      • 我已经修复了该代码并删除了 while 循环,我已经知道它的作用。我现在唯一的问题是子字符串实际上并没有打印,所以仍然有问题。输出如下所示:“匹配的子字符串是:ðäZ”对此有何想法?
      • 您不使用 NULL 终止 'sub',而是使用它来构造 MyString,使用构造函数扫描输入以查找终止 NULL。
      • 我很困惑,对不起我是初学者。您是说我必须在 sub[i] = String[i] 之后添加对 NULL 的检查吗?并且返回 Mystring(sub) 不正确?
      • 我是说你需要一个 sub[i] = 0; 循环结束后,以空值终止字符串。