Hello to all. There is a line with arguments for example "Hi, my name is% 1, I'm% 2 years old. I live in% 3" . Input data such char array [64] = "Anton | 15 | Arkhangelsk"; You need to parse the string and substitute the data into the arguments of the string, then output the string.
2 answers
To pull tokens from a string, you can use sregex_token_iterator from <regex> :
#include <ostream> #include <regex> #include <string> #include <vector> std::ostream& print(std::ostream& out, const std::string& format, const std::vector<std::string>& args) { std::regex re("[^%]+|%%|%\\d+"); for (std::sregex_token_iterator i {format.begin(), format.end(), re, 0}, end; i != end; ++i) { std::string token {*i}; if (token == "%%") { // escaped % out << '%'; } else if (token[0] == '%') { // positional parameter unsigned long index = std::stoul(token.substr(1)); out << args.at(index-1); } else { // print as is out << token; } } return out; } Example of use:
#include <iostream> int main() { char array[] = u8"Антон|15|Архангельске"; print(std::cout, u8"Привет, меня зовут %1, мне %2 лет. Я живу в %3", split(array, '|')) << std::endl; } where split() can also be defined using regex, or in the simple case when the char delimiter, you can use std::stringstream + std::getline() :
#include <sstream> #include <string> #include <vector> std::vector<std::string> split(const std::string& s, char sep) { std::vector<std::string> args; std::istringstream ss {s}; for (std::string arg; std::getline(ss, arg, sep); ) args.push_back(arg); return args; } Startup example:
$ c++ -std=c++11 *.cc && ./a.out Привет, меня зовут Антон, мне 15 лет. Я живу в Архангельске For comparison, you can look at the (non-recommended) option, which hands parses the format:
std::ostream& print(std::ostream& out, const std::string& format, const std::vector<std::string>& args) { bool in_format = false; size_t index = 0; for (char c : format) { if (in_format) { if (std::isdigit(static_cast<unsigned char>(c))) { // build up index index *= 10; index += c - '0'; } else { in_format = false; if (index) { // full number, print corresponding arg out << args[index-1]; index = 0; if (c != '%') { out << c; // print as is } } else if (c == '%') { // %% case -- print % literally out << c; } else { // error XXX ignore out << c; } } } else if (c == '%') { in_format = true; } else { // print as is out << c; } } if (index) out << args[index-1]; return out; } In this embodiment, it is easier to make a mistake and harder to track how extreme cases behave.
Create a new line in which you copy all the characters of the source except "formats", instead of which you copy the corresponding elements of array [].
Well, to parse it (remember pointers to words in another array), you can also use strtok () (just remember, strtok is not applicable to constants and irreversibly changes the string to which it is applied).
Most likely, it makes sense to create the resulting string in the "dynamic" memory, because its size is not known in advance (use, for example, malloc ), increasing its size as needed (for example, causing realloc ).
sscanf- DNSstrtokdid not work - without comm. - DNS