String_numput<> facet not writing to string - c++

I have written a String_numput<> facet that derives from the num_put<> facet, in order to write to a string.
The program is based on an example given by Stroustrup:
/// A num_put<> facet specialization that writes to a string
template<typename C>
class String_numput : public std::num_put<
C,
typename std::basic_string<C>::iterator>
{
public:
String_numput() :
/// this facet won't go into a locale;
/// it has a manually controlled lifetime
std::num_put<C, typename std::basic_string<C>::iterator> {1}
{
}
};
It is tested as follows:
using namespace std;
string s {};
void test(long i,
string& s,
int pos)
{
String_numput<char> f;
/// Format i into s at position pos;
/// use cout's formatting rules
f.put(s.begin() + pos, cout, ' ', i);
cout << s;
}
int main()
{
test(4567.9, s, 0);
cout << "completed" << endl;
}
http://coliru.stacked-crooked.com/a/f4e8386682471e7d
However, nothing is written to the string. The O/P is:
completed
What seems to be the problem here?
Thanks.

f.put(s.begin() + pos, cout, ' ', i);
the first argument is supposed to be an output iterator, but you give it the begin() of an empty string.
This has two problems:
it is illegal: it will overwrite the end of the empty [begin,end) range of s, so you're probably trampling some random memory, and
and it doesn't expand the string, so s.size() stays zero, so cout << s will insert zero characters of your damaged range.
You need a back_inserter instead of a string::iterator - this will actually append to your string correctly.
Note that std::num_put has two template parameters, and the second is the type expected for the iterator argument to put.
You're explicitly setting it to std::basic_string<C>::iterator, but if you change the iterator you pass to put, you need to change this second template parameter to match its type.

Based on an answer elsewhere, I have designed the solution as follows:
1) String_numput : will write a numeric to a string at a specified position. The string must be large enough to accommodate the numeric.
2) String_numapp : will append a numeric to a string using a back_inserter.
The solution is working.

Related

Is it possible to construct a modifiable view of portion in a string?

I have a match table with start and end indices of portions, in array (in a callback) - I wrap that array into vector of strings - now recently I did have the need to modify the original portions of the string.
struct regexcontext {
std::vector<std::optional<std::string>> matches;
std::string subject;
};
int buildmatchvector(size_t(*offset_vector)[2], int max, regexcontext* pcontext) {
pcontext->matches.clear();
ranges::transform(ranges::span{ offset_vector, max }, std::back_inserter(pcontext->matches), [&](const auto& refarr) {
return refarr[0] == -1 ? std::optional<std::string> {} : std::optional<std::string>{ pcontext->subject.substr(refarr[0], refarr[1] - refarr[0]) };
});
return 0;
}
Is it possible to change the above definition in a way that by modifying the match vector I will modify the subject string as well.
I've heard of string view but I've also heard it can't be modified with a variable sized string.
Note I'm using ranges-v3 which is the only library that implements standard ranges at the moment plus the nonstandard ranges::span which allows me to compile on msvc (since std::span doesn't work there for some reason).
As long as you only need to change characters to others, but not add or remove characters, then you could use a vector of span. Supporting addition or removal would be much more complicated and I don't think there's any simple solution in the standard library. Example:
return refarr[0] == -1
? span<char> {}
: span<char> {
&pcontext->subject[refarr[0]],
refarr[1] - refarr[0]
};
Note that any invalidating operation on the pointed string would invalidate these spans, so it would be a good idea to make the string private.

std::remove_if doesn't remove all items

In the input I would like to erase all non unique values. I want the subset after removing the double items to be identical to the input. Somehow some characters remain in the input and not all characters are removed. It seems like the std::map inside the predicate is also decrementing in size.
The predicate to std::remove_if() I am using is:
template<class T>
class RemovePredicate {
public:
RemovePredicate() : m_oldsize(0) {}
bool operator()(const T& value)
{
//
bool retval;
m_uniques[value] ='a'; // 'a' could be any value
cout << m_uniques.size() << endl;
retval = m_uniques.size() == m_oldsize;
m_oldsize = m_uniques.size();
return retval;
}
private:
std::map<T, char> m_uniques;
unsigned m_oldsize;
};
I designed the predicate in such way that when I can see the size increases I have not encountered the input. So when the size is not the same I don't remove the input. When the size remains the same I've encountered that input value again, then I do remove it.
The code to test this is:
template<class T>
void print(T iterable)
{
for (auto c : iterable)
cout << c;
cout << endl;
}
int main(int argc, char** argv){
if (argc != 2)
return 1;
char * str= argv[1];
vector <char> charvec (str, str + strlen(str));
print(charvec);
auto itend = std::remove_if(charvec.begin(),
charvec.end(),
RemovePredicate<char>()
);
print(charvec);
// apply erase remove idiom
charvec.erase(itend, charvec.end());
print(charvec);
return 0;
}
a example input is:
./remove_duplicates deadbeef
output gives
deabef
But as you can see there is still a double 'e' inside the output. But on the bright side the original ordering is maintained.
What am I doing wrong?
There's no guarantee that every call to the predicate is made on the same copy of the function object.
You need to arrange for copies to share a single map (or set or unordered_set), e.g. by declaring the map at a wider scope and keeping a reference, or by using shared_ptr (so the function objects as a group still own it).

How to use std::string as key in stxxl::map

I am trying to use std::string as a key in the stxxl::map
The insertion was fine for small number of strings about 10-100.
But while trying to insert large number of strings about 100000 in it, I am getting segmentation fault.
The code is as follows:
struct CompareGreaterString {
bool operator () (const std::string& a, const std::string& b) const {
return a > b;
}
static std::string max_value() {
return "";
}
};
// template parameter <KeyType, DataType, CompareType, RawNodeSize, RawLeafSize, PDAllocStrategy (optional)>
typedef stxxl::map<std::string, unsigned int, CompareGreaterString, DATA_NODE_BLOCK_SIZE, DATA_LEAF_BLOCK_SIZE> name_map;
name_map strMap((name_map::node_block_type::raw_size)*3, (name_map::leaf_block_type::raw_size)*3);
for (unsigned int i = 0; i < 1000000; i++) { /// Inserting 1 million strings
std::stringstream strStream;
strStream << (i);
Console::println("Inserting: " + strStream.str());
strMap[strStream.str()]=i;
}
In here I am unable to identify why I am unable to insert more number of strings. I am getting segmentation fault exactly while inserting "1377". Plus I am able to add any number of integers as key. I feel that the variable size of string might be causing this trouble.
Also I am unable to understand what to return for max_value of the string. I simply returned a blank string.
According to documentation:
CompareType must also provide a static max_value method, that returns a value of type KeyType that is larger than any key stored in map
Because empty string happens to compare as smaller than any other string, it breaks this precondition and may thus cause unspecified behaviour.
Here's a max_value that should work. MAX_KEY_LEN is just an integer which is larger or equal to the length of the longest possible string key that the map can have.
struct CompareGreaterString {
// ...
static std::string max_value() {
return std::string(MAX_KEY_LEN, std::numeric_limits<unsigned char>::max());
}
};
I have finally found the solution to my problem with great help from Timo bingmann, user2079303 and Martin Ba. Thank you.
I would like to share it with you.
Firstly stxxl supports POD only. That means it stores fixed sized structures only. Hence std::string cannot be a key. stxxl::map worked for about 100-1000 strings because they were contained in the physical memory itself. When more strings are inserted it has to write on disk which is internally causing some problems.
Hence we need to use a fixed string using char[] as follows:
static const int MAX_KEY_LEN = 16;
class FixedString {
public:
char charStr[MAX_KEY_LEN];
bool operator< (const FixedString& fixedString) const {
return std::lexicographical_compare(charStr, charStr+MAX_KEY_LEN,
fixedString.charStr, fixedString.charStr+MAX_KEY_LEN);
}
bool operator==(const FixedString& fixedString) const {
return std::equal(charStr, charStr+MAX_KEY_LEN, fixedString.charStr);
}
bool operator!=(const FixedString& fixedString) const {
return !std::equal(charStr, charStr+MAX_KEY_LEN, fixedString.charStr);
}
};
struct comp_type : public std::less<FixedString> {
static FixedString max_value()
{
FixedString s;
std::fill(s.charStr, s.charStr+MAX_KEY_LEN, 0x7f);
return s;
}
};
Please note that all the operators mainly((), ==, !=) need to be overriden for all the stxxl::map functions to work
Now we may define fixed_name_map for map as follows:
typedef stxxl::map<FixedString, unsigned int, comp_type, DATA_NODE_BLOCK_SIZE, DATA_LEAF_BLOCK_SIZE> fixed_name_map;
fixed_name_map myFixedMap((fixed_name_map::node_block_type::raw_size)*5, (fixed_name_map::leaf_block_type::raw_size)*5);
Now the program is compiling fine and is accepting about 10^8 strings without any problem.
also we can use myFixedMap like std::map itself. {for ex: myFixedMap[fixedString] = 10}
If you are using C++11, then as an alternative to the FixedString class you could use std::array<char, MAX_KEY_LEN>. It is an STL layer on top of an ordinary fixed-size C array, implementing comparisons and iterators as you are used to from std::string, but it's a POD type, so STXXL should support it.
Alternatively, you can use serialization_sort in TPIE. It can sort elements of type std::pair<std::string, unsigned int> just fine, so if all you need is to insert everything in bulk and then access it in bulk, this will be sufficient for your case (and probably faster depending on the exact case).

Replace string in a vector of structs C++

I'm new to C++ and I got stuck.
I have a problem replacing | with ,. I have no problem finding |, but replace function doesn't seem to work. What am I doing incorrectly? Any help appreciated.
Header File:
struct Document
{
string text;
int NumLines;
};
struct Find {
const string text;
Find(const string& text) : text(text) {}
bool operator()(const Document& j) const {
return j.text == text;
}
};
class DataRecord
{
private:
vector <Document> field;
public:
void Replace();
}
cpp. file for this function
void DataRecord::Replace ()
{
vector<Document>::iterator it = replace(field.begin(),field.end(),Find("|"),"," );
}
What you are attempting isn't clear, but if all you want to do is replace all the "|" for "," in every Document in field, the simplest approach might be a loop:
for (auto& f : field) :
std::replace(f.text.begin(), f.text.end(), '|', ',');
If I understand correctly, you are trying to replace documents in the sequence fields with a string literal. This does not work.
std::replace semantics:
std::replace(It begin, It end, Predicate P, Value v)
where:
*begin (and any element in the sequence [begin, end)) yields a value of type Value.
Predicate has the semantics P(const Value&) -> bool.
v in the value that should be set instead of the elements matching the predicate.
In your case, the fourth argument (v) should be of type Document, not a string literal.
You should create a document instance that specifies what should replace the Document instances matching the predicate (because you cannot replace them with string instances or string literals).
Edit: Alternately, you could add an implicit Document constructor that creates an instance from a string, but creating implicit constructors like that is usually a bad idea.

Reverse a word using function call

How can input a word and reverse the output of it. I made a function to calculate the length of the word and from here I have to reverse the word depending on the length of it.
How can I do that?
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
int LengthOfString( const char *); // declaring prototype for length of the string
int reverse(const char []);
int main()
{
char string1[100];
cout<<"Enter a string: ";
cin>>string1;
cout<<"Length of string is "<<LengthOfString(string1);
system("PAUSE");
return 0;
}
int LengthOfString( const char *x)
{
int index;
for(index = 0; *x!='\0';x++,index++);
return index;
}
int reverse(const char y[])
{
/* my attempted loop, its not right i know.
a[] = *index; // length of the word
for(int i=0; i<=index/2; i++)
for(j=0; j == length, j--) */
}
This wheel has already been invented, and exists in the standard library.
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string word;
std::cout << "Enter a word: ";
std::cin >> word;
std::reverse(word.begin(), word.end());
std::cout << "Reverse: " << word << std::endl;
return 0;
}
To understand exactly what's going on here, there are a few things that you must cover first:
data structures (classes)
containers
iterators
I hope you already know what a class is. In case you're still in introductory stuff, a class is basically a user defined collection of state and behavior. The author can choose to restrict access to the state or behavior of a class for a variety of reasons. In the case of std::string, the standard library string class, all of the state is hidden and only behavior is accessible.
The string class is a container that contains characters. There are numerous other container classes, each of which with different strengths and weaknesses. The string class contains a sequence of characters with a strict order. Other containers exist, such as std::set, std::vector, std::list, and others. std::string bears a passing resemblance to std::vector, and is a distant cousin of std::list. Each collection behaves differently and is suited for different things.
You might think you need to understand how the string class stores its data in order to reverse it, but you don't. This is where iterators come in. std::string owns a typedef, std::string::iterator, which is a special object which stores the location of a single element in a string. std::reverse is a library function which takes 2 iterators and repeatedly swaps their contents and moves them towards each other. This looks like this as it's happening:
v v <-- positions of iterators (start at the start, end at the end)
ABC <-- initial state
v v <-- the end iterator moved back
ABC
v v
CBA <-- the iterators swapped their values
vv <-- the begin iterator moved forward
CBA
V <-- the end iterator moved back; both iterators are in the same place
CBA <-- therefore, we're done, the string is reversed
One thing about iterators is they're kind of like pointers. In fact, you can pass pointers to some functions that expect iterators because they behave syntactically the same. Therefore, you should be able to write your own reverse function that uses pointers that basically does the same thing this did, except with char *s.
Here's some pseudocode that you should be able to write the function with (I won't write it out completely because it's homework):
namespace BaidNation
{
void reverse(char *begin, char *end)
{
loop forever
{
if (end equals begin):
done;
move end backwards;
if (end equals begin):
done;
swap end's and begin's characters;
move begin forwards;
}
}
}
Keep in mind that BaidNation::reverse (as well as std::reverse) expects for end the iterator that references the element AFTER the end of the collection, not the one that references the last element. How does it then make sense to use this?
Your LengthOfString function returns the number of non-null characters in a string. Since arrays are zero-indexed, we know that, like any other array, if we check string1 + LengthOfString(string1), we'll get a pointer to the character after the end which is, for once, exactly what we want.
Thus, we can use this to reverse the string:
BaidNation::reverse(string1, string1 + LengthOfString(string1));
If you have to use exactly the signature earlier, you can adapt this design into the other one:
int reverse(const char str[])
{
char *start = str, *end = str + LengthOfString(str);
BaidNation::reverse(start, end);
}
Based on the fact that the return type of your prototype function is int, it looks to me like you want to do an in-place reversal of a string. You first need to find out how long the string is (although you computed that before, you didn't pass the result to this function), then swap elements until you get to the middle. To make this work you need to pass, not a const char[], but just a char* (indicating that you will be changing the content):
int reverse(char* y)
{
int ii, n;
n = LengthOfString(y); // "no built in functions - otherwise, use strlen()
for(ii=0; ii<n/2;ii++) {
char temp;
temp = y[ii];
y[ii] = y[n - ii - 1];
y[n - ii] = temp;
}
}
Declare a new char* of the same length, and then loop as follows -
for(int i=0;i<stringLength;i++){
newString[i]=oldString[stringLength-i];
}
return newString;
Also you might want to consider using the String class instead of char*.