C++-一个函数会使其他函数发生故障

C++ - one function makes others malfunction

本文关键字:函数 其他 故障 C++- 一个      更新时间:2023-10-16

这是我的任务:

编写类Word,该类具有:

  1. 字符数组上的指针
  2. 构造函数和析构函数
  3. 读取单词的函数
  4. 函数检查作为参数传递给它的字符是否出现在单词中,并返回出现的位置
  5. 函数,用于检查两个单词中哪一个出现次数更多的数字10,并返回出现次数

这是我的解决方案。我编译它没有错误,但它并没有按预期工作。

#include <iostream>
#include <string.h>
using namespace std;
class Word
  {
    private:
       char *content;
       int length;
    public:
       Word();
       Word(char *);
       ~Word();
       void print_content(void);
       int check_character(char);
       friend int check_number(Word,Word);
  };

Word::Word()
  {
  }
Word::Word(char *n)
  {
    length=strlen(n);
    content=new char [length];
    for(int i=0;i<length;i++)
      {
         content[i]=n[i];
      }
  }

Word::~Word()
  {
    delete content;
  }

void Word::print_content(void)
  {
    for(int i=0;i<length;i++)
      {
        cout<<""<<content[i];
      }
  }

int Word::check_character(char a)
  {
    int position=0;
    for(int i=0;i<length;i++)
      {
         if(content[i]==a)
          {
            position=i+1;
          }
      }
    if(position>0)
      {
        return position;
      }
    else return 0;
  }

int check_number(Word n,Word m)
  {
    int counter_n=0;
    int counter_m=0;
    for(int i=1;i<n.length;i++)
      {
        if((n.content[i-1]=='1')&&(n.content[i]=='0'))
          {
            counter_n=counter_n+1;
          }
      }
    for(int i=1;i<m.length;i++)
      {
        if((m.content[i-1]=='1')&&(m.content[i]=='0'))
          {
            counter_m=counter_m+1;
          }
      }
    if(counter_n>counter_m)
      { 
        return counter_n;
      }
    else if(counter_n<counter_m)
      {
        return counter_m;
      }
    else return 0;
  }

int main()
  {
    char characters1[]="qwerty10",*p1,*p2;
    char characters2[]="stackoverflow101010";
    p1=characters1;
    p2=characters2;
    Word first(p1);
    Word second(p2);
    cout<<""<<first.check_character('q')<<endl;
    cout<<""<<second.check_character('f')<<endl;
    //cout<<""<<check_number(first,second)<<endl; 
    first.print_content();
    second.print_content();
  }

由于某种原因,函数check_number(first,second)会使其他函数无法正常工作,如果您通过删除"//"来调用它,您会看到第一个.print_content()和第二个.print/content(。或者,如果函数first.check_character('r')首先被调用,第二个.check_charter('j')第二个被调用,然后check_number(first,second),那么两个第一次被调用的函数将不起作用。这种奇怪行为的原因是什么?

Word对象通过复制传递给check_number,但您没有定义复制构造函数。所以编译器使用默认的一个,而这个复制指针(char* content)。传递给函数的临时对象指向主函数中创建的数据firstsecond。。。在删除时(临时对象在调用函数后被删除),它们会删除指针,因此firstsecond对象指向已删除的内存。你在这里有未确定的行为,这解释了你所经历的副作用。

通过引用check_number传递对象是解决问题的一种简单方法。以下是一个工作代码(包括许多修复,因为您没有正确访问数组):

#include <iostream>
using namespace std;
#include <iostream>
#include <string.h>
using namespace std;
class Word
  {
    private:
       char *content;
       int length;
    public:
       Word();
       Word(char *);
       ~Word();
       void print_content(void);
       int check_character(char);
       friend int check_number(const Word&,const Word&); // changed here
  };

Word::Word()
  {
  }
Word::Word(char *n)
  {
    length=strlen(n);
    content=new char [length];
    for(int i=0;i<length;i++)
      {
        content[i]=n[i]; // changed here
      }
  }

Word::~Word()
  {
    delete [] content; // changed here
  }

void Word::print_content(void)
  {
    for(int i=0;i<length;i++)
      {
        cout<<""<<content[i]; // changed here
      }
  }

int Word::check_character(char a)
  {
    int position=0;
    for(int i=0;i<length;i++)
      {
         if(content[i]==a) // changed here
          {
            position=i+1;
          }
      }
    if(position>0)
      {
        return position;
      }
    else return 0;
  }

int check_number( const Word& n, const Word& m)// changed here
  { 
    int counter_n=0;
    int counter_m=0;
    for(int i=1;i<n.length;i++)
      {
        if((n.content[i-1]=='1')&&(n.content[i]=='0')) // changed here
          {
            counter_n=counter_n+1;
          }
      }
    for(int i=1;i<m.length;i++)
      {
        if((m.content[i-1]=='1')&&(m.content[i]=='0')) // changed here
          {
            counter_m=counter_m+1;
          }
      }
    if(counter_n>counter_m)
      { 
        return counter_n;
      }
    else if(counter_n<counter_m)
      {
        return counter_m;
      }
    else return 0;
  }

int main()
  {
    char characters1[]="qwerty10",*p1,*p2;
    char characters2[]="stackoverflow101010";
    p1=characters1;
    p2=characters2;
    Word first(p1);
    Word second(p2);
    cout<<""<<first.check_character('q')<<endl;
    cout<<""<<second.check_character('f')<<endl;
    cout<<""<<check_number(first,second)<<endl; 
    first.print_content();
    second.print_content();
  }

该输出:

1
10
3
qwerty10stackoverflow101010

声明复制构造函数是解决问题的另一种方法:

Word( const Wodr& word ) :
    length( word.length ),
    content( new char[word.length] )
{
    memcpy( content, word.content, word.length );
}

这将比通过const引用传递对象效率低,但会使代码更安全(最好始终声明复制构造函数,以防止您在这里遇到错误)。

最后,如果你懒惰,你也可以将复制构造函数声明为私有的,以防止编译器复制对象,只需声明它,而不是强制执行它:

class Word
{
   ....
private:
    Word( const Word& word ); // this makes argument passed by copy impossible.
};

然后,编译器将不允许您调用check_number。

相关文章: