How to properly remove a character from a char array (with or without converting to a string)?
Solution 1
For a char array you have to use
std::remove
instead of erase
, and insert the null-terminator manually:
auto newEnd = std::remove(std::begin(s), std::end(s), letterToRemove);
*newEnd = '\0';
Solution 2
If you have a generic array, that may or may not have decayed to a pointer, and you have the number of elements in the array but no other terminator (i.e. it's not a C-style zero-terminated string), then here's a solution:
First I want to you think abut how the array looks in memory. For example if we have an array of characters
char array[X] = { 'A', 'B', 'C', 'D', ... };
This array will look like this in memory
+---+---+---+---+-----+ | A | B | C | D | ... | +---+---+---+---+-----+
If you wanted to remove the letter 'B'
from that array you find the position of the letter, then you copy the next letter ('C'
) into its place, and the next next letter ('D'
) into the next letter place, etc.
You can of course do this using a single loop:
size_t index_to_remove = 1; // The index of 'B'
for (size_t i = index_to_remove = 1; i < element_count - 1; ++i)
array[i] = array[i + 1];
The above loop is simple, easy to figure out, and easy to step through in a debugger. It is also not very effective, especially if the array is large.
All the above copying can actually be done using a single call to the memmove
function:
memmove(&array[index_to_remove],
&array[index_to_remove + 1],
element_count - index_to_remove - 1);
The above call will basically do the same as our loop above but in a more efficient and optimized way.
Using either of the above methods, the loop or the memmove
call, will leave the array like this:
+---+---+---+-----+ | A | C | D | ... | +---+---+---+-----+
Important note: Remember to change element_count
after you "removed" the character, so it reflects the new size.
Admin
Updated on July 05, 2022Comments
-
Admin almost 2 years
Sorry in advance for any possible duplicate question. I have been Googling a solution for my compiler error, for a week now, tried different workarounds from various answers around here, yet I keep getting some errors.
I am currently learning C++, trying to build a program that does basic stuff like vowel/consonant count, letter removal etc. Everything works fine until I get to the custom letter removal part. Basically, it's near impossible to do that using character functions (according to my knowledge), while converting to a string seems to spawn other kinds of errors.
Here is the code fragment where I keep getting errors:
if (strcmp (service, key4) ==0) { string str(s); cout<<endl<<"Please insert the letter you would like removed from your "<<phrasal<<":"<<endl; cin>>letterToRemove; s.erase(remove(s.begin(), s.end(),letterToRemove), s.end()); cout<<endl<<s<< "\n"<<endl; }
and here are initialized variable I used:
int main() { char s[1000], phrasal[10], service[50], key1[] = "1", key2[] = "2", key3[] = "3", key4[] = "4", key5[] = "5", key6[] = "6", key0[] = "0", *p, letterToRemove; int vowel=0, vowel2=0, consonant=0, consonant2=0, b, i, j, k, phrase=0, minusOne, letter, idxToDel; void pop_back(); char *s_bin;
As you can see, the original 's' is a char array. In the first code sample I have tried converting it into a string array (string str(s)), but that results in the following compiling errors:
- error: request for member 'erase' in 's', which is of non-class type 'char[1000]'
- error: request for member 'begin' in 's', which is of non-class type 'char[1000]'
- error: request for member 'end' in 's', which is of non-class type 'char[1000]'
- error: request for member 'end' in 's', which is of non-class type 'char[1000]'
The other workaround I've tried was this:
if(strcmp(service, key4)==0) {std::string s(s); cout<<endl<<"Please insert the letter you would like removed from your "<<phrasal<<":"<<endl; cin>>letterToRemove; s.erase(remove(s.begin(), s.end(),letterToRemove), s.end()); cout<<endl<<s<< "\n"<<endl; }
Now here's the funny part, I get no errors whatsoever for this one, but the debug crashes as soon as I select the custom letter removal feature. Here's what it says:
Any help would be much appreciated, stuck at this one for a week now!
P.S. Is it okay if I or a moderator deletes this question after it's been answered? I'm quite sure I'm not the first one who asks this, but, as before-hand mentioned, I keep getting these errors, even after following answers from similar questions.
-
Admin over 7 yearsThank you. Both yours and @baddger964 's answers seems to have solved this problem. However, what exactly happens to the char s[ ] array after I have converted it using string str(s) ? My code consists of some loops that will make it go back to certain points, where the operator is required to insert a word/phrase based on the cin.getline format (to be as detailed as possible, you have to insert a sentence which equals 'cin.getline(service, 50)' ; depending on your input, the standard will have to apply some char functions to the s array). Thank you for your time.
-
Admin over 7 yearsThank you, this has proven useful!
-
Admin over 7 yearsYep, that's how it works indeed, but for my code you do not have an already known position for the element you want removed; the operator inputs a number/letter and the program would have to search for that element in the string array... which brings it to another questioning: what algorithm should I apply after the strchr function, that will basically do what you pinpointed in your example above? Thanks for the highly detailed answer, though, I appreciate it.
-
Some programmer dude over 7 years@Teo If you are using
strchr
, or any other C string function on this array, then it is a string and you should really be usingstd::string
. -
Some programmer dude over 7 years@Teo As for your question in the comment, you can actually subtract two (related) pointers to get the difference. If you subtract
s
from the (non-null) pointer you get fromstrchr
you get an offset that can be used as an index. Or you use the result fromstrchr
directly in the call tomemmove
. -
emlai over 7 years"what exactly happens to the char s[ ] array after I have converted it using string str(s) ?" — Nothing. The characters are copied into the
std::string
object, and the array is left untouched. -
Admin over 7 yearsThanks @tuple_cat, that's great!