How do you insert characters into middle of string? C++ - c++

The purpose of this code is to insert an x in between repeating letters. For example, if I were to input "CoolBoolFallmoose", the output would be "CoxolBoxolFalxlmoxose".
The code is also supposed to make an even number of pairs of letters, so if there is an odd amount of characters, an x is added to the end of the string. An example for this would be if we had "ball", it would become "balxlx" to make even pairs: "ba" "lx" "lx".
This is the code I have so far:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main(){
string cipher, plain, paired = "";
cout << "input plaintext(no spaces, lowercase):\n";
cin >> plain;
for (int i=0;i<plain.length();i++){
if (plain[i]==plain[i+1]){
plain.insert(i,'x');
}
paired[i]=paired[i];
cout<<paired[i];
}
if (paired.length() % 2!= 0){
paired=+'x';
}
cout<<paired<<endl;
return 0;
}
The output I get is just the same as my input, no "x" added in any place.
The issue I am having is, every time I try to use the append() or insert() function for strings, I get an error from my compiler, which is xCode. Is there another way to solve this code?
EDIT: The error says:
No matching member function to call for insert
It also comes up for append().

I don't really know what you wanted to do with this part:
paired[i]=paired[i];
cout<<paired[i];
but otherwise the logic is good. Here is my take on it, x is a counter:
#include <iostream>
#include <string>
using namespace std;
int main(){
string m,n;
int x = 0;
cout << "Input: " << endl;
getline(cin, m);
for(int i = 0;i < m.length();i++){
x++;
n = n + m[i];
if(m[i] == m[i+1]){
n = n + 'x';
x++;
}
}
if((x % 2) != 0){
n = n + 'x';
}
cout << n;
return 0;
}

If you look at the available overloads of std::string::insert(), you will see that your statement plain.insert(i,'x'); does not match any of them, hence the compiler error. The overloads that takes a single char require either:
an index and a count (you are omitting the count)
an iterator and an optional count
There is, however, a couple of overloads that take just an index and a value, but they require a const char* or a std::string, not a single char.
Also, paired[i]=paired[i]; is a no-op. Except in your case, since paired has a size() of 0 since you never append anything to paired, so actually any access to paired[...] is undefined behavior.
Try this instead:
#include <iostream>
#include <string>
using namespace std;
int main(){
string plain, paired;
cout << "input plaintext(no spaces, lowercase):\n";
cin >> plain;
paired = plain;
for (string::size_type i = 1; i < paired.size(); ++i){
if (paired[i] == paired[i-1]){
paired.insert(i, 1, 'x');
// or: paired.insert(paired.begin()+i, 'x');
// or: paired.insert(i, "x");
// or: paired.insert(i, string{'x'});
// or: paired.insert(paired.begin()+i, {'x'});
++i; // skip the x just inserted
}
}
if (paired.size() % 2 != 0){
paired += 'x';
}
cout << paired << endl;
return 0;
}
Demo

A couple of points
First, Although the string.insert function says it takes an int as its first argument it really wants an iterator in this case.
Second, you are inserting elements into your "plain" string which increases its length and you have plain.length within your loop so you create an infinite loop.
Third, insert inserts BEFORE the index so you need to add 1 to I.
The code below will work for your loop:
Int len = plain.length();
Int count = 0;
for (int i = 0; i < len + count; i++)
{
If (plain[i] == plain[i + 1])
{
plain.insert(plain.begin() + (i +1), 'X');
++count;
}
}
cout << plain;
And as, mentioned below, if you want to handle spaces you can use getline(cin, plain) instead of cin.

Related

std::copy doesn't copy vector in C++

To find all sequences of fixed length which contain only 0 and 1 I use this code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
void print_array(vector<string> arr) {
cout << '[';
int n = arr.size();
for (size_t i = 0; i < n; i++) {
cout << arr[i];
if (i < (n - 1)) {
cout << ", ";
}
}
cout << ']' << endl;
}
vector<string> get_variants(int n) {
vector<string> result = {"0", "1"};
vector<string> temp;
temp.reserve(2);
result.reserve(2);
for (int i=0; i < (n - 1); ++i) {
copy(result.begin(), result.end(), temp.end()); // [1]
for (int j=0; j < result.size(); ++j) {
temp[j] += "0";
result[j] += "1";
}
copy(temp.begin(),temp.end(), result.end());
temp.clear();
}
return result;
}
int main(int argc, char const *argv[]) {
int n;
cin >> n;
vector<string> maybe = get_variants(n);
print_array(maybe);
return 0;
}
But vector temp is empty, before copying in line which I marked [1] and after. So, my program's output was [0111, 1111]. What I'm doing wrong?
A more straightforward way than using std::copy is the use of .insert():
temp.insert(temp.end(), result.begin(), result.end()); //1
...
result.insert(result.end(), temp.begin(), temp.end()); // 2nd copy
You are writing to temp.end() and result.end(). These iterators represent "one past the end", and therefore writing to these iterators is Undefined Behavior.
You seem to be looking for std::back_inserter. This will create an iterator that will insert a new element to your container when it is written through.
std::copy(result.begin(), result.end(), std::back_inserter(temp));
While this answers the posted question, there remain other errors in your code leading to Undefined Behavior.
Trying to compile your program with a C++ compiler will not work, because you include #include <bits/stdc++.h>which is a non tC++ standard compliant header.
You should never include this file.
You are using typical competitive programming stuff, but including all C++ headers and not use them will eat up Compile time for no good reason.
Then, you typedef the typical competitive programming abbreviations. 2 of them, you do not use. Then there is no reason to define them.
I recommend to not do this any longer. And in C++, please use the using statement.
Then, although you want to be fast, you pass arr by value to your print function. This will copy the whole vector.
You assign/compare a lot of int with unsigned int values. This you should not do.
Additionally: Please use meaningful variable names and write comments. The more the better.
Regarding your specific bug. Both std::copy statements use end iterator as target. End is end. It is past the end of the vector. Please use std::back_inserter instead.
Regarding the algorithm. I took a while for me to realize that you basically want to create binary numbers. Nothing else. Unfortunately you translated that in a very complicated way.
Normally, you just would count from 0 to 2^n-1 and then show the data. Thats all. Becuase the numbers may be of arbitraty length, we will use manual addition of digits like in scholl on a peice of paper. Very simple.
Everthing then biols down to some lines of code.
Please see:
#include <iostream>
#include <vector>
int main() {
// Read length of binary number to create and validate input
if (int numberOfDigits{}; (std::cin >> numberOfDigits and numberOfDigits > 0)) {
// Here we will store the binary digits, so 0s or 1s
std::vector<int> digits(numberOfDigits,0);
// Som printing helper
std::cout << '[';
bool printComma{};
// We need to print 2^n possible combinations
for (int i = 0; i < (1 << numberOfDigits); ++i) {
// Print comma, if need
if (printComma) std::cout << ','; printComma = true;
// Print all digits of the binary number
for (const int d : digits) std::cout << d;
// Calculate next binary number
int carry = 0;
for (int index=numberOfDigits -1; index >=0; --index) {
const int sum = digits[index] + ((index == (numberOfDigits - 1)?1:0)) + carry;
carry = sum / 2;
digits[index] = sum % 2;
}
}
std::cout << ']';
}
}
If there should be questions, then I am happy to answer.

How to properly compare strings in c++?

Good night to everyone!
I am trying to compare 2 strings in c++, using the .compare() function. However, the result i see is not what is expected from this function. Take a look please.
#include <iostream>
#include <string>
using namespace std;
class game
{
private:
char mtx [2][2];
int i = 0, j = 0, a = 0;
std::string matrix1;
std::string xis = "xx";
public:
game();
char winner();
};
game::game()
{
for(i = 0; i<2; i++)
{
for (j = 0; j<2; j++)
{
mtx [i][j] = 'x';
}
}
char game::winner()
{
i = j = 0;
for (j=0; j<2; j++)
{
matrix1 = mtx [0][j]; //string recieve the first line of the matrix.
}
a = xis.compare(matrix1);
cout << a<<endl;
}
int main(void) {
velha game;
velha.winner;
}
When I compile the program the a value printed is neither a '0' nor any other integers. It prints #85.
Notes: I've also tried to use <string.h> and strncmp() using a char array instead of std:: string but with no success.
I was trying to create a game class and I did not put here the other methods because they are not relevant). (also, I use Linux Mint to code)
Can anyone help me please in this context?
#include <iostream>
#include <string>
int main(void) {
std::string first, second;
std::cout << "First String: ";
getline(std::cin, first);
std::cout << "Second Line: ";
getline(std::cin, second);
if (first == second)
std::cout << "Same strings.";
else
std::cout << "Different strings.";
return 0;
}
Explanation: Just taken two strings from the user and matches straightforward without using any much complexity, just used a conditional operation.
For string compare and even strcmp the value returned will be the lexicographical comparison of the two strings. The following are the values you should see:
negative if *this appears before the character sequence specified by the argument in lexicographical order
0 if *this and the character sequence specified are equivalent
positive if *this appears after the character sequence specified by the argument in lexicographical order
If you are looking to get the first column of your matrix, do a string comparison on, you would want to do something like:
for(int col = 0; col < 2; col++) {
matrix1.push_back(mtx[0][col]); // This appends that character to the end of your string
}
If you are looking to get the rows you can just do the following:
matrix1 = mtx[0];
// To ensure you have a null terminated string
// Otherwise you will have garbage.
matrix1.replace(matrix1.begin() + 2, matrix1.end(), 1, "\0");
I have ran through the test with comparing that the matrix contains "xx" and ended up receiving 0. However a much easier comparison is to us operator == to simply return a true or false value.

How to parse a user's input and store each individual character as a string

Okay so I'm working a calculator program that takes in a user input(ex. "(3+(4+12))"), and I need to parse the user's input and store it in an array of strings but I am having trouble doing so. My code currently is this
void parseInput(string input) {
vector <string> input_vector;
for(int i = 0; i < input.size(); ++i) {
if(isdigit(input.at(i)) == 0 && isdigit(input.at(i + 1)) == 0) {
++i;
input_vector.push_back((input.at(i) + input.at(i+1)));
}
else {
input_vector.push_back(input.at(i));
}
}
for(int i = 0; i < input_vector.size(); ++i) {
cout << endl << input_vector[i];
}
}
I know my problem is coming from trying to add a char to an vector of strings, but how would I get each char in the string and keep it as a string to store into my vector. Or is there a better way to parse this out??
edit
Okay so what I am having the most trouble with is the problems that come from the 12 splitting up into two separate chars "1 * 2" How would I go about so that it represents 12 and doesn't split it up???
Here is a solution (using c++11):
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
int main() {
std::string const input = "(3+(4+12))";
std::vector<std::string> chars(input.length());
// Maps each character of `input` to `std::string`
// with that character and saves the results in
// corresponding position in `chars` vector:
std::transform(input.cbegin(), input.cend(), chars.begin(),
[](char c) {
// One of the ways to cast `char` to `std::string`:
return std::string(1, c);
});
// To be sure it works properly, it prints
// generated strings:
for (size_t i = 0; i < chars.size(); ++i) {
std::cout << chars[i];
}
std::cout << std::endl;
}
The answer is u need to split the string into tokens, i have given an example which will add 4 to 12, to make it 16, but think that the string does'nt have any brackets, suppose if the user entered 4+12 and u need to add it you can do the following:
char string[10], nstr[10];
int p=0, a=0, b=0, op=0;
cin>>string; // input string
While (string[i]!='+' || string[i]!='-')
{
nstr[p]=string[i]; // copy the contents of string to nstr.
p++;
i++;
}// loop exits if the string[i] reaches to the operator (+/-*).
nstr[p]='\0';
a=atoi(nstr);// convert the string to integer.
op=i;// this will hold the position of array of the operator in the string.
i++;
p=0;
while (string[i]!='\0')
{
nstr[p]=string[i];// this will copy the contents of the string after the operator.
i++;
p++;
}
nstr[p]='\0';
b=atoi(nstr);
if (string[op]=='+')// check what the user want to do. Add/subtract/divide etc.
c=a+b;
else if (string[op]=='-')
c=a-b;
This program is not tested but will work, if not then use the logic in your program, like i did in my program, this will not take 1 and 2 sepratly, instead it will take 4 and 12, you can type more charaters but is limited to long, i used int here to get the return value of atoi(), hope this helps u...

String output gives weird letters

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
string s = "Too many tags";
for(int i = 0; i < s.size(); i++){
if(!(isspace(s[i]))){
s[i] = '#' + s[i];
}
}
cout << s << endl;
return 0;
}
I'm trying to make a program which adds # tag before each letter in the string, but on output I get weird letters.. where is my mistake?
s[i] = '#' + s[i];
modifies the value of an existing character. If you want to add new characters into your string, you should use insert:
s.insert(i, "#");
As Mark Ransom points out, you also need to move one further char through your string to avoid constantly adding "#" before the same letter. You could do this using
s.insert(i++, "#");
Note that you could always take VladimirM's advice and make slightly larger changes to something like
int i=0;
while (i<s.size()) {
if (!isspace(s[i])) {
s.insert(i++, "#");
}
i++;
}
This line:
s[i] = '#' + s[i];
isn't doing what you think it is. s[i] is a char, # is also a char. Adding these together doesn't give you the concatenation of the two characters, it gives you the addition of the integer code of the characters (so 35 for # and the ASCII code for whatever s[i] happens to be).
I add more: I think the simpler way is to use temporary variable otherwise your loop with 'insert' will go to endless loop and will hang:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
string s = "Too many tags";
string res = "";
for(int i = 0; i < s.size(); i++){
if(!(isspace(s[i]))){
res += "#";
}
res += s[i];
}
cout << res << endl;
return 0;
}

Error-correcting loop in C++, find specific chars in a string and flag as bad input

Here is v1.0 of the binary_to_decimal converter I wrote. I want to make several changes as I keep improving the spec. Classes and pointers will be added as well in the future. Just to keep me fresh and well practiced.
Well, I now want to implement an error-correcting loop that will flag any character that is not a 0 or a 1 and ask for input again.
I have been trying something along the line of this code block that worked with an array.
It might be way off but I think I can tweak it. I am still learning 0_0
I want to add something like this:
while ((cin >> strint).get())
{
cin.clear(); //reset the input
while (cin.get() != '\n') //clear all the way to the newline char
continue; //
cout << "Enter zeroes and/or ones only! \n";
}
Here is the final code without the error-correcting loop:
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
const int MAX = 100;
int conv(int z[MAX], int l[MAX], int a);
int main()
{
int zelda[MAX];
int link[MAX];
string strint;
int am;
cout << "Enter a binary number: \n";
(cin >> strint).get(); //add error-correction to only read 0s and 1s.
am = strint.size();
cout << am << " digits entered." << endl;
int i = 0;
int p = 0;
while (i < am)
{
zelda[i] = strint[p] - '0'; //copies the string array elements into the int array; essentially STRING TO INT (the minus FORCES a conversion because it is arithmetic) <---- EXTREMELY CLEVER!
++i;
++p;
}
cout << conv(zelda, link, am);
cin.get();
return 0;
}
int conv(int zelda[MAX], int link[MAX], int length)
{
int sum = 0;
for (int t = 0; t < length; t++)
{
long int h, i;
for (int h = length - 1, i = 0; h >= 0; --h, ++i)
if (zelda[t] == 1)
link[h] = pow(2.0, i);
else
link[h] = 0;
sum += link[t];
}
return sum;
}
thanks guys.
I'm not completely sure of what you're trying to do, but I think what you're wanting is string::find_first_not_of. There's an example included in that link. You could have something like: myString.find_first_not_of("01");
If the return value is string::npos, then there are no characters in the string other than 1 or 0, therefore it's valid. If the return value is anything else, then prompt again for valid input and continue looping until the input's valid.