简体   繁体   English

如何从char数组中正确删除字符(有或没有转换为字符串)?

[英]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. 我目前正在学习C ++,试图构建一个程序来完成基本的东西,如元音/辅音计数,删除字母等。一切正常,直到我找到自定义字母删除部分。 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. 如您所见,原始's'是一个char数组。 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: 在第一个代码示例中,我尝试将其转换为字符串数组( 字符串str(s) ),但这会导致以下编译错误:

  • error: request for member 'erase' in 's', which is of non-class type 'char[1000]' 错误:请求's'中的成员'erase',这是非类型'char [1000]'
  • error: request for member 'begin' in 's', which is of non-class type 'char[1000]' 错误:请求's'中的成员'begin',这是非类型'char [1000]'
  • error: request for member 'end' in 's', which is of non-class type 'char[1000]' 错误:请求's'中的成员'end',这是非类型'char [1000]'
  • error: request for member 'end' in 's', which is of non-class type 'char[1000]' 错误:请求's'中的成员'end',这是非类型'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: 这就是它所说的:

"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." “在抛出'std :: length_error'的实例后调用终止what():basic_string :: _ S_create此应用程序已请求运行时以不寻常的方式终止它。请联系应用程序的支持团队以获取更多信息。”

Any help would be much appreciated, stuck at this one for a week now! 任何帮助将非常感激,坚持这一个一个星期吧!

PS Is it okay if I or a moderator deletes this question after it's been answered? PS如果我或主持人在回答完问题后删除了这个问题,这样可以吗? 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. 我很确定我不是第一个问这个问题的人,但是,正如之前提到的那样,即使在回答了类似问题的答案后,我仍然会遇到这些错误。

For a char array you have to use std::remove instead of erase , and insert the null-terminator manually: 对于char数组,您必须使用std::remove而不是erase ,并手动插入null-terminator:

auto newEnd = std::remove(std::begin(s), std::end(s), letterToRemove);
*newEnd = '\0';

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 (ie it's not a C-style zero-terminated string), then here's a solution: 如果你有一个通用数组,可能会或可能没有衰减到指针,并且你有数组中的元素数但没有其他终结符(即它不是C风格的零终止字符串),那么这是一个解决方案:

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. 如果你想从那个数组中删除字母'B' ,你会找到该字母的位置,然后将下一个字母( 'C' )复制到它的位置,然后将下一个字母( 'D' )复制到下一个字母中地方等

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函数的单次调用来完成:

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: 使用上述方法之一,循环或memmove调用,将保留数组如下:

+---+---+---+-----+
| A | C | D | ... |
+---+---+---+-----+

Important note: Remember to change element_count after you "removed" the character, so it reflects the new size. 重要说明:请记住在“删除”字符后更改element_count ,以便它反映新的大小。

For your first workaround : 对于您的第一个解决方法:

string str(s);

This statement declare a string named str and is content is initialized with the content of s 此语句声明一个名为str并使用s的内容初始化content

This statement as no effect on you object s 这个语句作为你的对象没有影响s

So you need to call str.erase() not s.erase() 所以你需要调用str.erase()而不是s.erase()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM