c++ remove all duplicates of a character in a string

I made this program to remove all duplicates in a string. I used counting sort to make it efficient. But the problem is if I enter a string "shilpi" it removes all occurrences of the character thats repeated. The output becomes "shlp". I want it to be "shilp". How do I change this code to do that ? :

link to formatted code: http://rafb.net/p/lZHCjS15.html

#include<iostream>
#include<conio.h>
#include<string.h>
using namespace std;
class dup
{
      string s;
      int c[256];
      public:
             void input();
             void logic();
             dup();
};
dup::dup()
{
          for(int i=0;i<256;i++)
          c[i]=0;
}
void dup::input()
{
     cout<<"enter a string\n";
    cin>>s;
}
void dup:: logic()
{
     int sc=0,d=0;
     for(int i=0;s[i]!='\0';i++)
     {
               c[s[i]]=c[s[i]]+1; //the c array stores the no. of occurence of each alphabet. e.g if string is "abcae"
                                  //then c[97]=2,c[98]=1,c[99]=1,c[100]=0,c[101]=1,c[102]=0......
     }
     //int cx[];
     for(int j=0;s[j]!='\0';j++)
     {//cout<<c[s[j]];
             if(c[s[j]]==1)
             {
                          s[d]=s[sc]; //if there's only 1 occurence of this alphabet
                          d++;
                          sc++;
             }
             else
             {
                     sc++;
             }
     }
     for(int k=0;k<d;k++)
     {
             cout<<s[k];
     }
}
int main()
{
    dup d;
    d.input();
    d.logic();
    getche();
}
     
shilpi84Asked:
Who is Participating?
 
itsmeandnobodyelseConnect With a Mentor Commented:
UrosVidojevic and abith,

why are you posting full code to a homework assignment. Experts are allowed to help but not to make the work in case of homework.

Instead of posting code that is supposed to be copied and pasted, you should have outlined how the asker could change his program to make it work. That is what he asked for and that is what he would help him much more than exchanging his own code by one of yours.

>>>> How do I change this code to do that ? :
If the occurrence of a char is >1 you need to print it once. To find out that given char already was printed you simply set the c[s[i]] to 0 (you also could set it to -c[s[i]] if you don't want to loose the information).

So your code might turn to

             if(c[s[j]] >=1)    // print all where the occurrence >= 1
             {
                          s[d]=s[sc]; //if there's only 1 occurence of this alphabet
                          d++;
                          sc++;
                          c[s[j]] = 0;   // that makes that it is not printed twice
             }
             else
             {
                     sc++;
             }

Regards, Alex
0
 
UrosVidojevicConnect With a Mentor Commented:
Here is the corrected version.

You don't need to count characters, just go
char by char through string.
In used array you memorize which chars you have used.
If you have used some character, you ignore it.
If you didn't use it, just add character and mark it used in used array.

#include<iostream>
#include<conio.h>
#include<string.h>
using namespace std;
class dup
{
      string s;
      bool used[256];
      public:
             void input();
             void logic();
             dup();
};
dup::dup()
{
          for(int i=0;i<256;i++)
                  used[i] = false;

}
void dup::input()
{
     cout<<"enter a string\n";
    cin>>s;
}
void dup:: logic()
{
    int sc = 0;
    for (int i = 0; s[i] != '\0'; i++)
        if (!used[s[i]]) {
           s[sc] = s[i];
           sc++;
           used[s[i]] = true;
        }
   
    for (int j = 0; j < sc; j++)
        cout << s[j];    
       
}
int main()
{
    dup d;
    d.input();
    d.logic();
    getche();
}
0
 
UrosVidojevicConnect With a Mentor Commented:
Also some recommendations.
I didn't want to modify your code much but I noticed a big C influence in your C++ program. :-)
Some of them are:

- I suppose you used header <conio.h> because getche(); function, in c++ more used method is cin.get().
- It is better to iterate through string with:
      for (int i = 0; i < s.length(); i++)
  than with
      for (int i = 0; s[i] != '\0'; i++)
- You don't need use new variable name for each new for loop.
      it is ok to say:
            for (int i = 0; i < n; i++) {/* something*/}
            /* ... */
            for (int i = 0; i < m; i++) {/* something else*/}
     except in VS6 where this approach isn't legal, and your is.

0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

 
abithConnect With a Mentor Commented:
this will do  with less memory

class dup
{
      char m_szStr[256] ;
public:
      void input();
      void logic();
      char* output();
};

void dup::input()
{
    cout<<"enter a string\n";
      std::cin>>m_szStr;
}
char* dup::output()
{
      return m_szStr;
}
void dup:: logic()
{
      int repeat[3]= {0};
      char refBot [3] = {'0','A','a'};
      char refTop [3] = {'9','Z','z'};
      int start = 0;
      int pos =0;
      int ind =0;
      while(m_szStr [pos] )
      {
            int c = m_szStr[pos] ;

            for (int ind=0; ind<3;ind++)
                  if (c <= refTop[ind])
                  {
                        if(!( repeat[ind] & (1 << (c-refBot[ind]+1)) ))
                        {
                              m_szStr[start++] = m_szStr[pos];
                              repeat[ind] |= (1 << (c-refBot[ind]+1));
                        }
                        ind = 3;
                  }
            pos++;
      }
      m_szStr [ start] = 0;
}

int main()
{
    dup d;
    d.input();
    d.logic();
    cout << d.output() << endl;
}
0
 
abithCommented:
this works  with ALL ASCII letters..

void dup:: logic()
{
      int repeat[ 130/sizeof(int) + 1 ]= {0};
      int start = 0;
      int pos =0;
      int ind =0;
      while(m_szStr [pos] )
      {
            int c = m_szStr[pos] ;
            int arInd = c / (sizeof (*repeat) * 8 -1) ;
            int nShift = c % (sizeof (*repeat) * 8  -1) ;

            if (repeat [arInd] & ( 1 << (nShift + 1)))
                  pos++;
            else
            {
                  m_szStr[start++] = m_szStr[pos];
                  repeat[arInd] |= (1 << (nShift + 1));
            }
      }
      m_szStr [ start] = 0;
}

0
 
shilpi84Author Commented:
thanks alex ( it wasn't homework though :) )...

thanks UrosVidojevic good solution but i'm going with Alex's solution as it's the least modification to my code.

thanks abith.
0
 
shilpi84Author Commented:
thanks UrosVidojevic for the C, C++ tips :)
0
 
itsmeandnobodyelseCommented:
>>>> it wasn't homework though :)
Yes, I believe you though the task is a typical homework task.

>>>> thanks UrosVidojevic for the C, C++ tips
Unfortunately, Uros not only posted full code when not knowing whether it is homework or not, but his tips are questionable as well:

- I suppose you used header <conio.h> because getche(); function, in c++ more used method is cin.get().

cin.get() is rather unusual. Like any C++ stream operation it requires a key + enter as input. So it has no benefits over getche()  beside that it is C++.

I would recommend to put all statements of main() in a while(true) block. At end of that block, ask the user whether she wants to continue? If no, break the endless loop.


- It is better to iterate through string with:
      for (int i = 0; i < s.length(); i++)
  than with
      for (int i = 0; s[i] != '\0'; i++)

Uros is right, though I wonder that you can use std::string at all, cause you included <string.h> and not <string>. string.h is the old (deprecated) string header and I really wonder why your code compiled. Note, when  s[i] == '\0' you are accessing the string out of the boundaries where indexing is valid. std::string could throw an exception when doing so, though most implementations wouldn't do.

- You don't need use new variable name for each new for loop.
      it is ok to say:
            for (int i = 0; i < n; i++) {/* something*/}
            /* ... */
            for (int i = 0; i < m; i++) {/* something else*/}
     except in VS6 where this approach isn't legal, and your is.

It would be better to have

   int i = 0;
   for (i = 0; i < n; i++) {/* something*/}
   ...
   for (i = 0; i < m; i++) {/* something else*/}

cause that works for all compilers.


Some additional remarks:

- main should return 0 finally.
- instead of

     for(int k=0;k<d;k++)  { cout<<s[k]; }

  you could

      s.resize(d);
      cout << s;

Regards, Alex
0
 
UrosVidojevicCommented:
"but his tips are questionable as well"

Alex, I don't agree with you, every one of my tips is correct, and I'm sure that not any of your remarks towards correctness of my tips have much weight. Since all of 3 things I said are widely used by professionals and authors (and yes I have examples of that).

I don't want to argue with you
    because I don't like to argue with people on forums especially on this forum.
   and because I'm here since recent, and you are one of the main experts in this area so it wouldn't be polite of me.

But, by saying that my comments are of questionable truth you are directly insulting me and my knowledge, and you don't even know who am I.

I will not comment more about this issue.
Bye
0
 
itsmeandnobodyelseCommented:
>>>> you don't even know who am I
Uros, I experienced multiple times that you were posting full code to homework assignments (or what looks like homework). That alone makes your comments less worthy (and may have made me choosing my words more 'rough' than you deserve it).

>>>> saying that my comments are of questionable truth
>>>> you are directly insulting me
I didn't say that they are of 'questionable truth' but that they are questionable, i. e. that I wouldn't fully agree to these recommendations.

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.