C++ C++;获取子字符串的代码

C++ C++;获取子字符串的代码,c++,substr,C++,Substr,我有一个字符串“1.0.0”,我想提取“1”、“0”和“0”。如果最后一个零不存在,则默认情况下字符串必须存储0: verstr.substr(0,verstr.find("."); 上面的语句可以找到第一个数字“1”,但是,我想不出提取字符串剩余部分的解决方案 在此之后,我将其转换为long,如下所示: va = atol(verstr.substr(0,verstr.find(".")).c_str()); 所以我想要va中的“1”,vb中的“0”等等 谢谢。尝试类似的方

我有一个字符串“1.0.0”,我想提取“1”、“0”和“0”。如果最后一个零不存在,则默认情况下字符串必须存储0:

verstr.substr(0,verstr.find(".");
上面的语句可以找到第一个数字“1”,但是,我想不出提取字符串剩余部分的解决方案

在此之后,我将其转换为long,如下所示:

        va = atol(verstr.substr(0,verstr.find(".")).c_str());
所以我想要va中的“1”,vb中的“0”等等


谢谢。

尝试类似的方法,而不是线下的解决方案

string s = "1.0.0";
string delimiters = ".";
size_t current;
size_t next = -1;
do
{
  current = next + 1;
  next = s.find_first_of( delimiters, current );
  string current_substring = s.substr( current, next - current ); // here you have the substring
}
while (next != string::npos);

好的,根据下面与@DavidSchwartz的讨论,如果你真的不知道自己在做什么,请不要使用下面的解决方案

看看函数
strtok


具体来看一下Boost库

<>标准的字符串支持在C++中有一定的局限性。而重新发明轮子显然很糟糕

更新:

我在评论中被问到为什么我认为所有基于find /SUBL的解决方案都是坏的风格。 我会尽力的

正如问题没有说明的那样,性能在这里不是问题。可维护性和可读性更为重要。这里提出的所有解决方案都将拆分算法语义与特定的版本解析算法语义紧密联系在一起。这对双方都有伤害

这会损害可维护性,因为当您需要更改版本格式时,将涉及更改实现拆分的同一代码块,从而使其更容易出错。单元测试也是如此

这损害了可读性,因为由于混合语义,我无法立即猜测这段代码背后的意图。例如,当我查找解析算法以检查丢失的3d版本参数是如何处理的时,我最好不要浪费时间去挖掘分割实现的细节


若解析模式会稍微困难一些,我会建议使用正则表达式。但在这种情况下,用分隔符拆分字符串是一种通用操作,经常被用来证明将其作为一个单独的函数是正确的。

不确定我是否理解您需要什么,如果您希望以字符串的形式检索数字,并且最少有x个数字,您可以这样做

vector<string> GetVersion(const string &strInput, int iMinSize)
{
    vector<string> vRetValue;

    std::stringstream ss(strInput); 
    string strItem;
    while(std::getline(ss, strItem, '.'))   
        vRetValue.push_back(strItem);

    while(vRetValue.size() < iMinSize)
        vRetValue.push_back("0");

    return vRetValue;
}

int _tmain(int argc, _TCHAR* argv[])
{   
    vector<string> vRetValue = GetVersion("1.0", 3); 
    return 0;
}
vector GetVersion(常量字符串和strInput,int iMinSize)
{
向量值;
标准:stringstream ss(strInput);
弦纹;
while(std::getline(ss,strItem,“.”)
vRetValue.向后推(strItem);
while(vRetValue.size()
可能需要使用。它使用起来很简单,并且提供了一个级别的错误检查,代码行相对较少:

#include <iostream>
#include <string>
#include <cstdio>

int main()
{
    std::string input[] = { "1.0.7", "1.0.", "1.0", "1.", "1" };

    for (size_t i = 0; i < sizeof(input)/sizeof(input[0]); i++)
    {
        std::cout << input[i] << ": ";

        // Init to zero.
        int parts[3] = { 0 };

        // sscanf() returns number of assignments made.
        if (std::sscanf(input[i].c_str(),
                        "%d.%d.%d",
                        &parts[0],
                        &parts[1],
                        &parts[2]) >= 2)
        {
            // OK, the string contained at least two digits.
            std::cout << parts[0]
                      << ","
                      << parts[1]
                      << ","
                      << parts[2]
                      << "\n";
        }
        else
        {
            std::cout << "bad format\n";
        }
    }
    return 0;
}
#包括
#包括
#包括
int main()
{
字符串输入[]={“1.0.7”、“1.0.”、“1.0”、“1.”、“1.”、“1”};
对于(size_t i=0;i如果只是一个小字符串中的简单字符比较

char []不应该那么坏……C函数应该工作……(编辑:对于一些人来说,这是亵渎……很多C++方法使用char *它是否是const)。< /P> 如果一个对象想要有相同的功能,需要使用更多的内存,需要花费更多的时间,那么为什么要使用它呢

编辑: 我看到一些答案假设创建了很多字符串对象…我不知道这是否是最好的方法。。。 一个小的2行递归C类函数可以做到这一点,而无需太多喘息。 在C++代码中,我可能会使用字符串对象来实现这一点,因为它可以忽略不计,但只是这样说。 在string对象中,我将使用length属性首先获取最后一个字符(使用[]运算符或适当的方法)。 然后只需要获取两个元素(在循环中,或者在接受regex的对象中使用2个back引用(效率较低))

C++11解决方案:

#include <iostream>
#include <string>
#include <regex>

using namespace std;

int main(int, char **) {
    string version("1.2.3");
    match_results<string::const_iterator> m;
    regex re("([0-9]+)\\.([0-9]+)(\\.([0-9]+))?");
    if (regex_match(version, m, re)) {
        int major = stoi(m[1].str()),
            minor = stoi(m[2].str()),
            rev = stoi(m[4].str().length() == 0 ? 0 : m[4].str());
        cout << "major: " << major << endl;
        cout << "minor: " << minor << endl;
        cout << "rev: " << rev << endl;
    } else {
        cout << "no match\n";
    }
}
#包括
#包括
#包括
使用名称空间std;
int main(int,char**){
字符串版本(“1.2.3”);
匹配结果m;
正则表达式re(“([0-9]+)\.([0-9]+)(\.([0-9]+))?”;
if(正则表达式匹配(版本,m,re)){
int major=stoi(m[1].str()),
minor=stoi(m[2].str()),
rev=stoi(m[4].str().length()==0?0:m[4].str());
cout和是两个非常好的函数重载家族,它们非常适合于许多简单的解析问题,特别是当您的语法检查只需要放松时

要从版本向量中提取多个标量,请将找到的索引存储在某个位置:

const auto a = verstr.find('.');
const std::string major = verstr.substr(0, a);
然后将其与of
string::find
一起重新使用,并在
a
之后的一处开始搜索:

等等

如果需要语法检查,请将返回的索引与
string::npos
进行比较:

const auto a = verstr.find('.');
if (std::string::npos == a)
    .... bad syntax ....

此答案的Pastebin样式版本:

#include <string>
#include <stdexcept>
#include <iostream>

struct Version
{
    std::string Major, Minor, Patch;

    Version(std::string const &Major)
    : Major(Major), Minor("0"), Patch("0")
    {}

    Version(std::string const &Major, std::string const &Minor)
    : Major(Major), Minor(Minor), Patch("0")
    {}

    Version(std::string const &Major, std::string const &Minor, std::string const &Patch)
    : Major(Major), Minor(Minor), Patch(Patch)
    {}
};

std::ostream& operator<< (std::ostream &os, Version const &v)
{
    return os << v.Major << '.' << v.Minor << '.' << v.Patch;
}

Version parse (std::string const &verstr) {
    if (verstr.empty()) throw std::invalid_argument("bad syntax");

    const auto first_dot = verstr.find('.');
    if (first_dot == std::string::npos)
        return Version(verstr);

    const auto second_dot = verstr.find('.', first_dot+1);
    if (second_dot == std::string::npos)
        return Version(verstr.substr(0, first_dot),
                       verstr.substr(first_dot+1, second_dot));


    return Version(verstr.substr(0, first_dot),
                   verstr.substr(first_dot+1, second_dot),
                   verstr.substr(second_dot+1));

}
#包括
#包括
#包括
结构版本
{
标准:字符串大调、小调、补丁;
版本(标准::字符串常量和主要)
:大调(大调),小调(“0”),补丁(“0”)
{}
版本(标准::字符串常量和主要版本,标准::字符串常量和次要版本)
:大调(大调)、小调(小调)、补丁(“0”)
{}
版本(标准::字符串常量和主要,标准::字符串常量和次要,标准::字符串常量和补丁)
:主要(主要)、次要(次要)、补丁(补丁)
{}
};

std::ostream&operator创建包含第一个
之后的所有内容的子字符串。然后在该子字符串中查找第一个
。您的意思是verstr.substr(,verstr.find(“.”);你知道如何创建包含第一个点之后的所有内容的子字符串吗?如果不知道,你应该真正学习如何使用
substr
find
,从阅读他们的文档开始。我使用了糟糕的算法和擦除子字符串,我已经找到了。但这是一种糟糕的做法我没有否决投票,但是..说真的吗stion是关于C++@KirilKirov的,这意味着,你应该使用基本的C函数?我想是这样的
const auto b = verstr.find ('.', a+1);
const std::string minor = verstr.substr(a+1, b);
const auto a = verstr.find('.');
if (std::string::npos == a)
    .... bad syntax ....
#include <string>
#include <stdexcept>
#include <iostream>

struct Version
{
    std::string Major, Minor, Patch;

    Version(std::string const &Major)
    : Major(Major), Minor("0"), Patch("0")
    {}

    Version(std::string const &Major, std::string const &Minor)
    : Major(Major), Minor(Minor), Patch("0")
    {}

    Version(std::string const &Major, std::string const &Minor, std::string const &Patch)
    : Major(Major), Minor(Minor), Patch(Patch)
    {}
};

std::ostream& operator<< (std::ostream &os, Version const &v)
{
    return os << v.Major << '.' << v.Minor << '.' << v.Patch;
}

Version parse (std::string const &verstr) {
    if (verstr.empty()) throw std::invalid_argument("bad syntax");

    const auto first_dot = verstr.find('.');
    if (first_dot == std::string::npos)
        return Version(verstr);

    const auto second_dot = verstr.find('.', first_dot+1);
    if (second_dot == std::string::npos)
        return Version(verstr.substr(0, first_dot),
                       verstr.substr(first_dot+1, second_dot));


    return Version(verstr.substr(0, first_dot),
                   verstr.substr(first_dot+1, second_dot),
                   verstr.substr(second_dot+1));

}
int main () {
    std::cout << parse("1.0") << '\n'
              << parse("1.0.4+Patches(55,322)") << '\n'
              << parse("1") << '\n';

    parse(""); // expected to throw
}