我在使用Crypto ++的Integer
课时遇到了一些问题。我使用的是最新版本5.6.2。
我正在尝试使用以下代码将Integer转换为字符串:
CryptoPP::Integer i("12345678900987654321");
std::ostrstream oss;
oss << i;
std::string s(oss.str());
LOGDEBUG(oss.str()); // Pumps log to console and log file
输出似乎有额外的垃圾数据:
12345678900987654321.ÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««îþîþ
当我直接输出到控制台时,我得到同样的东西:
std::cout << "Dec: " << i << std::endl; // Same result
此外,我无法获得精确或科学的符号。以下将输出相同的结果:
std::cout.precision(5); // Does nothing with CryptoPP::Integer
std::cout << "Dec: " << std::setprecision(1) << std::dec << i << std::endl;
std::cout << "Sci: " << std::setprecision(5) << std::scientific << i << std::endl;
除此之外,足够大的数字打破了整个事情。
CryptoPP::Integer i("12345");
// Calculate i^16
for (int x = 0; x < 16; x++)
{
i *= i;
}
std::cout << i << std::endl; // Will never finish
最终我正在努力获得可以使用大Integer
个数字的东西,并且可以用科学记数法输出字符串。我在提取Integer
库或根据需要修改它时没有问题,但我更喜欢使用稳定的代码。
我做错了什么,或者有没有办法让我能正常工作?
答案 0 :(得分:2)
我尝试使用以下代码将Integer转换为字符串:
CryptoPP::Integer i("12345678900987654321"); std::ostrstream oss; oss << i; std::string s(oss.str()); LOGDEBUG(oss.str()); // Pumps log to console and log file
输出似乎有额外的垃圾数据:
12345678900987654321.ÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««îþîþ
我无法在Visual Studio 2010上使用Crypto ++ 5.6.2重现这一点。损坏的输出很可能是其他问题的结果,而不是Crypto ++中的错误。如果您还没有这样做,我建议您尝试使用CryptoPP::Integer
和std::cout
以及任何其他应用程序代码在最小程序中重现这一点,以消除所有其他可能的问题。如果它不能在一个简单的独立测试中工作(这会令人惊讶),那么构建库的方式可能会出现问题(例如,它可能是使用不同的C ++运行时或编译器版本构建的。应用程序正在使用)。如果您的独立测试通过,您可以添加其他字符串操作,记录代码等,直到找到罪魁祸首。
我确实注意到你使用的std::ostrstream
已被弃用。您可能想要使用std::ostringstream
instead。 This Stack Overflow answer to the question "Why was std::strstream deprecated?"可能会引起关注,甚至可能是答案中提到的问题导致您的问题。
此外,我无法获得精确或科学的符号。 以下将输出相同的结果:
std::cout.precision(5); // Does nothing with CryptoPP::Integer std::cout << "Dec: " << std::setprecision(1) << std::dec << i << std::endl; std::cout << "Sci: " << std::setprecision(5) << std::scientific << i << std::endl;
std::setprecision
和std::scientific
modify floating-point input/output。因此,对于像int
或long long
这样的C ++中的常规整数类型,这也不会起作用(但我可以看到,尤其是像CryptoPP:Integer
这样的任意长度整数能够输出在具有指定精度的科学记数法中是有意义的。)
即使C ++没有像这样定义它,Crypto ++的实现仍然需要注意那些标志。通过查看std::ostream& operator<<(std::ostream& out, const Integer &a)
的Crypto ++实现,我可以看到它识别的唯一iostream标志是std::ios::oct
和std::ios::hex
(分别对于八进制和十六进制格式数字)。
如果您需要科学记数法,您必须自己格式化输出(或使用不同的库)。
除此之外,足够大的数字打破了整个 的事情。
CryptoPP::Integer i("12345"); // Calculate i^16 for (int x = 0; x < 16; x++) { i *= i; } std::cout << i << std::endl; // Will never finish
这实际上会计算i^(2^16) = i^65536
,而不是i^16
,因为在每个循环中,您将i
与其新的中间值相乘,而不是与其原始值相乘。这段代码的实际结果是268,140位长,所以我希望它只需要很长一段时间来生成输出。
以下是调整后产生正确结果的代码:
CryptoPP::Integer i("12345");
CryptoPP::Integer i_to_16(1);
// Calculate i^16
for (int x = 0; x < 16; x++)
{
i_to_16 *= i;
}
std::cout << i_to_16 << std::endl;
答案 1 :(得分:1)
LOGDEBUG(oss.str()); // Pumps log to console and log file
输出似乎有额外的垃圾数据:
12345678900987654321.ÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««îþîþ
我怀疑你所呈现的内容与现实生活中的内容略有简化。我认为问题与LOGDEBUG
和ostringstream
有关。而且我相信您输出的是char*
,而不是string
(尽管我们还没有看到您的记录器的代码)。
std::string
返回的oss.str()
是暂时的。所以这个:
LOGDEBUG(oss.str());
与此略有不同:
string t(oss.str());
LOGDEBUG(t);
当您打算使用string
时,您应始终复制ostringstream
。或者确保使用包含在一个语句中。
我发现的最好方法是:
// Note: reference, and the char* is used in one statement
void LOGDEBUG(const ostringstream& oss) {
cout << oss.str().c_str() << endl;
}
或者
// Note: copy of the string below
void LOGDEBUG(string str) {
cout << str.c_str() << endl;
}
你不能甚至做到这一点(这一点我在制作中):
const char* msg = oss.str().c_str();
cout << msg << endl;
您无法执行此操作,因为从string
返回的oss.str()
是暂时的。所以char*
在语句执行后是垃圾。
以下是解决问题的方法:
const string t(oss.str());
const char* msg = t.c_str();
cout << msg << endl;
如果您在程序中运行 Valgrind ,那么您可能会得到与您使用ostringstream
和strings
相关的无法解释的结果。
以下是类似的日志记录问题:stringstream temporary ostream return problem。另请参阅Turning temporary stringstream to c_str() in single statement。这是我经历的那个:Memory Error with std:ostringstream and -std=c++11?
Matt在下面的评论中指出,您应该使用ostringstream
,而不是ostrstream
。自C ++ 98以来,ostrstream
已被弃用,使用它时应该会收到警告。
所以请改用:
#include <sstream>
...
std::ostringstream oss;
...
但我相信问题的根源在于您使用std::string
函数或宏中的LOGDEBUG
的方式。
您在Integer的其他问题是在Softwariness的回答和相关评论中处理的。所以我不会再重复它们了。