我正在创建一个类来删除随机单词中的重复字符。例如,如果输入是“aabbccddeeff”,则应输出“abcdef”。但是我的输出包含“abcdef”之后的奇怪字符。 main.cpp文件已作为创建类的要求而存在。请参阅以下代码:
main.ccp
#include <iostream>
#include "repeatdeletion.h"
using namespace std;
int main()
{
char* noRepeats;
int length;
string s;
cout<<"Enter a random word with repeating characters: ";
cin>>s;
RepeatDeletion d;
length=s.length();
noRepeats=d.deleteRepeats(s, length);
cout<<"Your word without any repeating characters: ";
for (int k=0; k<length; k++){
cout<<noRepeats[k];
}
cout<<endl;
delete [] noRepeats;
noRepeats=NULL;
return 0;
}
repeatdeletion.h
#ifndef REPEATDELETION_H
#define REPEATDELETION_H
#include <iostream>
using namespace std;
class RepeatDeletion
{
char* c;
char arr[128]={};
bool repeated;
bool isRepeated(char);
public:
RepeatDeletion();
~RepeatDeletion();
char* deleteRepeats(string, int);
};
#endif // REPEATDELETION_H
repeatdeletion.cpp
#include "repeatdeletion.h"
RepeatDeletion::RepeatDeletion()
{
repeated=false;
}
RepeatDeletion::~RepeatDeletion()
{
delete [] c;
c=NULL;
}
bool RepeatDeletion::isRepeated(char c){
bool repeated=false;
if (arr[c]>=1){
repeated=true;
arr[c]++;
}else{
arr[c]++;
}
return repeated;
}
char* RepeatDeletion::deleteRepeats(string str, int len){
c=new char[len];
int j=0;
for (int i=0; i<len; i++){
if (isRepeated(str[i])==false){
c[j]=str[i];
j++;
}
}
return c;
}
答案 0 :(得分:1)
如果要使用C字符串数组,它们最后会有一个空终止符。这意味着您希望(在deleteRepeats
中)将字符数组一个字符定义为长度
c=new char[len+1];
并且,在for
循环之后,确保将该空终结符放入:
c[j] = '\0';
然后,在你的调用函数中,你可以这样做:
cout << noRepeats;
即使您不想要使用C字符串,您也需要以某种方式将新长度传回给来电者(目前,您正在使用原始长度)。最简单的方法是(IMNSHO)仍然使用C风格的字符串并使用strlen
获取新的长度(a)。
否则,您将需要类似于新长度的参考参数,由函数填充并由调用者使用。
(a)但我建议重新思考你做事的方式。如果你想成为一名C ++编码器,是一个C ++编码器。换句话说,对字符串使用std::string
,因为它避免了人们似乎对C字符串的绝大多数问题。
答案 1 :(得分:1)
您的返回字符数组未终止。 字符串的长度函数不包括\ 0。
您有两个选择
在返回的字符数组的末尾添加null,并且std :: cout直接使用char数组(而不是char的char)
输出char数组的最终长度,并将其用作范围以char显示char
答案 2 :(得分:1)
您的打印循环使用旧的和未修改的字符串长度循环。这意味着您将超出您添加到deleteRepeats
返回的内存中的字符。
处理此问题的最简单方法是将数据作为正确的字符串终止,并检查循环中的终结符。
答案 3 :(得分:0)
for(k=0;k<length;k++)
此处length
应该是noRepeats
的确切长度,而不是s
的确切长度
所以:
char* RepeatDeletion::deleteRepeats(string str, int len)
应该返回长度 - 之后
答案 4 :(得分:0)
那是因为在你的代码中你写了以下内容:
cout<<"Your word without any repeating characters: ";
for (int k=0; k<length; k++){
cout<<noRepeats[k];
}
cout<<endl;
在这里,length
指的是原始字符串的长度(顺便提一下,你不应该传递给deleteRepeats
方法)。我建议你让deleteRepeats
返回一个字符串并写下这样的东西:
std::string noRepeats = d.deleteRepeats(s);
std::cout << "Your word without any repeating characters: ";
std::cout << noRepeats << std::endl;
C风格的字符串(char *
,如果你坚持的话)遵循最后一个字符为'\0'
的约定,表示字符串结束。您也可以通过附加deleteRepeats
来更改'\0'
,即
char* RepeatDeletion::deleteRepeats(string str){
c = new char[str.size() + 1];
int j = 0;
for (int i = 0; i < str.size(); i++){
if(isRepeated(str[i]) == false){
c[j] = str[i];
j++;
}
}
c[j] = '\0';
return c;
}
并在你的主要
std::cout << noRepeats << std::endl;
而不是for
循环。但实际上,您应该使用std::string
,如果可能的话,不要将其与char *
混用。希望有所帮助。
答案 5 :(得分:0)
使用std::unique
它可以满足您的需求:
std::string s{};
std::cin>>s;
auto it = std::unique(std::begin(s), std::end(s));
s.resize(std::distance(std::begin(s),it));
std::cout << s;
它的工作方式是遍历范围开始结束,如果当前元素等于下一个元素,则向前移动所有剩余元素。它返回新字符串结尾的位置(在此示例中为it
),但实际上并没有缩短字符串,因此在下一行我们将字符串缩短为等于begin()
距离的长度到it
。