logo elektroda
logo elektroda
X
logo elektroda

[C++] Efficient Element Removal from Char Array Based on Condition

elektronik512 24964 18
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
  • #1 7623509
    elektronik512
    Level 9  
    Does anyone know how to remove specific items from an array? I have such a program and I would like it to remove letters from the array, but I don`t know how to remove the selected element from the array ;/
    #include<iostream>
    
    using namespace std;
    
    int main()
    {
    	char dozwolone[10]={0,1,2,3,4,5,6,7,8,9};
    	char* znak=new char[50];
    	cin>>znak;
    	int i=0;
    	int k=0;
    	int c;
    	while(znak[i]!=0)
    	{
    		c=znak[i]-'0';
    		for(int j=0;j<=9;j++)
    		{
    			if(c==dozwolone[j])
    			{
    				cout<<c<<endl;
    				k++;
    			}
    		}
    		i++;
    	}
    	delete[] znak;
    	system("pause");
    	return 0;
    }
  • ADVERTISEMENT
  • #2 7624101
    Szymon Tarnowski
    Level 27  
    First try to define what you mean by "remove from the table".
  • #3 7625367
    elektronik512
    Level 9  
    For example, if there are 5 elements in the array: 5,6,e,4,g, I want the array to have 3 elements after deletion: 5,6,4
  • ADVERTISEMENT
  • #4 7625737
    Dariusz Bismor
    Level 18  
    The code you showed is actually in C, not C++. In C++, removing elements from an array is done using a standard algorithm remove_if . To use it, you must write a unary predicate that returns true when a given character does not belong to the set of allowed characters. Since the remove_if algorithm does not actually remove unwanted elements from the container, but only moves them to the end, it is usually "wrapped" with the container`s erase method.
    Assuming you have written a "checker()" predicate, the task of removing elements is trivial:
    p.erase( remove_if( p.begin(), p.end(), sprawdzacz ), p.end() );

    where "p" denotes a container, e.g. a list or a vector.
    If you insist on using a character array, you can also use this algorithm, but without erase, e.g.:
    char *koniec = remove_if( znak, znak+50, sprawdzacz ), znak+50 );

    The "end" pointer after executing this statement points to the first element that is not in the allowed character set; all elements from "char" to "end-1" are allowed elements, maintaining their original order.

    HTH,
    Darius
  • ADVERTISEMENT
  • #5 7627339
    elektronik512
    Level 9  
    Could you tell us more or less what is given in the parameters of this function?
  • #6 7630745
    Dariusz Bismor
    Level 18  
    As I wrote, it is a unary predicate, i.e. one with one argument. This argument is, of course, the element stored in the container (array) - in your case, a character. The predicate returns true if the character is not in the allowed set, false otherwise.

    Darius
  • #7 7630777
    arnoldziq
    VIP Meritorious for electroda.pl
    Dear friend Dariusz Bismor ,
    Would your friend be kind enough to describe the use of the above-mentioned function again, in a more understandable language. I would especially ask you to avoid phrases such as unary predicate .
    Please don`t forget that this post is aimed at a beginner programmer.

    Thank you in advance, arnoldziq
  • #8 7630790
    nomar600
    Level 11  
    For this purpose, it is best to replace the regular array with a vector from the standard STL library. The operation is very simple, you refer to the elements as in a regular array, the vector can store any data types, the operation is done using a few simple functions, and the vector increases its size itself if necessary. Be interested in the STL library and containers, especially vector. This is the perfect solution to your problem.
  • #9 7631386
    Dariusz Bismor
    Level 18  
    In fact, it seems to me that Arnolddziq`s request comes close to point 16 of the forum rules (twice), but after all, he is a moderator, and when called to the board, I always answer succinctly.

    The meaning of the word predicate in the context of programming in the C++ language results from point 25, paragraphs 7 and 8 of the C++ Language Standard: a predicate is a function object returning a bool value. A detailed explanation of what a function object is is beyond the scope of the forum - I recommend any book on the standard library. For the purposes of this thread, it is enough to assume - as the author of the question did in the fifth statement - that this is a function.

    Unary and binary functions are simply functions with one and two arguments. I use these names because Standard uses them (see 20.5.3), but I also provide Polish names.

    The use of the function - if it is already defined - is given in my first statement:
    "Assuming you have written the `checker()` predicate, the task of removing elements is trivial...".

    What else - apart from writing ready-made code (see point 16 of the regulations!) - can I serve?

    Darius
  • #10 7631570
    toma5z
    Level 13  
    elektronik512 wrote:
    For example, if there are 5 elements in the array: 5,6,e,4,g, I want the array to have 3 elements after deletion: 5,6,4


    I have one pathological method of removing electronics. from the board.

    If you have an array of N=5 elements with elements in the following order: 5,6,e,4,g you want to get 5,6,4
    then you do this by entering the fourth element (3 index of the array) into the 3rd cell (2 index of the array) and you have: 5,6,4,4,g then you delete the last two elements in the array N=N-2; Of course N cannot be const.
  • #11 7632306
    ed-ek
    Level 34  
    I have a question. If in the table we have:
    1,2,a,b,d,a,2,f,6,8,b,a;
    and we want to remove: 2,a;
    then we remove all the desired characters and the array will be:
    1,b,d,f,6,8,b;
    or another criterion?
  • #12 7633240
    Dariusz Bismor
    Level 18  
    The flexibility of the solution, which is based on a standard algorithm, is that any scenario can be implemented. It all depends on the predicate. A predicate can be written, for example, to remove no more than two occurrences of each element and leave the third and subsequent occurrences. Or so that it only leaves the fifth occurrence and deletes every other occurrence.

    H.T.H.,
    Darius
  • ADVERTISEMENT
  • #13 7633847
    elektronik512
    Level 9  
    I read a bit about the vektor class and came up with something like this, but the program doesn`t want to delete the data ;/ I don`t really know how this "erase" function works.
    #include<iostream>
    #include<vector>
    
    using namespace std;
    
    int main()
    {
    	vector<char>tab;
    	vector<char>dozwolone;
    	dozwolone.push_back('0');
    	dozwolone.push_back('1');
    	dozwolone.push_back('2');
    	dozwolone.push_back('3');
    	dozwolone.push_back('4');
    	dozwolone.push_back('5');
    	dozwolone.push_back('6');
    	dozwolone.push_back('7');
    	dozwolone.push_back('8');
    	dozwolone.push_back('9');
    	char* a=new char[50];
    	cin>>a;
    	int k=0;
    	while(a[k]!=0)
    	{
    		tab.push_back(a[k]);
    		k++;
    	}
    	vector<char>::iterator i;
    	vector<char>::iterator j;
    	for(i=tab.begin();i<tab.end();i++)
    	{
    		cout<<*i;
    	}
    	cout<<endl;
    	int c=0;
    	for(i=tab.begin();i<tab.end();i++)
    	{
    		for(j=dozwolone.begin();j<dozwolone.end();j++)
    		{
    			if(*i==*j)
    				tab.erase(tab.begin()+c);
    		}
    		c++;
    	}
    	cout<<endl;
    	for(i=tab.begin();i<tab.end();i++)
    		cout<<*i;
    	cout<<endl;
    	delete[] a;
    	system("pause");
    	return 0;
    }

    ps. The program now has to remove numbers instead of characters.
  • #14 7636118
    Dariusz Bismor
    Level 18  
    Oh, my friend, believe me, it`s worth investing in a book about programming in C++. Then your program will look like this:
    int main(){
      char * usuwane = "1234567890";
      vector<char> usuw( usuwane, usuwane+10 );
      list<char> p;
    
      copy( istreambuf_iterator<char>(cin), istreambuf_iterator<char>(), back_inserter( p ) );
      p.erase( remove_if( p.begin(), p.end(), sprawdzacz() ), p.end() );
      copy( p.begin(), p.end(), ostream_iterator<char>(cout, " ") );
    
      return 0;
    }

    Now a few comments.
    First of all, you were wrongly advised to store the loaded data in a vector. A vector is a container in which deleting non-final data is time-intensive . In your case, you know in advance that you will do it. It is therefore much better to use a list.
    Secondly, if you want to store the set of characters to be deleted in a vector (although there is no need to do so, an array is also a container), do it as above, not an inelegant and time-suboptimal series of push_back()s .
    Third, there is no point in reading data into a character array (help, overflow!) , and then transfer them to the container. The solution above is better (to finish loading, press enter and Ctrl-D). You could also use getline() and string - then you won`t have to press Ctrl-D.
    And finally, removal: why break open the door by writing these two deep for loops that don`t work? The code is ready - simple and error-free! - you have it above, just write the "checker" predicate (it shouldn`t be much longer than 5 lines).

    There is one more solution. If you don`t care about maintaining the order of the loaded data, it may be easier sort the container first , and then find where the numbers start. This may work faster in some situations.

    And now the riddle: what headers are needed to compile this?

    HTH,
    Darius
  • Helpful post
    #15 7641776
    ed-ek
    Level 34  
    If we really want to remove characters from the table, I have attached the code that allows us to remove any selected characters. If we only want to remove numbers or letters, the code simplifies significantly. Undoubtedly, this could be written in a simpler way, I will be grateful for your comments. I enter the characters to be removed into the container because I do not know their number in advance.
    
    #include <iostream>
    #include <conio.h>
    #include <time.h>
    #include <vector>
    using namespace std;
    int const mx=35;
    int i,j,it,ile=0,mxx=35;
    vector<char>znaki;
    char tab[35],usun,st;
    int *ile_zn;
        int erase (int x)
         {
                 for(i=x;it<mxx;i++)
                 {
                  if(i==mxx-1)break;                 
                  tab[i]=tab[i+1];      
                 }mxx--;
            return mxx;     
          }      
    int main()
    {
     	time_t t;
    	srand((unsigned) time(&t));
     cout<<"tablica wejsciowa"<<endl;
      i=0;
      while(i<35)
      {
       int x=48+rand()%54;
       if((x>57)&&(x<97))continue;else
       {
        tab[i]=char(x);cout<<tab[i]<<" ";
        i++;
        }                                          
      }     
    // koniec wypelniania tablicy   
       while(st !='/') 
       {  
         cout<<endl<<"wprowadz znak do usuniecia,znak: / konczy wprowadzanie"<<endl;              
         cin>>st;
        if(st=='/')break;      
        znaki.push_back(st);
        ile++;
        }
     if((st=='/')&&(ile==0)) {cout<<"brak znaku!";getch();exit(0);}   
      ile_zn=new int(ile);
        for(i=0;i<ile;i++)
        {ile_zn[i]=0;
         for(j=0;j<mxx;j++)
         {
           if(znaki[i]==tab[j])ile_zn[i]=ile_zn[i]+1;                
          }
          }
        for(i=0;i<ile;i++)cout<<"ile_zn= "<<znaki[i]<<" = "<<ile_zn[i]<<endl; 
              
         for(j=0;j<ile;j++)      
          for(int k=0;k<ile_zn[j];k++)                        
           for(i=0;i<mxx;i++)
           {
            usun=znaki[j];            
            if(tab[i]==usun){it=i;erase(it);break;}
           }  
    cout<<"nowa tablica"<<endl;
     for(i=0;i<mxx;i++)cout<<char(tab[i])<<" ";
     delete []ile_zn;          
     getch();   
     return 0;
      }
    
  • #16 7642776
    Dariusz Bismor
    Level 18  
    What a ride! Code of 6 lines + 5 for functor vs. code of 30 lines. Fellow ed-ek, let`s face it: you don`t write in C++, you write in C (with a little help from resizable arrays).

    Darius
  • #17 7645640
    ed-ek
    Level 34  
    Dariusz Bismor wrote:
    What a ride! Code of 6 lines + 5 for functor vs. code of 30 lines. Fellow ed-ek, let`s face it: you don`t write in C++, you write in C (with a little help from resizable arrays).

    Darius

    Please provide your code so that I can evaluate and use your solution. My code is not that long, many lines include entering an array, showing the number of elements to remove, and additional bells and whistles. In fact, the kernel of the code is less than 20 lines. What does it mean that I don`t write in C++? If you do not present your code, your post is worthless and cannot be an argument for further discussion. Present the code. Perhaps many will benefit.
  • #18 7646111
    Dariusz Bismor
    Level 18  
    I presented my code above. This is complete code, cut from a running program. The only thing missing is "#includes" and the code for the checker() functor. I`m not giving it on purpose, because learning has to cost money - otherwise you won`t remember it. Take up the challenge, make an effort, read, think. Even if it doesn`t work out, show us what you managed to do. Then I will help you improve it.

    As for C and C++, look at the C++ Language Standard: 2/3 is the description of the library. One of the advantages of high-level programming in C++ is the brevity of the code and the associated low maintenance cost. If someone doesn`t know the library and codes what is posted there, they don`t know the language. My colleague ed-ek`s code is a typical example: after converting the vector into an array and cin, cout into scanf, printf, this is C code.

    Darius
  • #19 7662081
    ed-ek
    Level 34  
    I wrote that if we want to remove only letters or only numbers from the array, the code will be simpler. I am presenting code that is essentially two programs for removing letters or numbers. There is no need to create any container. Whether the code is written in C++ does not depend on the included libraries - which we use depending on the needs - but on the nature of the code instructions.
    
    #include <iostream>
    #include <conio.h>
    using namespace std; 
    int main ()
    { 
      cout<<"usuwanie cyfr z tablicy, tab. pierwotna:"<<endl;
      char *tab1;
      int n=8,i,ii=0,j=0;  
      char tab[]={'1','z','e','5','9','g','1','5'};
         for(i=0;i<n;i++)
          {
           cout<<tab[i]<<" ";              
           if(isdigit(int (tab[i])))ii++;
           }
      cout<<endl<<"nowa tablica:"<<endl;     
      tab1=new char[n-ii];
      for(i=0;i<n;i++)
       if(!isdigit(int (tab[i])))
       {tab1[j]=tab[i];cout<<tab1[j]<<" ";j++;}    
      delete []tab1;   
      //------------------------------
      cout<<endl<<"usuwanie liter z tablicy, nowa tablica:"<<endl;
        tab1=new char[ii];
        j=0;
      for(i=0;i<n;i++)
       if(isdigit(int (tab[i])))
       {tab1[j]=tab[i];cout<<tab1[j]<<" ";j++;}    
      delete []tab1;   
        
      getch();    
      return 0;
    }
    

Topic summary

The discussion revolves around efficiently removing specific elements from a character array in C++. The original poster seeks guidance on how to eliminate certain characters from an array, specifically letters, while retaining others. Various responses suggest using C++ standard algorithms like `remove_if` in conjunction with a unary predicate to filter out unwanted characters. It is noted that while character arrays can be manipulated, using STL containers like `vector` or `list` is recommended for better performance and ease of use. The conversation also touches on the importance of understanding predicates and the flexibility they offer in defining removal criteria. Additionally, some participants provide code snippets demonstrating different approaches to the problem, including a pathological method for shifting elements and a simpler method for removing only letters or numbers.
Summary generated by the language model.
ADVERTISEMENT