C++ 将十进制字符串拆分为两个整数
C++ Split decimal string into two integers
给定一个十进制值(秒及其分数)作为字符串,例如
std::string span = "ssss.nnnn" // ssss is value in seconds, nnnn is fractional seconds
将其转换为 timeval 结构(val.ts_sec 和 val.ts_usec)或 timespec 结构(tv_sec 和 tv_nsec)的最佳方法是什么。
大多数答案都讨论了转换值或者不是 C++。有些答案变得非常复杂或设置 类 这对于这种用法来说实在是太多了。
显然,如果两个值由白色分隔,则可以使用 sscanf 或 istringstream space。但是,如果它们由“.”分隔,是否有一种简单的方法可以做到这一点?无需遍历字符缓冲区搜索“。”
我刚刚发现这是一个可能的答案。我也想找点别的东西。
Parse (split) a string in C++ using string delimiter (standard C++)
strtok allows you to pass in multiple chars as delimiters. I bet if
you passed in ">=" your example string would be split correctly (even
though the > and = are counted as individual delimiters).
EDIT if you don't want to use c_str() to convert from string to char*,
you can use substr and find_first_of to tokenize.
string token, mystring("scott>=tiger");
while(token != mystring){
token = mystring.substr(0,mystring.find_first_of(">="));
mystring = mystring.substr(mystring.find_first_of(">=") + 1);
printf("%s ",token.c_str());
}
更新:
@Wintermute 指出以下代码片段将无法运行,因为可能存在前导零。
string span;
int sec;
int usec;
timeval inTime;
sscanf(span.c_str(), "%d.%d", &sec, &usec);
inTime.tv_sec = sec;
inTime.tv_usec = usec;
编辑:正如 Borgleader 正确提到的那样,如果时间戳变得足够大(大于一百万,给予或接受),简单地读入双精度会导致精度损失。一个数值稳定的方法是
timeval v;
time_t seconds;
double fraction;
std::istringstream parser(span);
if(parser >> seconds >> std::noskipws >> fraction) {
v.tv_sec = seconds;
v.tv_usec = static_cast<suseconds_t>(fraction * 1e6);
}
从现在开始,fraction
部分保证足够小,ieee-754 double
的尾数将覆盖逗号后超过 9 个十进制数字。一种可能的添加是
v.tv_usec = static_cast<suseconds_t>(fraction * 1e6 + 0.5); // rounding to nearest instead of down
取决于您的用例。
您可以使用 strtok_s 根据分隔符拆分字符串。在你的情况下是“。”
#include <iostream>
#include <string>
int main()
{
std::string span = "ssss.nnnn";
char * span1 = (char *)span.c_str();
char * pch = NULL;
char * context;
pch = strtok_s(span1, " .", &context);
while (pch != NULL)
{
printf("%s\n", pch);
pch = strtok_s(NULL, " .", &context);
}
return 0;
}
Output:
ssss
nnnn
如果您决定使用 string
class 及其函数 如果数字始终为十进制,那么我建议采用以下解决方案:
string span = "1234.123";
span += "000000";
size_t pos = span.find('.');
struct timeval val;
val.tv_sec = stol(span.substr(0,pos));
val.tv_usec = stol(span.substr(pos+1,6));
如果string
也可能得到不带点'.'的整数值字符然后使用
string span = "1234";
size_t pos = span.find('.');
struct timeval val;
val.tv_sec = stol( (pos!=string::npos)? span.substr(0,pos):span );
val.tv_usec = (pos!=string::npos)? stol((span+"000000").substr(pos+1,6)):0;
这个解决方案也使用了一些c++11。
给定一个十进制值(秒及其分数)作为字符串,例如
std::string span = "ssss.nnnn" // ssss is value in seconds, nnnn is fractional seconds
将其转换为 timeval 结构(val.ts_sec 和 val.ts_usec)或 timespec 结构(tv_sec 和 tv_nsec)的最佳方法是什么。
大多数答案都讨论了转换值或者不是 C++。有些答案变得非常复杂或设置 类 这对于这种用法来说实在是太多了。
显然,如果两个值由白色分隔,则可以使用 sscanf 或 istringstream space。但是,如果它们由“.”分隔,是否有一种简单的方法可以做到这一点?无需遍历字符缓冲区搜索“。”
我刚刚发现这是一个可能的答案。我也想找点别的东西。
Parse (split) a string in C++ using string delimiter (standard C++)
strtok allows you to pass in multiple chars as delimiters. I bet if you passed in ">=" your example string would be split correctly (even though the > and = are counted as individual delimiters).
EDIT if you don't want to use c_str() to convert from string to char*, you can use substr and find_first_of to tokenize.
string token, mystring("scott>=tiger"); while(token != mystring){ token = mystring.substr(0,mystring.find_first_of(">=")); mystring = mystring.substr(mystring.find_first_of(">=") + 1); printf("%s ",token.c_str()); }
更新:
@Wintermute 指出以下代码片段将无法运行,因为可能存在前导零。
string span;
int sec;
int usec;
timeval inTime;
sscanf(span.c_str(), "%d.%d", &sec, &usec);
inTime.tv_sec = sec;
inTime.tv_usec = usec;
编辑:正如 Borgleader 正确提到的那样,如果时间戳变得足够大(大于一百万,给予或接受),简单地读入双精度会导致精度损失。一个数值稳定的方法是
timeval v;
time_t seconds;
double fraction;
std::istringstream parser(span);
if(parser >> seconds >> std::noskipws >> fraction) {
v.tv_sec = seconds;
v.tv_usec = static_cast<suseconds_t>(fraction * 1e6);
}
从现在开始,fraction
部分保证足够小,ieee-754 double
的尾数将覆盖逗号后超过 9 个十进制数字。一种可能的添加是
v.tv_usec = static_cast<suseconds_t>(fraction * 1e6 + 0.5); // rounding to nearest instead of down
取决于您的用例。
您可以使用 strtok_s 根据分隔符拆分字符串。在你的情况下是“。”
#include <iostream>
#include <string>
int main()
{
std::string span = "ssss.nnnn";
char * span1 = (char *)span.c_str();
char * pch = NULL;
char * context;
pch = strtok_s(span1, " .", &context);
while (pch != NULL)
{
printf("%s\n", pch);
pch = strtok_s(NULL, " .", &context);
}
return 0;
}
Output:
ssss
nnnn
如果您决定使用 string
class 及其函数 如果数字始终为十进制,那么我建议采用以下解决方案:
string span = "1234.123";
span += "000000";
size_t pos = span.find('.');
struct timeval val;
val.tv_sec = stol(span.substr(0,pos));
val.tv_usec = stol(span.substr(pos+1,6));
如果string
也可能得到不带点'.'的整数值字符然后使用
string span = "1234";
size_t pos = span.find('.');
struct timeval val;
val.tv_sec = stol( (pos!=string::npos)? span.substr(0,pos):span );
val.tv_usec = (pos!=string::npos)? stol((span+"000000").substr(pos+1,6)):0;
这个解决方案也使用了一些c++11。