I am struggling with this piece of code :
std::queue<char> output_queue;
std::string output_string
// put stuff into output_queue
while (!output_queue.empty())
{
output_string.insert(0,(output_queue.front()));
output_queue.pop();
}
I somehow can't do this since std::queue<char>::front() will return a char& and I can't put this into std::string.
You're missing an argument to make insert insert a character. You need to specify how many of that character:
output_string.insert(0, 1, output_queue.front());
If you want to make it easier on yourself, you can also use std::deque instead of std::queue and replace it with this:
std::deque<char> output_queue;
//fill output_queue in same way, but use push/pop_front/back instead of push/pop
std::string output_string(output_queue.begin(), output_queue.end());
output_queue.clear();
It would nearly be the same thing as now because your queue is actually using a std::deque by default under the hood. The deque, however, supports iterators, which makes this possible without ugly code that relies on the underlying storage.
You may use
output_string += (output_queue.front());
and then (after while) reverse it
Related
In C++ creating and manipulating a mutable stack of characters is rather simple. I use a built-in standard data type (std::string), use a push and pop fuctions that comes with it and can directly print the results. None of this requires creating additional classes or functions.
#include <iostream>
int main()
{
std::string path {};
path.push_back('L');
path.push_back('R');
path.pop_back();
std::cout << path;
}
Produces:
L
What is Kotlin for C++ push_back() and pop_back() as a stack of characters?
The question is not how can I implement these as member functions in Kotlin.
C++ Shell code
Strings are immutable, so you won't find an exact equivalent.
While StringBuilder is generally considered to be a decent string buffer type, deleteCharAt copies the entire backing array.
You can use setLength for this purpose. Note that, as with std::string, this does not do anything more than modify the internal length of the string buffer:
val string = StringBuilder("Hello")
string.append(", world!")
string.setLength(string.length - 1)
Alternatively, take the more functional approach and work with immutable values:
var string = "Hello"
string += ", world!"
string = string.dropLast(1)
As already stated by other answerers/commenters, if what you really want is a stack or deque, see Deque and ArrayDeque (seeing as you did not mention std::stack or std::deque in your question, I do not believe this to be the case; not to mention that a stack of characters isn't inherently very useful.)
Taking OP's comment into account, this should be an idiomatic solution:
enum class Move {
Left, Right, Forward
}
val moves = ArrayDeque<Move>()
// Push a move:
moves.push(Move.Left)
// Pop a move:
val lastMove = moves.pop()
See also Why should I use Deque over Stack? for an explanation of Java's unfortunate history.
I'm not really sure if this is what you mean, but Kotlin has a dropLast(param: number of characters to drop) function which returns a string without the number of characters you did want to remove. Link: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/drop-last.html
If you are looking for a stack data structure, you might take a look at the Stack and Deque data structures.
https://chercher.tech/kotlin/deque-kotlin, https://chercher.tech/kotlin/stack-kotlin
I am trying to store only the alpha characters of a string 's' into my deque of characters using std::copy_if but is giving a crash during the copy statement.
std::string s{"Love"};
std::deque<char> dr;
std::deque<char>::reverse_iterator itr =std::copy_if(s.cbegin(),s.cend (),dr.rbegin(),[](char c){return isalpha(c);});
program.exe stopped working
The likely problem is that your deque isn't big enough to hold the characters you are copying. std::copy_if does not resize the deque (how could it since it only has an iterator to work with)? The usual answer is to use a special kind of iterator called a std::front_insert_iterator which will call push_front to grow the deque when elements are copied. You can create a std::front_insert_iterator with the function std::front_inserter. Like this
auto itr =
std::copy_if(s.cbegin(), s.cend(),
std::front_inserter(dr),
[](char c){return isalpha(c);});
PS there is also a corresponding std::back_insert_iterator and function std::back_inserter which are more commonly used. But std::front_inserter is appropriate for your case since it seems you want to reverse the sequence of characters when you insert them into the deque.
It started with converting a vector<string> to vector<double>. I use gcc without C++11 so I could not use this approach. After having a look at the algorithm template of transpose I tried to use the template instead, but there is a bug for std::stod used inside the template (for gcc 4.x which results in ‘stod’ is not a member of ‘std’) So why not write it yourself and I use while-loop with stringstream (expensive?):
int i = 0;
while (svec.begin() != svec.end()) {
stringstream(*svec.begin())>> dvec[i] ;//svec: strings, dvec: doubles
//dvec[i] = std::stod(*svec.begin());
++svec.begin(); i++;
}
Unfortunately I get: double free or corruption (out): 0x00007f4788000ba0 ***
I think the issue here is that
++svec.begin();
doesn't work the way you think it does. This doesn't advance forward the beginning of the vector. Instead, it gets a (temporary) iterator to the beginning of the vector, then increments that. As a result, you'll be stuck in an infinite loop. To fix this, use a more traditional "loop over a container" loop either by using a range-based for loop or just counting up the indices.
I also noticed that you're writing into dvec by index. Without seeing the code to initialize dvec, I can't be sure of whether this is safe, since if you didn't already resize the vector this will write off the end and lead to undefined behavior. Even if you did set it up properly, because of the broken loop, my guess is that this eventually writes off the end of the vector and is what directly triggers the issue.
First of all, let's clear up some confusion:
std::stod is a C++11 function, so if you do not use C++11, then it is not a "bug" if it cannot be found.
You mean std::transform and not transpose, don't you?
You may very well use std::transform without C++11 and without std::stod. Unfortunately you don't show the code with which you tried.
So why not write it yourself and I use while-loop with stringstream
Yes, why not?
(expensive?):
Measure it :)
But it's unlikely you'll notice a difference.
int i = 0;
while (svec.begin() != svec.end()) {
The loop condition does not make sense. begin() and end() do not change. This line effectively reads as "do this stuff as long as the vector does not become empty".
stringstream(*svec.begin())>> dvec[i] ;//svec: strings, dvec: doubles
//dvec[i] = std::stod(*svec.begin());
++svec.begin(); i++;
}
I'd say you are overthinking this. The crash you get may come from the fact that you access dvec[i] while dvec is still empty, and you never actually add elements to it. That's undefined behaviour.
It's really as simple as "loop through string vector, use a stringstream on each element to get a double value, and add that value to the result vector", expressed in C++03 as:
// loop through string vector
for (std::vector<std::string>::const_iterator iter = svec.begin(); iter != svec.end(); ++iter)
{
std::string const& element = *iter;
// use a stringstream to get a double value:
std::istringstream is(element);
double result;
is >> result;
// add the double value to the result vector:
dvec.push_back(result);
}
If you don't have stod (which was added in C++11) you can use strtod and apply it to a C-string that corresponds to the C++ string that you have. Copying from the approach that you linked to and making that change (and cleaning up the formatting):
std::vector<double> convertStringVectortoDoubleVector(
const std::vector<std::string>& stringVector){
std::vector<double> doubleVector(stringVector.size());
std::transform(stringVector.begin(), stringVector.end(),
doubleVector.begin(), [](const std::string& val)
{
return strtod(val.c_str(), 0);
});
return doubleVector;
}
Note that if the code hasn't already ensured that each string holds a valid representation of a floating-point value you'll have to add code to check whether strtod succeeded.
I am using visual studio 2012 (windows) and I am trying to write an efficient c++ function to remove some words from a big vector of strings.
I am using stl algorithms. I am a c++ beginner so I am not sure that it is the best way to proceed. This is what I have did :
#include <algorithm>
#include <unordered_set>
using std::vector;
vector<std::string> stripWords(vector<std::string>& input,
std::tr1::unordered_set<std::string>& toRemove){
input.erase(
remove_if(input.begin(), input.end(),
[&toRemove](std::string x) -> bool {
return toRemove.find(x) != toRemove.end();
}));
return input;
}
But this don't work, It doesn't loop over all input vector.
This how I test my code:
vector<std::string> in_tokens;
in_tokens.push_back("removeme");
in_tokens.push_back("keep");
in_tokens.push_back("removeme1");
in_tokens.push_back("removeme1");
std::tr1::unordered_set<std::string> words;
words.insert("removeme");
words.insert("removeme1");
stripWords(in_tokens,words);
You need the two-argument form of erase. Don't outsmart yourself and write it on separate lines:
auto it = std::remove_if(input.begin(), input.end(),
[&toRemove](std::string x) -> bool
{ return toRemove.find(x) != toRemove.end(); });
input.erase(it, input.end()); // erases an entire range
Your approach using std::remove_if() is nearly the correct approach but it erases just one element. You need to use the two argument version of erase():
input.erase(
remove_if(input.begin(), input.end(),
[&toRemove](std::string x) -> bool {
return toRemove.find(x) != toRemove.end();
}), input.end());
std::remove_if() reorders the elements such that the kept elements are in the front of the sequence. It returns an iterator it to the first position which is to be considered the new end of the sequence, i.e., you need to erase the range [it, input.end()).
You've already gotten a couple of answers about how to this correctly.
Now, the question is whether you can make it substantially more efficient. The answer to that will depend on another question: do you care about the order of the strings in the vector?
If you can rearrange the strings in the vector without causing a problem, then you can make the removal substantially more efficient.
Instead of removing strings from the middle of the vector (which requires moving all the other strings over to fill in the hole) you can swap all the unwanted strings to the end of the vector, then remove them.
Especially if you're only removing a few strings from near the beginning of a large vector, this can improve efficiency a lot. Just for example, let's assume a string you want to remove is followed by 1000 other strings. With this, you end up swapping only two strings, then erasing the last one (which is fast). With your current method, you end up moving 1000 strings just to remove one.
Better still, even with fairly old compilers, you can expect swapping strings to be quite fast as a rule--typically faster than moving them would be (unless your compiler is new enough to support move assignment).
The STL provides std::copy but it is tricky to use it with output containers with fixed sizes as there is no bounds checking on the output iterator
So I invented my own, something like below
template<class InputIterator , class OutputIterator>
void safecopy( InputIterator srcStart , InputIterator srcEnd ,
OutputIterator destStart , OutputIterator destEnd )
{
while ( srcStart != srcEnd && destStart != destEnd )
{
*destStart = *srcStart;
++srcStart;
++destStart;
}
}
int main()
{
std::istream_iterator<char> begin(std::cin), end;
char buffer[3];
safecopy( begin, end, buffer, buffer + 3 );
return 0;
}
Questions:
Am I reinventing the wheel here ? Is there an stl algorithm to do what I want.
Are there any deficiencies in my safecopy , does it work for everything std::copy works for ?
Let me promote my comment to an answer, so I have a bit more space.
First off, your implementation looks good.
Now, why isn't this in the standard? (The new standard adds std::copy_n, but that does something different, too.*)
Think about it like this: strncopy isn't really a "good" idea; it's just not a terrible idea. Since C doesn't have any dynamic data structures, a length-checked version is the best you can do.
But in C++ this doesn't fit nicely into the general idea of dynamic containers: You would rarely want to overwrite some elements, but rather create all elements, which you do by std::copy plus std::inserter. strncpy is a crutch which requires you to preallocate the destination data structure, but in C++ we can do a lot better than this. With dynamic containers, iterators and inserters, we can copy anything without needing to worry about allocation.
In other words, any abstract algorithm that you might conceive should have a better, more specific method of obtaining iterators and iterator ranges (think remove/erase); it is rarely the case that the ultimate goal of an algorithm is to only produce an output range that is constrained by some other destination range.
In summary: Yes, you can do that, but you can probably do better.
*) Though copy_n plus min of source and destination size could be used to create a bounded copy.
I would make one minor adjustment to your implementation. Give it a return value. Either the final output iterator, or an integer indicating the number of elements copied.
The main use case I can see for your function would be reading fixed size chunks from an input stream and you don't know when it will end. If it does end, you need some way of knowing that, and you need to know how many elements were copied before it actually ended. If you know how many elements were copied, and it didn't meet or exceed the size of the output range, that's how you can know it ended.
Yes. You're reinventing the wheel again!
For example, you could use std::copy as:
std::copy(s.begin(), s.begin() + 3 , buffer);
instead of this,
safecopy(s.begin(), s.end() , buffer, buffer + 3);
The usage of std::copy in this way is NOT less safer than your safecopy.
Or even better is std::copy_n which comes with C++11:
std::copy_n(s.begin(), 3, buffer);
This would work even if the argument is not random access iterator.
As for when you use std::vector<char>, you could use its constructor directly as:
std::vector<char> v(s.begin(), s.end());
No need of even std::copy.