Eludium
Eludium

Reputation: 61

How to properly remove a character from a char array (with or without converting to a string)?

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:

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:

"terminate called after throwing an instance of 'std::length_error' what(): basic_string::_S_create          This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information."

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.

Upvotes: 4

Views: 35421

Answers (3)

Some programmer dude
Some programmer dude

Reputation: 409166

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.

Upvotes: 1

baddger964
baddger964

Reputation: 1227

For your first workaround :

string str(s);

This statement declare a string named str and is content is initialized with the content of s

This statement as no effect on you object s

So you need to call str.erase() not s.erase()

Upvotes: 0

Emil Laine
Emil Laine

Reputation: 42828

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';

Upvotes: 9

Related Questions