如何argv在int128_t支持下使用值?我知道atoi()暴露的函数和函数系列,<cstdlib>但不知怎的,我找不到一个int128_t固定宽度整数.这可能是因为这type不受c或c ++标准的支持,但是我有什么方法可以让这段代码工作吗?
#include <iostream>
int main(int argc, char **argv) {
__int128_t value = atoint128_t(argv[1]);
}
Run Code Online (Sandbox Code Playgroud)
几乎所有发布的答案对我来说都足够好了,但我选择的是当前代码的解决方案,所以也要查看其他答案.
这是实现此目的的简单方法:
__int128_t atoint128_t(const char *s)
{
const char *p = s;
__int128_t val = 0;
if (*p == '-' || *p == '+') {
p++;
}
while (*p >= '0' && *p <= '9') {
val = (10 * val) + (*p - '0');
p++;
}
if (*s == '-') val = val * -1;
return val;
}
Run Code Online (Sandbox Code Playgroud)
此代码检查每个字符以查看它是否是数字(带有可选的前导 + 或 -),如果是,则将当前结果乘以 10 并添加与该数字关联的值。如果需要的话,它会反转符号。
请注意,此实现不检查溢出,这与 的行为一致atoi。
编辑:
修改后的实现,int128_MIN通过根据符号添加或减去每个数字的值并跳过前导空格来覆盖大小写。
int myatoi(const char *s)
{
const char *p = s;
int neg = 0, val = 0;
while ((*p == '\n') || (*p == '\t') || (*p == ' ') ||
(*p == '\f') || (*p == '\r') || (*p == '\v')) {
p++;
}
if ((*p == '-') || (*p == '+')) {
if (*p == '-') {
neg = 1;
}
p++;
}
while (*p >= '0' && *p <= '9') {
if (neg) {
val = (10 * val) - (*p - '0');
} else {
val = (10 * val) + (*p - '0');
}
p++;
}
return val;
}
Run Code Online (Sandbox Code Playgroud)
这是一个 C++ 实现:
#include <string>
#include <stdexcept>
__int128_t atoint128_t(std::string const & in)
{
__int128_t res = 0;
size_t i = 0;
bool sign = false;
if (in[i] == '-')
{
++i;
sign = true;
}
if (in[i] == '+')
{
++i;
}
for (; i < in.size(); ++i)
{
const char c = in[i];
if (not std::isdigit(c))
throw std::runtime_error(std::string("Non-numeric character: ") + c)
res *= 10;
res += c - '0';
}
if (sign)
{
res *= -1;
}
return res;
}
int main()
{
__int128_t a = atoint128_t("170141183460469231731687303715884105727");
}
Run Code Online (Sandbox Code Playgroud)
如果你想测试它,那么这里有一个流运算符。
表现
我进行了一些性能测试。我生成了 100,000 个均匀分布在__int128_t. 然后我每个都转换了2000次。所有这些(200,000,000)次转换都在大约 12 秒内完成。使用此代码:
#include <iostream>
#include <string>
#include <random>
#include <vector>
#include <chrono>
int main()
{
std::mt19937 gen(0);
std::uniform_int_distribution<> num(0, 9);
std::uniform_int_distribution<> len(1, 38);
std::uniform_int_distribution<> sign(0, 1);
std::vector<std::string> str;
for (int i = 0; i < 100000; ++i)
{
std::string s;
int l = len(gen);
if (sign(gen))
s += '-';
for (int u = 0; u < l; ++u)
s += std::to_string(num(gen));
str.emplace_back(s);
}
namespace sc = std::chrono;
auto start = sc::duration_cast<sc::microseconds>(sc::high_resolution_clock::now().time_since_epoch()).count();
__int128_t b = 0;
for (int u = 0; u < 200; ++u)
{
for (int i = 0; i < str.size(); ++i)
{
__int128_t a = atoint128_t(str[i]);
b += a;
}
}
auto time = sc::duration_cast<sc::microseconds>(sc::high_resolution_clock::now().time_since_epoch()).count() - start;
std::cout << time / 1000000. << 's' << std::endl;
}
Run Code Online (Sandbox Code Playgroud)