从随机单词中删除重复的字符

时间:2014-07-28 06:58:03

标签: c++

我正在创建一个类来删除随机单词中的重复字符。例如,如果输入是“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;
}

6 个答案:

答案 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。

您有两个选择

  1. 在返回的字符数组的末尾添加null,并且std :: cout直接使用char数组(而不是char的char)

  2. 输出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

直播http://ideone.com/0CeaHW