A CPP int to string in a statement question - c++

I have to write something like
q.push_back(q1); ... to ... q.push_back(q100);
I am writing this as
for (int i = 1; i <= 100; i++) {
try {
std::string s = boost::lexical_cast<std::string > (i);
"q.push_back(q" + s + ");";
} catch (boost::bad_lexical_cast &) {
std::cout << "Some error message \n";
}
}
It compiles (no syntax errors) but does not work. I don't know how to mix cpp statements and strings to make a compound statement.
Any help here would be highly appreciated. Thanks!

How about:
for (int i = 1; i <= 100; i++)
{
std::cout << "q.push_back(q" << i << ");\n";
}

If you're using std::string (which it looks like you are) try s.append(str);

std::ostringstream os;
for( int i = 1; i < 100; ++i)
{
os << "s.push_back( q" << i << "); ";
}
std::string result = os.str();
// Do what you need with result
Your output string was put inside the for loop, so at each loop the string is initialized, the content generated in the previous loop was lost.

You aren't telling it where to put that string, it just creates a temporary. Try appending to s.
std::string s = "q.push_back(q";
s.append(boost::lexical_cast<std::string > (i));
s.append(");");
It isn't clear what you expect to do with the string. If you are printing it to std::cout, then your error message will get mixed in with the results. You should use std::cerr instead.
std::cerr << "Some error message" << std::endl;

The variables q1, q2, ..., q100 should have been an array in the first place.

If my understanding of what you are trying to do is correct, then you basically want to automatically generate some code. For that, people normally use simple macro definitions...
You can just define a macro that takes your respective integer from the for loop as a parameter and expands to the code you require with it...
Take a quick look at [ http://en.wikipedia.org/wiki/C_preprocessor#Token_concatenation ]. You can use ## in macros to glue things together, so you could use something like the following, inside a for loop for i:
#define MY_PUSH(vector, i) vector.push_back(q##i);
But as people have suggested, it might have been better to use an array of variables in the first place, as macros are basically evil for anything other than raw code generation tools...

Related

Questions regarding efficiency

So while working through a course on Udemy over C++ one of the challenges was to check a string to see whether it was a palindrome or not. I completed the task successfully but went about it a different way than the instructor. I understand there are a multitude of ways to complete a task but I am wondering which is more efficient and why? It may seem stupid to be wondering about this while reteaching myself coding but I feel this is something I should be keeping in mind.
//Instructors code//
# include<iostream>
using namespace std;
/*program for reverse a string and check a string is a palidrome
*/
int main()
{
string str="MADAM";
string rev="";
int len=(int)str.length();
rev.resize(len);
for(int i=0, j=len-1; i<len; i++, j--)
{
rev[i]=str[j];
}
rev[len]='\0';
if(str.compare(rev)==0)
cout<<"palindrome"<<endl;
else
cout<<"not a pallindrome"<<endl;
return 0;
}
My Approach
#include <iostream>
using namespace std;
int main(){
string str1="test";
// cout << "Enter a string to check if it is a Palindrome: ";
// getline(cin,str1);
string str2;
string::reverse_iterator it;
for(it=str1.rbegin(); it!= str1.rend(); it++)
{
str2.push_back(*it);
}
if(!str1.compare(str2))
cout << "\nPalindrome";
else
cout << "\nNot a Palindrome";
return 0;
}
Thank you in advance.
In theory the code from your instructor is more efficient, but both examples have issues.
With your instructors code the main issue is the use of
int len=(int)str.length();
In this example, it is okay because we know the size of the string will fit in a int, but if you were getting a string from an outside source, this could be a problem. A std::string using an unsigned integer type to store the size of the string and that means you can have a string who's size is larger then what can fit in an int. If that were to happen, then code is not going to work correctly.
With your code you a avoid all that, which is great, but you also leave some performance on the table. In theory your code of
for(it=str1.rbegin(); it!= str1.rend(); it++)
{
str2.push_back(*it);
}
is going to cause str2 to have multiple buffer allocations and copies from the old buffer to the new buffer as it grows. This is a lot of extra work that you don't need to do since you already know how much space you need to allocate. Having
str2.reserve(str1.size() + 1);
before the loop pre-allocates all the space you need so you don't have those potential performance hits.
Then we come to the fact that both of your examples are using a second string. You don't need another string to check for a palindrome. What you can do is just check and see if the first and last characters are the same, and if they are move on to the first+1 and last-1 character and so on until you reach the middle or they don't match. You can do that using a construct like
bool is_palindrome = true;
for (auto start = str.begin(), end = str.end() - 1;
start < end && is_palindrome;
++start, --end)
{
if (*start != *end)
is_palindrom = false
}
if (is_palindrome)
std::cout << "palindrome\n";
else
std::cout << "not a pallindrome\n";
The simplest and most efficient way (no copying required) would be something like this:
inline bool is_palindrome(const std::string& u) {
return std::equal(u.begin(), std::next(u.begin(), u.length() / 2), u.rbegin());
}
I would say that both are almost the same, but as mentioned in the comments, the line:
str2.push_back(*it);
Is actually very inefficient, since std::string may copy the existing string to a new location in the memory, and then append the next char to the string, which is wasteful.
But I am wondering, why to create the copy in the first place?
It is very simple to run both from start to end, and from end to start to check it out, meaning:
bool is_polindrom(const std::string& str)
{
for (std::size_t idx = 0, len = str.length(); idx < len / 2; ++idx)
{
if (str[idx] != str[len - 1 - idx])
{
return false;
}
}
return true;
}
Running the code with:
int main()
{
const std::string right1 = "MADAM";
const std::string right2 = "MAAM";
const std::string wrong1 = "MADAAM";
const std::string wrong2 = "MEDAM";
std::cout << "MADAM result is: " << is_polindrom(right1) << std::endl;
std::cout << "MAAM result is: " << is_polindrom(right2) << std::endl;
std::cout << "MADAAM result is: " << is_polindrom(wrong1) << std::endl;
std::cout << "MEDAM result is: " << is_polindrom(wrong2) << std::endl;
}
Will yield:
MADAM result is: 1
MAAM result is: 1
MADAAM result is: 0
MEDAM result is: 0
You don't need extra memory in this case, since it is possible to iterate over a string from the end to the beginning, and you need to run on it exactly once (and notice that I stop when idx >= len / 2 since you don't really need to check each letter twice!).

Why does my function not switch the first character with the last one of my string?

I picked up a challenge on r/dailyprogrammer on reddit which wants me to match a necklace and put the last letter at the beginning of a string. I've considered using nested for loops for this but this has made me really confused.
Instead I chose the way of replacing the last with the first character in an if-statement. But I am not getting my desired output with it, though I've tried everything what comes into my mind.
I used even std::swap() which didn't lead me to success either.
Here's the code:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string same_necklace(string& sInput, string& sOutput)
{
for (string::size_type i = 0; i < sInput.size(); i++)
{
if (sInput[i] == sInput.size())
{
sInput[0] = sInput[sInput.size()];
}
}
for (string::size_type j = 0; j < sOutput.size(); j++)
{
if (sOutput[j] == sOutput.size() - 1)
{
sOutput[0] = sOutput[sOutput.size()];
}
}
return sInput, sOutput;
}
int main()
{
system("color 2");
string sName{ "" };
string sExpectedOutput{ "" };
cout << "Enter a name: ";
cin >> sName;
cout << "Enter expected output: ";
cin >> sExpectedOutput;
cout << "Result: " << same_necklace(sName , sExpectedOutput) << endl;
return 0;
}
And of course the link to my challenge (don't worry, it's just Reddit!):
https://www.reddit.com/r/dailyprogrammer/comments/ffxabb/20200309_challenge_383_easy_necklace_matching/
While I am waiting (hopefully) for a nice response, I will keep on trying to solve my problem.
In your if you compare the value of the current index (inside the loop) with the size of the string. Those are two unrelated things.
Also, you use a loop though you only want to do something on a single, previously known index.
for (string::size_type i = 0; i < sInput.size(); i++)
{
if (sInput[i] == sInput.size())
{
sInput[0] = sInput[sInput.size()];
}
}
You could change the if condition like this to achieve your goal:
if (i == sInput.size()-1) /* size as the index is one too high to be legal */
But what is sufficient and more elegant is to drop the if and the loop. completely
/* no loop for (string::size_type i = 0; i < sInput.size(); i++)
{ */
/* no if (sInput[i] == sInput.size())
{*/
sInput[0] = sInput[sInput.size()-1]; /* fix the index*/
/* }
} */
I.e.
sInput[0] = sInput[sInput.size()-1]; /* fix the index*/
Same for he output, though you got the correct index already correct there.
This is not intended to solve the challenge which you linked externally,
if you want that you need to describe the challenge completely and directly here.
I.e. this only fixes your code, according to the desription you provide here in the body of your question,
"put the last letter at the beginning of a string".
It does not "switch" or swap first and last. If you want that please find the code you recently wrote (surely, during your quest for learning programming) which swaps the value of two variables. Adapt that code to the two indexes (first and last, 0 and size-1) and it will do the swapping.
So much for the loops and ifs, but there is more wrong in your code.
This
return sInput, sOutput;
does not do what you expect. Read up on the , operator, the comma-operator.
Its result is the second of the two expressions, while the first one is only valuated for side effects.
This means that this
cout << "Result: " << same_necklace(sName , sExpectedOutput) << endl;
will only output the modified sExpectedOutput.
If you want to output both, the modified input and the modified output, then you can simply
cout << "Result: " << sName << " " << sExpectedOutput << endl;
because both have been given as reference to the function and hence both contain the changes the function made.
This also might not answer the challenge, but it explains your misunderstandings and you will be able to adapt to the challenge now.
You have not understand the problem i guess.
Here you need to compare two strings that can be made from neckless characters.
Lets say you have neckless four latters word is nose.
Combination is possible
1)nose
2)osen
3)seno
4)enos
your function (same_necklace) should be able to tell that these strings are belongs to same necklace
if you give any two strings as inputs to your function same_necklace
your function should return true.
if you give one input string from above group and second input string from other random word thats not belongs to above group, your function should return false.
In that sense, you just take your first string as neckless string and compare other string with all possible combination of first string.
just move move you first latter of first input string to end and then compare each resulting string to second input string.
below is the function which you can use
void swap_character(string &test)
{
int length = test.length();
test.insert(length, 1, test[0]);
test.erase(0, 1);
}

C++ string number of occurence

This is my first time asking something on stackoverflow, so I'm sorry if I fail in any aspect of building the topic etc...
So I'm a newbie at C++, I'm still at the beginning. I'm using a guide someone recommended me, and I'm stuck in a exercise which is about char and strings.
It's the following: They ask me to create a function that says the number of times that a certain word was repeated on a string.
I'll leave my code below for someone who can help me, if possible dont give me an obvious response like the code and then I just copy paste it. If you can just give me some hints on how to do it, I want to try to solve it on my own. Have a good night everyone.
#include <iostream>
#include <string.h>
#define MAX 50
using namespace std;
int times_occ(string s, string k) {
int count = 0, i = 0;
char word[sizeof(s)];
// while (s[i] == k[i])
// {
// i++;
// if (s[i] == '\0')
// {
// break;
// }
// }
for (i = 0; i <= sizeof(s); i++) {
if (s[i] == ' ' || s[i] == '\0') {
break;
}
word[i] = s[i];
}
word[i] = '\0';
for (i = 0; i <= sizeof(k); i++) {
if (word) {
if (k[i] == word[a]) {
a++;
count++;
}
}
}
cout << word << endl;
cout << count << endl; // this was supposed to count the number of times
// certain word was said in a string.
return count;
}
int main() {
char phrase[MAX];
char phrase1[MAX];
cin.getline(phrase, MAX);
cin.getline(phrase, MAX);
times_occ(phrase, phrase1);
}
Okay, first of all, the way you've used sizeof isn't really valid.
sizeof won't tell you the length of a string. For that, you want std::string::size() instead.
In this case, std::string is an object of some class, and sizeof will tell you the size of an object of that class. Every object of that type will yield the same size, regardless of the length of the string.
For example, consider code like this:
std::string foo("123456789");
std::string bar("12345");
std::cout << sizeof(foo) << "\t" << foo.size() << "\n";
std::cout << sizeof(bar) << "\t" << bar.size() << "\n";
When I run this, I get output like this:
8 9
8 5
So on this implementation, sizeof(string) is always 8, but some_string.size() tells us the actual length of the string.
So, that should at least be enough to get you started moving in a useful direction.
As #JerryCoffin mentioned, your word array has an invalid size. But - I want to make a more fundamental point:
Your code has two loops and a bunch of variables with arbitrary names. How should I know what's the difference between s and k? I even get k and i mixed up in the sense of forgetting that k is a string, not an integer. That kind of code difficult to read, and to debug. And we are a bit lazy and don't like debugging other people's code...
I suggest that you:
Have a very clear idea what your loops do, or what the different parts of your function do.
Create small self-contained functions - no more than one loop each please! - for each of those parts.
Use meaningful names for each function's parameters and for the local variables.
And then, if your program doesn't work - try debugging one function at a time.

How to use a variable int within a filename string in C++/openFrameworks

I am a total new guy to C++, as I am used to Processing, but for a project I have to make something in openFrameworks, a C++ framework. I am trying to load a movie each time a condition is triggered. I generate a random number, and then the videoplayer should load the movie that contains that number. Something like this:
else if ( myByte > 130 ){
float ranNumb = ofRandom(1, 5);
int rounded = (int)ranNumb;
cout << rounded << "\n";
myPlayer.loadMovie("movies/testMovie_", rounded,".mp4");
}
Obviously the last line does not work in C++/OpenFrameworks. I am used to Processing and there I would just use the "+" operator to combine the string with the rounded variable. How would I go about doing this?
openFrameworks provides the ofToString() function that will convert your int into a string. You can use it like this:
myPlayer.loadMovie("movies/testMovie_" + ofToString(rounded) + ".mp4");
Documentation: ofToString
Hopefully C++11 is available, so you can do:
myPlayer.loadMovie(std::string("movies/testMovie_") + std::to_string(rounded) + ".mp4");
I find std::stringstream useful.
std::string pfn; // derived path file name
{
std::stringstream ss;
ss << "movies/testMovie_" << rounded;
pfn = ss.str();
}
cout << pfn << "\n";
myPlayer.loadMovie(pfn);

'Replace' a char with an int in a string

At first this seemed easy to do but I was mistaken. I want to 'replace' a char (a variable) in a string with a int (value). But how?
I tried replace() because I'm working with a string and it worked but it will not work if I wish to change the value of the variable again to another
value because then the original variable will not be found. I have been struggling with this for the passed 2 days. Any help will be much appreciated on how to do this.
changeVar(string startingExpr, char var, int val)
{
for(int i = 0; i < startingExpr.length(); i++)
{
if(startingExpr[i] == var)
{
cout << "I found x! Now to replace it!";
startingExpr[i] = val; //'Replace' x with 5, but x but how?
}
}
}
Your help on this one will be much appreciated.
J
If you want to be able to replace the "variable" by the "value" as many times as you want, you should keep a copy of the original string and do the replacement from there only.
Another option is to undo the replacement (replace the value by the variable) and redo with another value, provided the undo can be done unambiguously.
I am sorry to hear this problem wasted your more than 2 days. You shouldcarefully read a basic C++ textbook. As your problem is a very basic one. If you understand the arguments passing for function, you will sort this out!
More specific, you function is not wrong, but just did not deliver the results you want. Because your function using argument, which will make a copy of argument startingExpr inside the function body, when you make replacement using "startingExpr[i] = val", the replacement is happened on the copy of startingExpr (which is a local variable just visible inside the function), your original startingExpr does change at all.
The solution is very simple, change argument passing with its reference, just add &, now the declaration your function should be: "changeVar(string startingExpr, char var, int val)"
Try the following code, which will demonstrate my explanation:
#include <iostream>
#include <string>
using namespace std;
//the original function which was reported had problem
// This because the function using parameter not reference
void changeVar(string startingExpr, char var, int val)
{
for(int i = 0; i < startingExpr.length(); i++)
{
if(startingExpr[i] == var)
{
cout << "I found x! Now to replace it!(But the replace is happend inside the function, the original string is not changed!)"<<endl;
startingExpr[i] = val; //'Replace' x with 5, but x but how?
}
}
}
// updating using the reference
//void changeVar(string & startingExpr, char var, int val)
void changeVar_refe(string & startingExpr, char var, int val)
{
for(int i = 0; i < startingExpr.length(); i++)
{
if(startingExpr[i] == var)
{
cout << "I found x! Now to replace it!(Now using reference, the replace is happend inside the original string, which will be changed!)"<<endl;
startingExpr[i] = val; //'Replace' x with 5, but x but how?
}
}
}
int main()
{
//lets test the original function
string my_name="Hi there, I am C++ taoism .";
cout<<"The original string is: "<<my_name<<endl;
//lets change a to A
changeVar(my_name,'a',65);
cout<<"The changed string is: "<<my_name<<endl;
cout<<endl;
cout<<"Using the reference to test ... "<<endl;
cout<<endl;
cout<<"The original string is: "<<my_name<<endl;
//lets change a to A
changeVar_refe(my_name,'a',65);
cout<<"The changed string is: "<<my_name<<endl;
//cout <<"Char A is int 65:"<<int('A')<<endl;
}
Your mistake is to assign the number that is different from the ASCII character represntation. In ASCII table characters '0', '1' .. '9' goes one after another. So you can rewrite your code as:
startingExpr[i] = '0' + val;
But please aware that this is good for one character case only. If you need to replace multiple chars then your solution without need for a function is that:
#include <iostream>
#include <string>
int
main()
{
std::string a("SomeVar1"), b("SomeVar356");
std::string::size_type index = std::string::npos;
std::cout << "Before: " << a << std::endl;
if ((index = a.rfind("1")) != std::string::npos)
a.replace(index, 1, std::to_string(2));
std::cout << "After: " << a << std::endl;
std::cout << "Before: " << b << std::endl;
if ((index = b.rfind("356")) != std::string::npos)
b.replace(index, 3, std::to_string(673));
std::cout << "After: " << b << std::endl;
return 0;
}
This is slightly optimized since it is using rfind (search from the end of the string).
P.S. As the comments suggested - you can use std::replace with reverse iterators and lambda for condition. Since it is available in C++11 I wrote a small example in universal style.