I need help debugging my code. I've tried many things, but I can't seem to be able to delete a character from a string.
I also don't understand completely how std::erase works, I'm not sure if you can erase characters with it.
#include <iostream>
#include <string>
using namespace std;
int main(){
string s;
char n;
cin >> s;
cin >> n;
for (int i = 0;i < s.length(); i++) {
s.erase (n[i]);
}
cout << s;
return 0;
}
EDIT: Sorry for being so vague. I recognized my issue of attempting to delete something from an array rather than the intended string. With the help of the answers posted; the updated code is attached below that works the way I want it to. Thank you for your responses!
#include <iostream>
#include <string>
using namespace std;
int main(){
string s;
char n;
cin >> s;
cin >> n;
for (int i = 0; i < s.length(); i++) {
while (s[i] == n) {
s.erase(i, i);
}
}
cout << s;
return 0;
}
Use the erase-remove idiom:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string s = "Hello World!";
s.erase(std::remove(s.begin(), s.end(), 'l', s.end());
std::cout << s << std::endl;
return 0;
}
Broken down into two statements it would be:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string s = "Hello World!";
auto it = std::remove(s.begin(), s.end(), 'l');
s.erase(it, s.end());
std::cout << s << std::endl;
return 0;
}
If you want just to remove one character from the string you can use its method find to find the character in the string. For example
auto pos = s.find( n );
if ( pos != std::string::npos ) s.erase( pos, 1 );
Or you can use a loop the following way
std::string::size_type pos = 0;
while ( pos < s.size() && s[pos] != n ) ++pos;
if ( pos != s.size() ) s.erase( pos, 1 );
If you want to erase all occurrences of the character in the string using a loop you can write
for ( std::string::size_type pos = 0; pos < s.size(); )
{
if ( s[pos] == n ) s.erase( pos, 1 );
else ++pos;
}
It will be helpful if you included a proper description of what you are trying to do. The question is a little vague but I presume you are trying to remove a given char from a string, if that's what you are trying to do, here is a working example that builds on what you already provided.
#include <iostream>
#include <string>
using namespace std;
int main(){
string s;
char n ;
cin >> s;
cin >> n;
for (int i = 0; i < s.length(); i++) {
if (s[i] == n) {
s.erase(i, 1);
}
}
cout << s;
return 0;
}
Related
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
vector<string> createvector() {
vector<string> words;
string names;
cout << "Please enter 5 different words: " << endl;
for (int i = 0; i < 5; i++) {
cin >> names;
words.push_back(names);
}
return (words);
}
void mostchar(vector<string> words) {
string w1 = words[0];
string largestword;
for (int i = 1; i < 5; i++) {
if (words[i] > w1) {
largestword = words[i];
}
}
cout << "The largest word is: " << largestword;
}
int main()
{
vector<string> words;
string names;
words = createvector();
mostchar(words);
}
I do not understand why it's picking the last element or the second to last element every time. Right I've tried to change for(int i = 1; i < 5; i++) but it makes no difference to what I do.
For starters you are comparing strings in the lexicographical order.
if (words[i] > w1) {
Secondly you always comparing with the word in the first element of the array
if (words[i] > w1) {
and the variable w1 is not being changed within the loop. So any last element in the vector that is greater than w1 will be assigned to the variable largestword.
Using the for loop the function can look the following way
void mostchar( const std::vector<std::string> &words )
{
size_t largestword = 0;
for ( size_t i = 1; i < words.size(); i++ )
{
if ( words[largestword].size() < words[i].size() )
{
largestword = i;
}
}
if ( largestword != words.size() )
{
std::cout << "The largest word is: " << words[largestword] << '\n';
}
}
Pay attention to that in general case the user can pass to the function an empty vector. You must check such a possibility within the function.
Bear in mind that there is standard algorithm std::max_element that can be used instead of manually written for loop.
For example
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
void mostchar( const std::vector<std::string> &words )
{
auto largestword = std::max_element( std::begin( words ), std::end( words ),
[]( const auto &a, const auto &b )
{
return a.size() < b.size();
} );
if ( largestword != std::end( words ) )
{
std::cout << "The largest word is: " << *largestword << '\n';
}
}
There are a couple issues here:
1: You should use something like .length() to compare "length"
2: You are comparing the next word in the array to words[0] every time.
EDIT: To further explain this, there is an assignment of string w1 = words[0];. w1 is then used in the if in the for loop here:
string w1 = words[0];
string largestword;
for (int i = 1; i < 5; i++) {
if (words[i] > w1) {
largestword = words[i];
}
}
resulting in the value of words[0] being the value repeatedly compared in the loop.
Adjust the comparison line to if (words[i].length() > largestword.length()) and that solves both problems. You can elminate w1 entirely this way as well.
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
vector<string> createvector() {
vector<string> words;
string names;
cout << "Please enter 5 different words: " << endl;
for (int i = 0; i < 5; i++) {
cin >> names;
words.push_back(names);
}
return (words);
}
void mostchar(vector<string> words) {
string largestword;
for (int i = 0; i < 5; i++) {
if (words[i].length() > largestword.length()) {
largestword = words[i];
}
}
cout << "The largest word is: " << largestword;
}
int main()
{
vector<string> words;
string names;
words = createvector();
mostchar(words);
}
I am trying to replace each occurrence of the letter 'a' by the letter 'z', each occurrence of 'b' by 'y', etc, and each occurrence of 'z' by 'a'....in a string. But the code is not giving desired output...
int main()
{
string S;
cin >> S;
string alphabet = "abcdefghijklmnopqrstuvwxyz";
string reversed = "zyxwvutsrqponmlkjihgfedcba";
int N = S.length();
for(int i = 0; i < N; i++)
{
for(int z = 0; z < 26; z++)
{
if(S[i] == alphabet[z])
{
S[i] = reversed[z];
}
}
}
cout << S << endl;
}
If you're using ASCII you can do this:
int main()
{
std::string S;
std::cin >> S;
std::for_each(std::execution::par_unseq, S.begin(), S.end(),
[](char &c) { c = 'a' + 'z' - c; });
std::cout << S << std::endl;
}
Your logic is flawed:
for(int i = 0; i < N; i++)
{
for(int z = 0; z < 26; z++)
{
if(S[i] == alphabet[z])
{
S[i] = reversed[z];
}
}
}
As reversed is the reversed of alphabet, whenever you encounter S[i]== alphabet[z] you will replace the letter, but after that you will encounter the replaced letter again in alphabet.
Example: You replace a by z but then at the end of the loop you find z and replace that by a.
To avoid replacing the replaced character, break from the loop after you replaced it:
for(int i = 0; i < N; i++)
{
for(int z = 0; z < 26; z++)
{
if(S[i] == alphabet[z])
{
S[i] = reversed[z];
break;
}
}
}
Note that there is a more efficient solution, as characters a till z have consecutive values you can look them up directly instead of using a loop.
Moreover, you really should have used a debugger to see what the code does. It is simple code like this that is a good opportunity to learn how to use a debugger.
Here is my five cents.:)
#include <iostream>
#include <string>
#include <cctype>
#include <cstring>
int main()
{
const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
const size_t N = sizeof( alphabet ) - 1;
std::string s( alphabet );
// std::cin >> s;
for (auto &c : s)
{
if (const char *p = std::strchr( alphabet, std::tolower( ( unsigned char )c ) ) )
{
size_t i = p - alphabet;
if (std::isupper( c ))
{
c = std::toupper( alphabet[N - i - 1] );
}
else
{
c = alphabet[N - i - 1];
}
}
}
std::cout << alphabet << '\n';
std::cout << s << '\n';
}
The program output is
abcdefghijklmnopqrstuvwxyz
zyxwvutsrqponmlkjihgfedcba
Pay attention to that the user can enter a symbol that is not present in the alphabet or a letter in the upper case. The program should correctly process such situations.
For example if the user will enter the string "AbcxyZ" then the program output will be
ZyxcbA
You could write a separate function that does the task. For example.
#include <iostream>
#include <string>
#include <cctype>
#include <cstring>
std::string & reverse_letters( std::string &s )
{
const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
const size_t N = sizeof( alphabet ) - 1;
for (auto &c : s)
{
if (const char *p = std::strchr( alphabet, std::tolower( ( unsigned char )c ) ))
{
size_t i = p - alphabet;
if (std::isupper( c ))
{
c = std::toupper( alphabet[N - i - 1] );
}
else
{
c = alphabet[N - i - 1];
}
}
}
return s;
}
int main()
{
std::string s( "AbcxyZ" );
std::cout << s << '\n';
std::cout << reverse_letters( s ) << '\n';
s.assign( "A1b2y3Z4" );
std::cout << s << '\n';
std::cout << reverse_letters( s ) << '\n';
}
The program output is
AbcxyZ
ZyxcbA
A1b2y3Z4
Z1y2b3A4
I am trying to erase particular characters using the erase() function from a string but its not working.
The question says you have to remove a substring which is either "AB" or "BB". When the substring gets deleted from the string the remaining parts of the string get concatenated and the process continues...
Here is the code:
#include <bits/stdc++.h>
#define ios ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long int
using namespace std;
int32_t main()
{
ios;
int t;
cin>>t;
while(t--)
{
string s;
cin>>s;
int i;
for(i=0;i<s.length();i++)
{
if(s[i]=='A'&&s[i+1]=='B')
{
s.erase(i,i+1);
cout<<s<<"\n";
i=-1; // I want to start from begining therefore initializing i=-1 after i++ it becomes i=0;
}
else if(s[i]=='B'&&s[i+1]=='B')
{
s.erase(i,i+1);
cout<<s<<"\n";
i=-1;
}
}
//cout<<s.length()<<"\n";
}
return 0;
}
Input:
1
AABBBABBBB
The output is :
ABBABBBB
BBABBBB
BABBBB
BBBB
BBB
BB
B
But the output should be:
ABBABBBB
BABBBB
BBBB
BB
Am I doing something wrong?
You can change two s.erase(i, i + 1); statements to s.erase(i, 2);.
1
AABBBABBBB
ABBABBBB
BABBBB
BBBB
BB
And you can use C++ STL.
#include <vector>
#include <iostream>
#include <string>
int main() {
int t{0};
std::cin >> t;
while (t--) {
std::string s{};
std::cin >> s;
for (auto i = 0; i < s.length() && i + 1 < s.length(); i++) {
if (s[i] == 'A' && s[i + 1] == 'B') {
s.erase(i, 2);
std::cout << s << std::endl;
i = -1;
} else if (s[i] == 'B' && s[i + 1] == 'B') {
s.erase(i, 2);
std::cout << s << std::endl;
i = -1;
}
}
}
return EXIT_SUCCESS;
}
Am I doing something wrong?
Yes, almost everything.
#include <iostream>
#include <string>
#include <regex>
int main()
{
std::regex re("AB|BB");
int t;
std::cin >> t;
while(t--)
{
std::string s;
std::cin >> s;
std::string prev;
// do one replacement at a time, until there are no changes
do
{
std::cout << s << '\n';
prev = s;
s = std::regex_replace(s, re, "", std::regex_constants::format_first_only);
} while (s != prev);
}
return 0;
}
It's just a simple variation of bubble sort.
#include <iostream>
#include <string>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while(t > 0 && t--)
{
string s;
cin >> s;
for(size_t i = 0; i < s.length(); i++) {
for(size_t j = 0; j < s.length() - 1; j++) {
if((s[j]=='A' || s[j] == 'B') && s[j+1]=='B')
{
s.erase(j,2);
cout<<s<<"\n";
break;
}
}
}
}
return 0;
}
What's the best way of counting all the occurrences of a substring inside a string?
Example: counting the occurrences of Foo inside FooBarFooBarFoo
One way to do is to use std::string find function:
#include <string>
#include <iostream>
int main()
{
int occurrences = 0;
std::string::size_type pos = 0;
std::string s = "FooBarFooBarFoo";
std::string target = "Foo";
while ((pos = s.find(target, pos )) != std::string::npos) {
++ occurrences;
pos += target.length();
}
std::cout << occurrences << std::endl;
}
#include <iostream>
#include <string>
// returns count of non-overlapping occurrences of 'sub' in 'str'
int countSubstring(const std::string& str, const std::string& sub)
{
if (sub.length() == 0) return 0;
int count = 0;
for (size_t offset = str.find(sub); offset != std::string::npos;
offset = str.find(sub, offset + sub.length()))
{
++count;
}
return count;
}
int main()
{
std::cout << countSubstring("FooBarFooBarFoo", "Foo") << '\n';
return 0;
}
You should use KMP Algorithm for this.
It solves it in O(M+N) time where M and N are the lengths of the two strings.
For more info-
https://www.geeksforgeeks.org/frequency-substring-string/
So what KMP Algorithm does is, it search for string pattern. When a pattern has a sub-pattern appears more than one in the sub-pattern, it uses that property to improve the time complexity, also for in the worst case.
The time complexity of KMP is O(n).
Check this out for detailed algorithm:
https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/
#include <iostream>
#include<string>
using namespace std;
int frequency_Substr(string str,string substr)
{
int count=0;
for (int i = 0; i <str.size()-1; i++)
{
int m = 0;
int n = i;
for (int j = 0; j < substr.size(); j++)
{
if (str[n] == substr[j])
{
m++;
}
n++;
}
if (m == substr.size())
{
count++;
}
}
cout << "total number of time substring occur in string is " << count << endl;
return count;
}
int main()
{
string x, y;
cout << "enter string" << endl;
cin >> x;
cout << "enter substring" << endl;
cin >> y;
frequency_Substr(x, y);
return 0;
}
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1,s2;
int i=0;
cout<<"enter the string"<<endl;
getline(cin,s1);
cout<<"enter the substring"<<endl;
cin>>s2;
int count=0;
string::iterator it=s1.begin();
while(it!=s1.end())
{
if(*it==s2[0])
{
int x =s1.find(s2);
string subs=s1.substr(x,s2.size());
if(s2==subs)
count++;
}
++it;
}
cout<<count<<endl;
return 0;
}
when I was researching vectors, I noticed that size() is supposed to give the number of elements in the vector, right? So, when I found c++ does not have a string split() function built-in, I decided to make one. The problem is, vector.size() displays the same value as vector.capacity() as shown in the code:
#include <iostream>
#include <algorithm>
using namespace std;
void split(string input, char chr, vector<string> list) {
string add;
string conv;
int size = 0;
for (int i = 0; i <= input.size(); i++) {
if ((input[i] != char(chr)) && (input[i] != 0)) {
conv = input[i];
add += conv;
}
else {
cout << list.size() << endl;
if (size <= list.capacity()) {
list[size] = add;
add = "";
size++;
}
}
}
}
int main() {
vector<string> list(6);
split("test1,test2", ',', list);
for (int i = 0; i < 2; i++) {
cout << list[i] << endl;
}
}
The output is this:
6
6
<blank line>
<blank line>
whereas it SHOULD be this from my understanding:
1
2
test1
test2
Edit: if this is of any importance, I am compiling with -std=c++11
You initialize the vector with size 6, not capacity 6. It will be constructed with 6 empty elements inside and thus setting values 0 and 1 won't change that.
The reason why you see only blank lines is that you pass the vector by value instead of by reference to you split function.
#include <iostream>
#include <string>
#include <vector>
void split (const std::string& s, char sep, std::vector<std::string>& words)
{
if (s.empty()) return;
std::size_t beg = 0;
std::size_t end = s.find(sep, beg);
while (end != std::string::npos)
{
words.push_back(s.substr(beg, end - beg));
beg = end + 1;
end = s.find(sep, beg);
}
words.push_back(s.substr(beg));
}
int main() {
std::vector<std::string> words;
split("test1,test2", ',', words);
for (std::size_t i = 0; i != words.size(); ++i) {
std::cout << words[i] << std::endl;
}
return 0;
}