用字符串中的双重替换每次发生

发布于 2025-01-27 04:40:33 字数 1512 浏览 3 评论 0原文

我正在尝试编写一个函数,其第一个参数是字符串,第二个参数是实数的向量。该函数应结果返回一个新的字符串,其中每次发生的新字符串替代了序列“%d”或“%f”,每个数字从向量中,以它们出现的顺序为单位。在这样做时,如果序列为“%d”,则数字中的任何小数是截断的,而在序列“%f”中,它们被保留。

例如,如果字符串读为“ ABC%DXX%fyy%d”,并且矢量包含数字12.25、34.13、25和47,则新字符串应读为“ ABC12XX34.13YY 25”(数据47(数据47),是“冗余”被简单地忽略)。

#include <iostream>
#include <string>
#include <vector>

std::string Replace(std::string s, std::vector < double > vek) {
  std::string str;
  int j = 0;
  for (int i = 0; i < s.length(); i++) {
    while (s[i] != '%' && i < s.length()) {
      if (s[i] != 'f' && s[i] != 'd')
        str += s[i];
      i++;
    }
    if (s[i] == '%' && (s[i + 1] == 'd' || s[i + 1] == 'f')) {
      if (s[i + 1] == 'd')
        str += (std::to_string(int(vek[j])));
      if (s[i + 1] == 'f') {
        std::string temp = std::to_string(vek[j]);
        int l = 0;
        while (temp[l] != '0') {
          str += temp[l];
          l++;
        }
      }
      j++;
      if (j > vek.size())
        throw std::range_error("Not enough elements");
      if (i == s.length()) break;
    }
  }
  return str;
}
int main() {
  try {
    std::cout<<Replace("abc%dxx%fyy %d",{12.25, 34.13, 25});
    std::cout << "\n" << "abc12xx34.13yy 25";
  } catch (std::range_error e) {
    std::cout << e.what();
  }

  return 0;
}

输出:

abc12xx34.13yy 25

abc12xx34.13yy 25

输出是正确的。我如何修改它以减少代码行的工作?有什么方法可以使这种更优雅和高效?

I'm trying to write a function whose first parameter is a string and the second parameter is vector of real numbers. The function should return as a result a new string in which each occurrence replaces the sequences "%d" or "%f" with one number each from the vector, in the order in which they appear. In doing so, if the sequence is "%d", any decimals in the number are truncated, while in the sequence "%f" they are retained.

For example, if the string reads “abc%dxx%fyy %d” and if the vector contains the numbers 12.25, 34.13, 25 and 47, the new string should read “abc12xx34.13yy 25” (data 47 which is “redundant” is simply ignored).

#include <iostream>
#include <string>
#include <vector>

std::string Replace(std::string s, std::vector < double > vek) {
  std::string str;
  int j = 0;
  for (int i = 0; i < s.length(); i++) {
    while (s[i] != '%' && i < s.length()) {
      if (s[i] != 'f' && s[i] != 'd')
        str += s[i];
      i++;
    }
    if (s[i] == '%' && (s[i + 1] == 'd' || s[i + 1] == 'f')) {
      if (s[i + 1] == 'd')
        str += (std::to_string(int(vek[j])));
      if (s[i + 1] == 'f') {
        std::string temp = std::to_string(vek[j]);
        int l = 0;
        while (temp[l] != '0') {
          str += temp[l];
          l++;
        }
      }
      j++;
      if (j > vek.size())
        throw std::range_error("Not enough elements");
      if (i == s.length()) break;
    }
  }
  return str;
}
int main() {
  try {
    std::cout<<Replace("abc%dxx%fyy %d",{12.25, 34.13, 25});
    std::cout << "\n" << "abc12xx34.13yy 25";
  } catch (std::range_error e) {
    std::cout << e.what();
  }

  return 0;
}

OUTPUT:

abc12xx34.13yy 25

abc12xx34.13yy 25

Output is correct. How could I modify this to work with less lines of code? Is there any way to make this more elegant and efficient?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蓝天 2025-02-03 04:40:33

您可以使用:

  1. 搜索模式(%d |%f)的正则表达式,
  2. 即字符串流以创建以返回的字符串。

进一步详细说明:

  • 代码基本上是while(std :: regex_search)
  • std :: Regex_search将在匹配模式之前返回输入字符串中的所有内容(输出字符串中您想要的内容),匹配的模式(您需要检查的内容以确定是否需要写出int或double),以及剩下的任何东西。
  • 通过使用std :: Ostringstream,您可以简单地写出INT或双打而无需将它们转换为字符串。
  • vek.at()如果您的数据用完了,则会抛出std :: out_of_range异常。
  • 同样请注意,尽管对于此实现,但最好通过值传递字符串s(由于我们在函数中修改它),但您应该将vek作为const传递参考以避免整个向量的副本。

[demo]

#include <iostream>
#include <regex>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>

std::string Replace(std::string s, const std::vector<double>& vek) {
    std::regex pattern{"(%d|%f)"};
    std::smatch match{};
    std::ostringstream oss{};
    for (auto i{0}; std::regex_search(s, match, pattern); ++i) {
        oss << match.prefix();
        auto d{vek.at(i)};
        oss << ((match[0] == "%d") ? static_cast<int>(d) : d);
        s = match.suffix();
    }
    return oss.str();
}

int main() {
    try {
        std::cout << Replace("abc%dxx%fyy %d", {12.25, 34.13, 25});
        std::cout << "\n"
                  << "abc12xx34.13yy 25";
    } catch (std::out_of_range& e) {
        std::cout << e.what();
    }
}

// Outputs:
//
//   abc12xx34.13yy 25
//   abc12xx34.13yy 25

[edit] [edit]无需std :: regex_search 将是手动搜索(%d |%f)模式,使用std :: string :: find在循环中,直到字符串的结尾为到达。

下面的代码考虑了:

  • 输入字符串无法具有该模式,并且
  • 它可以具有字符,后跟d not d也不是f 。

[demo]

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

std::string Replace(std::string s, const std::vector<double>& vek) {
    std::ostringstream oss{};
    size_t previous_pos{0};
    size_t pos{0};
    auto i{0};
    while (previous_pos != s.size()) {
        if ((pos = s.find('%', previous_pos)) == std::string::npos) {
            oss << s.substr(previous_pos);
            break;
        }
        oss << s.substr(previous_pos, pos - previous_pos);
        bool pattern_found{false};
        if (s.size() > pos + 1) {
            auto c{s[pos + 1]};
            if (c == 'd') {
                oss << static_cast<int>(vek.at(i));
                pattern_found = true;
            } else if (c == 'f') {
                oss << vek.at(i);
                pattern_found = true;
            }
        }
        if (pattern_found) {
            ++i;
            previous_pos = pos + 2;
        } else {
            oss << s[pos];
            previous_pos = pos + 1;
        }
    }
    return oss.str();
}

int main() {
    try {
        std::cout << Replace("abc%%dx%x%fyy %d", {12.25, 34.13, 25}) << "\n";
        std::cout << "abc%12x%x34.13yy 25\n";
        std::cout << Replace("abcdxxfyy d", {12.25, 34.13, 25}) << "\n";
        std::cout << "abcdxxfyy d\n";
    } catch (std::out_of_range& e) {
        std::cout << e.what();
    }
}

// Outputs:
//
//   abc%12x%x34.13yy 25
//   abc%12x%x34.13yy 25
//   abcdxxfyy d
//   abcdxxfyy d

You could use:

  1. regular expressions to search for the pattern (%d|%f), i.e., %d or %f, and
  2. a string stream to create the string to return.

Going into some more detail:

  • The code is basically a while (std::regex_search).
  • std::regex_search will return whatever was in the input string before the matched pattern (what you want in the output string), the matched pattern (what you will need to check in order to decide if you want to write out an int or a double), and whatever is left to parse.
  • By using std::ostringstream, you can simply write out ints or doubles without converting them to strings yourself.
  • vek.at() will throw an std::out_of_range exception if you run out of data in the vector.
  • Notice as well that, whereas for this implementation it's good to pass the string s by value (since we are modifying it within the function), you should pass vek as a const reference to avoid a copy of the whole vector.

[Demo]

#include <iostream>
#include <regex>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>

std::string Replace(std::string s, const std::vector<double>& vek) {
    std::regex pattern{"(%d|%f)"};
    std::smatch match{};
    std::ostringstream oss{};
    for (auto i{0}; std::regex_search(s, match, pattern); ++i) {
        oss << match.prefix();
        auto d{vek.at(i)};
        oss << ((match[0] == "%d") ? static_cast<int>(d) : d);
        s = match.suffix();
    }
    return oss.str();
}

int main() {
    try {
        std::cout << Replace("abc%dxx%fyy %d", {12.25, 34.13, 25});
        std::cout << "\n"
                  << "abc12xx34.13yy 25";
    } catch (std::out_of_range& e) {
        std::cout << e.what();
    }
}

// Outputs:
//
//   abc12xx34.13yy 25
//   abc12xx34.13yy 25

[EDIT] A possible way to do it without std::regex_search would be to search for the (%d|%f) pattern manually, using std::string::find in a loop until the end of the string is reached.

The code below takes into account that:

  • the input string could not have that pattern, and that
  • it could have a % character followed by neither d nor f.

[Demo]

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

std::string Replace(std::string s, const std::vector<double>& vek) {
    std::ostringstream oss{};
    size_t previous_pos{0};
    size_t pos{0};
    auto i{0};
    while (previous_pos != s.size()) {
        if ((pos = s.find('%', previous_pos)) == std::string::npos) {
            oss << s.substr(previous_pos);
            break;
        }
        oss << s.substr(previous_pos, pos - previous_pos);
        bool pattern_found{false};
        if (s.size() > pos + 1) {
            auto c{s[pos + 1]};
            if (c == 'd') {
                oss << static_cast<int>(vek.at(i));
                pattern_found = true;
            } else if (c == 'f') {
                oss << vek.at(i);
                pattern_found = true;
            }
        }
        if (pattern_found) {
            ++i;
            previous_pos = pos + 2;
        } else {
            oss << s[pos];
            previous_pos = pos + 1;
        }
    }
    return oss.str();
}

int main() {
    try {
        std::cout << Replace("abc%%dx%x%fyy %d", {12.25, 34.13, 25}) << "\n";
        std::cout << "abc%12x%x34.13yy 25\n";
        std::cout << Replace("abcdxxfyy d", {12.25, 34.13, 25}) << "\n";
        std::cout << "abcdxxfyy d\n";
    } catch (std::out_of_range& e) {
        std::cout << e.what();
    }
}

// Outputs:
//
//   abc%12x%x34.13yy 25
//   abc%12x%x34.13yy 25
//   abcdxxfyy d
//   abcdxxfyy d
方圜几里 2025-02-03 04:40:33
#include <iostream>
#include <vector>
#include <string>

std::string replace(std::string str, std::vector<double> vec) {
    std::string result = "";
    int i = 0;

    // loop through the string
    while (i < str.size()) {
        // if the current character is a % 
        if (str[i] == '%') {
            // if the next character is a d
            if (str[i+1] == 'd') {
                // if the vector is not empty
                if (vec.size() > 0) {
                    // add the first element of the vector to the result
                    result += std::to_string(vec[0]);
                    // remove the first element of the vector
                    vec.erase(vec.begin());
                }
                // move the index to the next character
                i += 2;
            }
            // if the next character is a f
            else if (str[i+1] == 'f') {
                // if the vector is not empty
                if (vec.size() > 0) {
                    // add the first element of the vector to the result
                    result += std::to_string(vec[0]);
                    // remove the first element of the vector
                    vec.erase(vec.begin());
                }
                // move the index to the next character
                i += 2;
            }
            // if the next character is not a d or f
            else {
                // add the current character to the result
                result += str[i];
                // move the index to the next character
                i += 1;
            }
        }
        // if the current character is not a %
        else {
            // add the current character to the result
            result += str[i];
            // move the index to the next character
            i += 1;
        }
    }
    // return the result
    return result;
}


int main() {
    std::vector<double> vec = {12.25, 34.13, 25, 47};
    std::string str = "abc%dxx%fyy %d";
    std::cout << replace(str, vec);
    return 0;
}
#include <iostream>
#include <vector>
#include <string>

std::string replace(std::string str, std::vector<double> vec) {
    std::string result = "";
    int i = 0;

    // loop through the string
    while (i < str.size()) {
        // if the current character is a % 
        if (str[i] == '%') {
            // if the next character is a d
            if (str[i+1] == 'd') {
                // if the vector is not empty
                if (vec.size() > 0) {
                    // add the first element of the vector to the result
                    result += std::to_string(vec[0]);
                    // remove the first element of the vector
                    vec.erase(vec.begin());
                }
                // move the index to the next character
                i += 2;
            }
            // if the next character is a f
            else if (str[i+1] == 'f') {
                // if the vector is not empty
                if (vec.size() > 0) {
                    // add the first element of the vector to the result
                    result += std::to_string(vec[0]);
                    // remove the first element of the vector
                    vec.erase(vec.begin());
                }
                // move the index to the next character
                i += 2;
            }
            // if the next character is not a d or f
            else {
                // add the current character to the result
                result += str[i];
                // move the index to the next character
                i += 1;
            }
        }
        // if the current character is not a %
        else {
            // add the current character to the result
            result += str[i];
            // move the index to the next character
            i += 1;
        }
    }
    // return the result
    return result;
}


int main() {
    std::vector<double> vec = {12.25, 34.13, 25, 47};
    std::string str = "abc%dxx%fyy %d";
    std::cout << replace(str, vec);
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文