I'm doing leetcode 297. Serialize and Deserialize Binary Tree, and I'm trying to solve it with std::sregex_token_iterator
(other than using std::istringstream
/std::ostringstream
).
My solution is to append a whitespace when reading(serializing) a TreeNode value into the string, and using whitespace as delimieter when deserializing.
But due to "Definition for a binary tree node" (TreeNode(int x) : val(x), left(NULL), right(NULL) {}
), I have to cast elements pointed by sregex_token_iterator
to int
s.
I have read cppreference std::regex_token_iterator, and I'm still not sure if the type of the element dereferenced by sregex_token_iterator
is std::string
. (At first I thought it is definitely std::string
type.)
But error occured when I tried to do some attempts, like:
int val = stoi(*it);
TreeNode* node = new TreeNode(val);
or
string item = *it;
int val = stoi(item);
TreeNode* node = new TreeNode(val);
which all result in error
terminate called after throwing an instance of 'std::invalid_argument'
what(): stoi
And I've googled, but I didn't find question simiar to mine.
Below is my code:
/*
* @lc app=leetcode id=297 lang=cpp
*
* [297] Serialize and Deserialize Binary Tree
*/
// @lc code=start
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string data;
serialize(root, data);
return data;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
// whitespace
regex rgx {"\\s+"};
auto it = sregex_token_iterator {data.begin(), data.end(), rgx, -1};
auto it_end = sregex_token_iterator();
TreeNode* root = deserialize(data, rgx, it, it_end);
return root;
}
private:
void serialize(TreeNode* node, string& data) {
if (!node) {
data += "# ";
return;
}
data += node->val;
data += " ";
serialize(node->left);
serialize(node->right);
}
TreeNode* deserialize(string& data, regex& rgx, sregex_token_iterator& it, sregex_token_iterator& it_end) {
if (*it == "#") {
return nullptr;
}
/*** Error Here: ***/
// int val = stoi(*it);
string item = *it;
int val = stoi(item);
TreeNode* node = new TreeNode(val);
/* left tree */
++it;
node->left = deserialize(data, rgx, it, it_end);
/* right tree */
++it;
node->right = deserialize(data, rgx, it, it_end);
return node;
}
};
// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));
// @lc code=end
Is there any way to solve this casting problem without changing much of the code above? (i.e. do not change deserialize function from recursive one to iterative one.)
/*** Edit ***/
But after I revised it according to @Cubbi with data += to_string(node->val)
, another error occured:
Line 2778: Char 16: runtime error: reference binding to null pointer of type
'const std::__cxx11::regex_token_iterator<__gnu_cxx::__normal_iterator<
const char *, std::__cxx11::basic_string<char>>, char, std::__cxx11::regex_traits<char>>::
value_type' (aka 'const sub_match<__gnu_cxx::__normal_iterator<const char *, std::__cxx11::
basic_string<char>>>') (regex.h)
, but I have initialized it
and it_end
(while in my solution it_end
is not necessary) and still cannot find any possible errors.
Another try, adding:
if (it == it_end) {
return nullptr;
}
in deserialize()
recursive function, but surprisingly get an error with respect to vector
which I didn't use it in my code.
Line 1056: Char 34: runtime error: addition of unsigned offset to 0x6080000000a0 overflowed to 0x608000000058 (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1061:34