json-cpp longlong 类型的扩展

本文介绍如何解决JSON-CPP不支持longlong类型的问题,并提供了解决方案,包括定义long类型、添加解析方法等步骤。

用cocos2dx做跨平台项目的时候,自然就用了c++版本的json库,这个json-cpp是用的比较多的,总体用起来还算可以,有一个很不方便的地方就是不支持long long(int64)类型,一开始我使用double类型来强制转换,后来出了bug,double精度只有16位,超过20位的就会被四舍五入,试过了官网上bug列表里的方法都不行,

没办法,花点时间添加longValue才解决这个问题,加地方实在太多了,附上主要扩展代码备忘:


一,定义一个long类型

//lancer add long

typedef long long Long;


二、

//类型里添加longValue

enum ValueType

{

nullValue = 0, ///< 'null' value

intValue, ///< signed integer value

uintValue, ///< unsigned integer value

//lancer add for longlong

longValue, //signed int 64

realValue, ///< double value

stringValue, ///< UTF-8 string value

booleanValue, ///< bool value

arrayValue, ///< array value (ordered list)

objectValue ///< object value (collection of name/value pairs).


};


三、添加一个解析long类型的方法

bool

Reader::decodeLongLong( Token &token )

{

Long value = 0;

const int bufferSize = 32;

int count;

int length = int(token.end_ - token.start_);

if ( length <= bufferSize )

{

Char buffer[bufferSize];

memcpy( buffer, token.start_, length );

buffer[length] = 0;

count = sscanf( buffer, "%lld", &value );

}

else

{

std::string buffer( token.start_, token.end_ );

count = sscanf( buffer.c_str(), "%lld", &value );

}

if ( count != 1 )

return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );

currentValue() = value;

return true;

}


四、解析数字

bool

Reader::decodeNumber( Token &token )方法里,超出int型数据范围的时候使用decodeLongLong方法,而不是之前的decodeDouble

while ( current < token.end_ )

{

Char c = *current++;

if ( c < '0' || c > '9' )

return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );

if ( value >= threshold )

// return decodeDouble( token );

//lancer add for long long

return decodeLongLong( token );

value = value * 10 + Value::UInt(c - '0');

}


五,添加一个asLongLong方法供调用

//lancer as long

Long Value::asLongLong() const

{

switch ( type_ )

{

case nullValue:

return 0;

case intValue:

return value_.int_;

case uintValue:

JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );

return value_.uint_;

case longValue:

return value_.long_;

case realValue:

JSON_ASSERT_MESSAGE( value_.real_ >= minLong && value_.real_ <= maxLong, "Real out of signed long range" );

return Long( value_.real_ );

case booleanValue:

return value_.bool_ ? 1 : 0;

case stringValue:

{

//lancer safe long long

return atoll(value_.string_);

}

case arrayValue:

case objectValue:

JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );

default:

JSON_ASSERT_UNREACHABLE;

}

return 0; // unreachable;

}


其他地方细节要改的太多了,我都是全局搜索realValue,然后对应的地方改掉


另外,由于后台传输数据的时候数字可能会被传成字符串,所以解析数字的地方都需要加上对字符串的判断,

比如:

Value::Int

Value::asInt() const

{

switch ( type_ )

{

case stringValue:

{

//lancer safe int

return atoi(value_.string_);

}


转载请保留以下信息:

作者(Author):smilelance

出处( From ):http://blog.youkuaiyun.com/smilelance




35 0 F:\Dev-Cpp\MinGW64\lib\gcc\x86_64-w64-mingw32\4.9.2\include\c++\random In file included from F:/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++/random 4 C:\Users\余伟杰\Desktop\RSA.cpp from C:\Users\余伟杰\Desktop\RSA.cpp 32 2 F:\Dev-Cpp\MinGW64\lib\gcc\x86_64-w64-mingw32\4.9.2\include\c++\bits\c++0x_warning.h [Error] #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options. C:\Users\余伟杰\Desktop\RSA.cpp In function 'bool isPrime(long long int, int)': 33 5 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'random_device' was not declared in this scope 34 5 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'mt19937' was not declared in this scope 35 5 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'uniform_int_distribution' was not declared in this scope 35 30 C:\Users\余伟杰\Desktop\RSA.cpp [Error] expected primary-expression before 'long' 38 27 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'gen' was not declared in this scope 38 30 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'dis' was not declared in this scope C:\Users\余伟杰\Desktop\RSA.cpp In function 'long long int generateLargePrime(int)': 59 5 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'random_device' was not declared in this scope 60 5 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'mt19937' was not declared in this scope 61 5 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'uniform_int_distribution' was not declared in this scope 61 30 C:\Users\余伟杰\Desktop\RSA.cpp [Error] expected primary-expression before 'long' 65 21 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'gen' was not declared in this scope 65 24 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'dis' was not declared in this scope C:\Users\余伟杰\Desktop\RSA.cpp In function 'void generateRSAKeys(RSAKey&, RSAKey&, int)': 103 22 C:\Users\余伟杰\Desktop\RSA.cpp [Error] 'gcd' was not declared in this scope 108 22 C:\Users\余伟杰\Desktop\RSA.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 108 15 C:\Users\余伟杰\Desktop\RSA.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 109 23 C:\Users\余伟杰\Desktop\RSA.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 109 16 C:\Users\余伟杰\Desktop\RSA.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 C:\Users\余伟杰\Desktop\RSA.cpp In function 'std::vector<long long int> rsaEncrypt(const string&, const RSAKey&)': 115 19 C:\Users\余伟杰\Desktop\RSA.cpp [Error] range-based 'for' loops are not allowed in C++98 mode 117 19 C:\Users\余伟杰\Desktop\RSA.cpp [Error] redeclaration of 'long long int c' 115 15 C:\Users\余伟杰\Desktop\RSA.cpp [Note] 'char c' previously declared here C:\Users\余伟杰\Desktop\RSA.cpp In function 'std::string rsaDecrypt(const std::vector<long long int>&, const RSAKey&)': 126 24 C:\Users\余伟杰\Desktop\RSA.cpp [Error] range-based 'for' loops are not allowed in C++98 mode C:\Users\余伟杰\Desktop\RSA.cpp In function 'int main()': 147 24 C:\Users\余伟杰\Desktop\RSA.cpp [Error] range-based 'for' loops are not allowed in C++98 mode
最新发布
07-07
<think>我们遇到了关于C++11标准、随机数生成器和范围for循环的编译错误。让我们一步步解决这些问题。 ### 常见编译错误及解决方案 #### 1. **C++11标准支持问题** - 范围for循环(`for (char c : message)`)需要C++11或更高版本 - 解决方案:编译时添加`-std=c++11`标志 **示例编译命令:** ```bash g++ -std=c++11 rsa.cpp -o rsa ``` #### 2. **`<random>`头文件缺失** - 确保包含必要的头文件: ```cpp #include <random> #include <algorithm> // 用于std::gcd ``` #### 3. **`std::gcd`未定义错误** - C++17标准引入了`std::gcd`,在早期版本中需手动实现: ```cpp long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); } ``` #### 4. **随机数生成器兼容性问题** - `random_device`和`mt19937`是C++11标准库的一部分 - 确保编译器支持C++11 ### 修改后的兼容代码 ```cpp #include <iostream> #include <cmath> #include <vector> #include <random> #include <algorithm> // 包含std::gcd(C++17)或自定义实现 // 手动实现gcd函数(若编译器不支持C++17) #if __cplusplus < 201703L long long gcd(long long a, long long b) { while (b) { long long t = b; b = a % b; a = t; } return a; } #else using std::gcd; #endif // 扩展欧几里得算法(保持不变) long long modInverse(long long a, long long m) { /* 原有实现 */ } // Miller-Rabin测试(注意:pow函数可能溢出,需替换为模幂) bool isPrime(long long n, int k = 5) { if (n <= 1 || n == 4) return false; if (n <= 3) return true; // 将n-1分解为d*2^s long long d = n - 1; while (d % 2 == 0) d /= 2; std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<long long> dis(2, n - 2); for (int i = 0; i < k; i++) { long long a = dis(gen); long long x = modExp(a, d, n); // 使用模幂替换pow,防止溢出 if (x == 1 || x == n - 1) continue; bool prime = false; long long temp = d; while (temp != n - 1) { x = (x * x) % n; temp *= 2; if (x == 1) break; if (x == n - 1) { prime = true; break; } } if (!prime) return false; } return true; } // 其他函数保持不变... int main() { // 测试代码... } ``` ### 关键修改说明 1. **GCD函数兼容性**: - 使用预处理器指令检查C++版本 - C++17以下版本提供手动实现的GCD函数 2. **Miller-Rabin测试优化**: - 将`pow(a, d)`替换为`modExp(a, d, n)`避免整数溢出 - 使用模幂运算确保大数计算的安全性 3. **编译器标志**: - 务必在编译时添加`-std=c++11`(或更高版本)标志 ### 编译与运行示例 ```bash # 使用G++编译 g++ -std=c++11 -o rsa rsa.cpp # 运行程序 ./rsa ``` ### 常见问题排查 - **错误:'gcd' is not a member of 'std'** 解决方案:使用手动实现的gcd函数 - **错误:range-based 'for' loops are not allowed in C++98** 解决方案:添加编译选项`-std=c++11` - **错误:'random_device' is not a member of 'std'** 解决方案:包含`<random>`头文件并确保使用C++11 > **注意**:大素数生成时`pow(2, bits)`可能导致溢出,建议使用位运算`(1LL << bits)`替代[^1]。 §§相关问题§§ 1. 如何检查C++编译器的默认标准版本? 2. C++11与C++17在随机数生成方面有哪些改进? 3. 如何处理大整数运算中的溢出问题?</think>### C++ RSA 实现中的随机数生成器与 C++11 编译错误解决方案 在使用 C++ 实现 RSA 算法时,常见的编译错误主要涉及随机数生成器(`random_device`, `mt19937`)和 C++11 标准支持问题。以下是完整解决方案: --- #### 问题 1:`random_device` 和 `mt19937` 未定义错误 **错误信息示例:** ``` error: 'random_device' is not a member of 'std' error: 'mt19937' was not declared in this scope ``` **解决方案:** ```cpp{1,2,5} // 添加必要的头文件 #include <random> // 随机数库头文件 #include <algorithm> // 用于 std::gcd // 使用正确的命名空间 std::random_device rd; // 正确声明 std::mt19937 gen(rd()); // 正确初始化 ``` --- #### 问题 2:C++11 标准支持问题 **错误信息示例:** ``` error: range-based 'for' loops are not allowed in C++98 mode ``` **解决方案:** 1. **编译时添加 C++11 标志**: ```bash g++ -std=c++11 -o rsa rsa.cpp # GCC clang++ -std=c++11 -o rsa rsa.cpp # Clang ``` 2. **IDE 配置**(以 VSCode 为例): 在 `tasks.json` 中添加: ```json "args": ["-std=c++11", "-o", "rsa"] ``` --- #### 问题 3:范围 for 循环错误 **错误信息示例:** ``` error: expected ';' before ':' token ``` **解决方案:** ```cpp{1,4} // 传统循环替代范围 for 循环 // 原代码: for (char c : message) for (int i = 0; i < message.length(); i++) { char c = message[i]; // 后续处理... } ``` --- ### 完整修正代码示例 ```cpp{1,3,5,7,9} #include <iostream> #include <cmath> #include <vector> #include <random> // 关键添加 #include <algorithm> // 关键添加 // 手动实现 gcd (兼容旧标准) long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); } // 修正的 Miller-Rabin 测试 bool isPrime(long long n, int k = 5) { // ... [同原实现,但使用传统循环替代范围for循环] ... // 使用正确的随机数生成器 std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<long long> dis(2, n-2); for (int i = 0; i < k; i++) { long long a = dis(gen); // ... [后续代码] ... } } // 其他函数保持不变... ``` --- ### 关键修改说明 1. **头文件补充**: - `<random>`:提供 `random_device` 和 `mt19937` - `<algorithm>`:提供 `std::gcd`(需 C++17,旧版本需手动实现) 2. **随机数生成器修正**: ```cpp std::random_device rd; // 正确命名空间 std::mt19937 gen(rd()); // 正确初始化 ``` 3. **循环兼容性**: - 将范围 for 循环 `for (char c : message)` 改为传统索引循环 - 保持算法逻辑不变 4. **编译标准指定**: - 必须使用 `-std=c++11` 编译选项 > **注意**:在 MSVC 编译器中,C++11 是默认启用的,但 GCC 和 Clang 需要显式指定[^1]。 --- ### 测试验证 编译并运行修正后的代码: ```bash g++ -std=c++11 -o rsa rsa.cpp && ./rsa ``` 应输出: ``` 公钥 (n, e): (320027, 65537) 私钥 (n, d): (320027, 257633) 原始消息: Hello 加密结果: 12445 30123 14207 14207 18456 解密结果: Hello ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值