Getting the string "abxcxxdxxxef" you need to get the string "abcdef". Wrote code that removes x only if x does not go in a row. That is, the output is the string "abcxdxef".

I understand why this is happening, but I do not understand how to fix it. I would be grateful for the explanation (in priority) how to fix it and / or the corrected part of the code.

for (place = 0; str[place] != '\0'; place++) { if (str[place] == 'x') for (int i = place; str[i] != '\0'; i++) str[i] = str[i + 1]; } 
  • It is not completely clear what needs to be done. Remove all x from a string? - entithat
  • @entithat yes, you need to delete everything - qreed
  • @AnT is something that is not quite correct, I do not argue.) But the fact remains. I enter abxcxxdxxxef and get abcxdxef. finding the "unnecessary" element, the code shifts all elements of the line to the left and shortens the output string. the problem is that if the element repeats, then just the unnecessary element moves to the left. - qreed
  • Have you tried to debug? Hint: what happens when you delete the symbol x , after which x goes again? - VTT
  • and the sequence of characters after removal is important? - Croessmah

5 answers 5

Why not write everything in a separate line?

 string str="abxcxxdxxxef"; string str2=""; for (int place = 0; str[place] != '\0'; place++) { if (str[place] != 'x') str2+=str[place]; } cout<<"\n"<<str2; 
  • and if you do not know which characters are repeated? .. - AR Hovsepyan
  • The @ARHovsepyan task was exactly for х , do you need to delete all repeating characters? Or should you leave only one MB of all repeating ones? and etc., please specify - Lolidze

An example of deleting several duplicate.

In the loop we go through each character of the string, check for the existence of the same. If it exists, then stop the check and go on. If they did not find the same one, then we add a symbol (which is unique) to the output line .

 #include <iostream> using namespace std; int main() { string s = "abxcxxdxxxef", out; bool repeat; for (int i = 0; i < s.length(); i++) { repeat = false; for (int j = 0; j < s.length(); j++) { if (i != j && s[i] == s[j]) { repeat = true; break; } } if (!repeat) { out += s[i]; } } cout << out << endl; return 0; } 

Tests:

 1. Ввод: abxcxxdxxxef Вывод: abcdef 2. Ввод: helloworld Вывод: hewrd 3. Ввод: 11258348 Вывод: 2534 4. Ввод: 1122333 Вывод: пустая строка 
  • 3
    Instead of nested loops, you can use a bit string (32 bytes), which is first zeroed out, and then, using the character code as the bit index, if we already looked at such a character. By the way, if the characters need to be deleted from the source line, then out (as char * ) can be combined with the memory in s (and at the end resize) - avp
  • @avp, useful note. I was guided by instinct when I wrote this. Unfortunately, I could not make your version :) - entithat
  • What prevents? 32 bytes is an array of 4 int. Divide the character code by 32 - get the index in this array. The remainder of the division - the number of bits. Shift 1 left by the number of bits - get a mask. Operation & check whether the bit is already set in the array. Operation |= install it. It's very simple - avp
  • @avp, we must try. Always scares the unknown :) - entithat
  • @avp, you can also use a bitset for the same purpose. But I like your option even more, the legacy of C lives. - Ternvein
 #include <iostream> using namespace std; int main() { char str[] = "abxcxxdxxxef"; size_t len = sizeof(str); size_t writePtr = 0; size_t i = 0; for(;i < len; ++i) { if(str[i] != 'x') { str[writePtr] = str[i]; ++writePtr; } } cout << str << endl; } 

Keep the index of the character to be written, and if the current character is not equal to x copy it by the index to be written and increase the index.

  • @entithat, indeed, is not enough in one cycle ( - rewardealer

You do not need to know in advance which string will be and which characters are repeated, but in C ++ you can write for example

 #include <iostream> using std::string; string& binop(string& s, char c) { if (s.back() != c) s += c; else s.erase(--s.end()); return s; } int main() { // тест string str = "prkkkkkkogrbbbbbbam C++"; str = std::accumulate(str.begin(), str.end(), string(), binop) + '?'; std::cout << str; //выдаст: "program C?" return 0; } 

    If the task is simply to remove all the 'x' from the string, then your original approach will be fine to do it. You just need to remember that the place index should not be incremented unconditionally, like yours, but only if the current element of the string was not equal to 'x'

     for (int place = 0; str[place] != '\0'; ) if (str[place] == 'x') for (int i = place; str[i] != '\0'; i++) str[i] = str[i + 1]; else ++place; 

    However, everything can be done in one pass and one cycle.

     int dst = 0; for (int src = 0; str[src] != '\0'; ++src) if (str[src] != 'x') str[dst++] = str[src]; str[dst] = '\0';