[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 744
  • Last Modified:

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();
}
     
0
shilpi84
Asked:
shilpi84
  • 3
  • 3
  • 2
  • +1
4 Solutions
 
UrosVidojevicCommented:
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
 
UrosVidojevicCommented:
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
 
abithCommented:
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
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
 
itsmeandnobodyelseCommented:
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
 
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

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

  • 3
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now