I have a problem that strtok solves (split substrings from a string), but I'm that strtok is unsafe. I want to use some more modern parts of the C ++ standard library.
What should i use instead?
static int ParseLine(std::string line, std::string seps, int startIdx, std::vector<CNode>& collection) { if (startIdx > collection.size()) { throw std::invalid_argument("the start index is out of range"); } char buf[2000]; strcpy_s(buf, line.c_str()); auto idx = startIdx; for (auto objectType = strtok(buf, seps.c_str()); objectType != nullptr; idx++) { if (idx == collection.size()) { collection.push_back(CNode(idx)); } collection[idx].SetObjectType(objectType); objectType = strtok(nullptr, seps.c_str()); } return (idx - 1); }
Here is a complete sample that compiles with _CRT_SECURE_NO_WARNINGS:
#include <string> #include <vector> #include <iostream> class CObject { std::string _objectType; public: CObject() : _objectType("n/a") {} void SetObjectType(std::string objectType) { _objectType = objectType; } std::string GetObjectType() const { return _objectType; } }; class CNode { int _id; CObject _object; public: explicit CNode(int id) : _id(id) {} void SetObjectType(std::string objectType) { _object.SetObjectType(objectType); } std::string GetObjectType() const { return _object.GetObjectType(); } }; // Update the collection of nodes with the object types found in the line specified. // Return the number of elements in the collection. static int ParseLine(std::string line, std::string seps, int startIdx, std::vector<CNode>& collection) { if (startIdx > collection.size()) { throw std::invalid_argument("the start index is out of range"); } char buf[2000]; strcpy_s(buf, line.c_str()); auto idx = startIdx; for (auto objectType = strtok(buf, seps.c_str()); objectType != nullptr; idx++) { if (idx == collection.size()) { collection.push_back(CNode(idx)); } collection[idx].SetObjectType(objectType); objectType = strtok(nullptr, seps.c_str()); } return (idx - 1); } int main() { std::string seps = "."; // 2 3 4 5 6 7 8 9 std::string line = "abc.def.ghi.klm.nop.qrs.tuv.wxyz"; std::vector<CNode> collection { CNode(0), CNode(1), CNode(2) , CNode(3) , CNode(4) , CNode(5) }; auto startAt = 2; try { auto collection_size = ParseLine(line, seps, startAt, collection); std::cout << collection_size << std::endl; for (auto value : collection) { std::cout << value.GetObjectType() << std::endl; } } catch (std::invalid_argument& e) { std::cout << " out of range exception " << e.what() << std::endl; } return 0; }
source share