I keep getting the runtime error double free or corruption (!prev). I've spent a while trying things out, and I think I can come up with smaller reproducible example.
This code produces a similar "double free" error. What's going on here? I thought set::erase increments the iterator.
#include <iostream>
#include <set>
#include <string>
int main() {
std::set<int> tmp = {1,2,3};
for(auto num = tmp.begin(); num != tmp.end(); ) {
if(true) {
std::cout << "removing...\n";
tmp.erase(num);
}
}
return 0;
}
I thought set::erase increments the iterator.
It does not increment the iterator. It returns the next iterator. After erasing, the iterator num is invalidated. The valid code looks like below.
for(auto num = tmp.begin(); num != tmp.end(); ) {
if(true) {
std::cout << "removing...\n";
num = tmp.erase(num);
}
}
Related
Is there an elegant way in C++ 11 to get the item from a std::vector of doubles which is closest to a certain value?
Code:
#include <iostream>
#include <vector>
double GetClosest(const std::vector<double>& vec, double value) {
// How to get the item closest to "value" from the items in vec. Vec is assumed to be sorted.
}
int main() {
std::vector<double> my_doubles_vec;
my_doubles_vec.push_back(101480.76915103197);
my_doubles_vec.push_back(101480.85708367825);
my_doubles_vec.push_back(101480.93293087184);
my_doubles_vec.push_back(101481.0027936101);
my_doubles_vec.push_back(101481.5625);
my_doubles_vec.push_back(101481.5626);
std::cout.precision(17);
std::cout << GetClosest(my_doubles_vec, 101480.76915103201) << std::endl; // Should output "101480.76915103197"
std::cout << GetClosest(my_doubles_vec, 101480.93293086279) << std::endl; // Should output "101480.93293087184"
std::cout << GetClosest(my_doubles_vec, 101481.5625) << std::endl; // Should output "101481.5625"
return 0;
}
Since its a std::vector of doubles, I think precision comes into play? Or can the logic be made in such a way that one doesn't need to bother about precision?
You could use std::partition_point, std::lower_bound or std::upper_bound on the sorted range.
Example:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if(vec.empty()) throw std::runtime_error("no elements");
// partition_point is the most generic of the three:
auto it = std::partition_point(vec.begin(), vec.end(), [value](double v) {
return v < value;
});
// or auto it = std::lower_bound(vec.begin(), vec.end(), value);
// or auto it = std::upper_bound(vec.begin(), vec.end(), value);
if(it == vec.end()) --it; // value larger than the largest in the vector
else if( it != vec.begin()) { // value not less than first
// check which one of the two around the partition point that is closest
if(std::abs(*std::prev(it) - value) < std::abs(*it - value)) --it;
}
return *it;
}
Since the vector is sorted, you could try something like this:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if (vec.empty()) throw std::invalid_argument("vector cant be empty");
if (vec.size() == 1) return vec[0];
auto iter = std::find_if(vec.begin(), vec.end(),
[=](double d){ return d >= value; }
);
if (iter == vec.begin()) return vec.front();
if (iter == vec.end()) return vec.back();
if (std::abs(value - *(iter-1)) < std::abs(value - *iter)) --iter;
return *iter;
}
I am reading text from a text file and need to know the number of characters in the file in total. I thought this should work but it always seems to be overcounting. For example I typed this into my text file:
thisisatestthisisa
thisisa
And the program returned a total of 32.
#include <iostream>
#include <fstream>
#include <string>
#include <ostream>
using namespace std;
int main() {
fstream inFile;
string inputString;
inFile.open("text.txt", ios::in);
unsigned int total = 0;
if (inFile) {
while (inFile)
{
getline(inFile, inputString);
unsigned int tempStringLength = inputString.length();
total += tempStringLength;
}
cout << "total is: " << total << endl;
}
else {
cerr << "Unable to open file text.txt";
exit(1);
}
return 0;
}
You are double-counting the last line in the file.
Because you are using while(inFile) instead of while(getline(inFile, inputString)) the stream's state is not invalidated until the call to getline(...):
Walking through the loop will make this obvious:
Iteration 1:
unsigned int total = 0;
//...
while (inFile) //True
{
getline(inFile, inputString); //inFile: True, inputString: thisisatestthisisa
unsigned int tempStringLength = inputString.length(); //18
total += tempStringLength; //18
}
//...
Iteration 2:
//...
while (inFile) //True
{
getline(inFile, inputString); //inFile: True, inputString: thisisa
unsigned int tempStringLength = inputString.length(); //7
total += tempStringLength; //25
}
//...
Iteration 3:
//...
while (inFile) //True
{
getline(inFile, inputString); //inFile: EOF, inputString: thisisa (not modified)
unsigned int tempStringLength = inputString.length(); //7
total += tempStringLength; //32
}
//...
inFile now returns false because the EOF was reached and your loop terminates. Printing 32 as the length.
Long story short: Don't use the file state as a loop terminator. Use the actual read, either getline or operator>> depending on the situation.
I have made a function for my program that reads from a text file, adds content to a vector and then search in that vector. The Problem is that even if the file is empty it shows that it found something, on the other side if i change return value to 0 it does not give results at all!
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;
vector<string> contacts;
//This function returns at what index the name is found
int searchContact(string contactToSearch)
{
string entry;
ifstream input;
input.open("contacts.txt");
while (input.good())
{
while (getline(input, entry))
{
contacts.push_back(entry);
}
input.close();
}
for(int i = 0; i < contacts.size(); i++)
{
if(contactToSearch == contacts[i])
{
//Found => Returning index rest of program can see index
return i;
}
}
return 1;
}
I have just refactored your code a little. Further improvements are possible, but to begin with
1) You dont need a while for input.good()
2) You were trying to return 0 and 1 which are indeed valid positions where the string could have been present in the vector
All these aside, I still think your code might not properly populated the array The reasons for this maybe :- case sensitive comparison, reading incorrect file, binary file.. etc..
Here is a refactored code that you could use
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;
void readContacts(const string &fileName inputFileName, vector<string> &contacts){
string entry;
ifstream input;
input.open(inputFileName);
if (input.good())
{
while (getline(input, entry))
contacts.push_back(entry);
input.close();
}
}
int searchContact(const string &contactToSearch, vector<string> &contacts)
{
for (int i = 0; i < contacts.size(); i++)
{
if (contactToSearch == contacts[i])
return i;
}
return -1;
}
int main(){
vector<string> contacts;
// This needs to be filled in with the contact name u want to search
string contactToSearch;
readContacts("contacts.txt", contacts);
int index = searchContact(contactToSearch, contacts)
if (index != -1)
cout << "Found Contact " << contactToSearch" at location " << index << endl;
else
cout << "Could Not find contact " << contactToSearch << endl;
}
How to execute the body of the loop for every member of some type? I know I could repeat the body of the loop for the maxval after the loop, but it would be duplicating code which is bad. I also could make a function out of the body but it looks wrong to me too because functions should be small and simple and the body of the loop is huge.
const auto minval = std::numeric_limits<T>::min();
const auto maxval = std::numeric_limits<T>::max();
for (auto i = minval; i < maxval; ++i) {
// huge body of the loop
}
It is as simple as stopping after you process the last item:
auto i = minval;
while(1) {
// do all the work for `i`
if (i == maxval) break;
++i;
}
One can also move the increment to the top of the loop, provided it is skipped on the first pass:
i = minval;
switch (1) {
case 0:
do {
++i;
case 1:
// processing for `i`
} while (i != maxval);
}
The latter version translates to efficient machine code a little more directly, as each loop iteration has only a single conditional branch, and there is a single unconditional branch, while in the first there is a conditional branch plus an unconditional branch which both repeat every iteration.
Neither version increments the ultimate value, which might be undefined behavior.
You have to maintain a bit of additional state to indicate whether you've seen the last value or not. Here's a simple example that could be moved to a more idiomatic iterator style without too much work:
#include <iostream>
#include <limits>
using namespace std;
template <typename T>
class allvalues
{
public:
allvalues() = default;
T next()
{
if (done) throw std::runtime_error("Attempt to go beyond end of range");
T v = val;
done = v == std::numeric_limits<T>::max();
if (!done) ++val;
return v;
}
bool isDone() { return done; }
private:
T val = std::numeric_limits<T>::min();
bool done = false;
};
int main() {
allvalues<char> range;
while (!range.isDone())
{
std::cout << "Value = " << (int)range.next() << std::endl;
}
allvalues<unsigned char> urange;
while (!urange.isDone())
{
std::cout << "Value = " << (unsigned int)urange.next() << std::endl;
}
std::cout << "That's it!" << std::endl;
}
Following program hangs. I know, several ways to fix it by changing the code.
// How to compile
// % g++ <filename>.cpp
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> empty;
set<int>::iterator iter = empty.begin() ;
while (iter++ != empty.end())
{
cout << *iter << "\n";
}
return 0;
}
My questions are:
how to fix it or workaround this piece of code?
is it a bug in libstdc++ or gcc?
thank you in advance for the answers.
iter already points to the end of the set. Incrementing it further with iter++ is not allowed. The workaround is to write a loop that can deal with an empty range:
for (auto &it : empty)
for (; iter != empty.end(); ++iter)