目录
1. fstream中读取文件结束标志问题:
eofbit:当文件中所有数据均被读取完毕且再次读取一次发现无数据时才为TRUE,即eofbit标志
上一次读取文件的操作是否失败。当读取完最后一个数据时,此时eof()仍返回TRUE,只有再进行
一次读取操作,eofbit才置位,eof()才返回TRUE
EOF:文件最后一个数据的下一个位置为EOF数据,可通过peek()来判断下一个数据是否为EOF来判断文件是否读取结束,此方法更好
peek():预读文件下个位置的数据,但不影响文件内容,用此判断文件读取结束更好
正常读取结束
判断的文件数据数量比实际数量多1,用eof()进行判断应在读取之后,判断数据个数应在eof()之后
2. 关于数组定义时大小用变量的问题:
在项目属性里设置,这会在整个项目里生效,依次选择:属性->配置属性->C/C++ ->预处理器->预处理器定义
最后面直接加上:_CRT_SECURE_NO_WARNINGS
_CRT_SECURE_NO_WARNINGS此类警告非C++官方定义,而是VS内部自行定义的,VS认定某些方法存在安全隐患,故而设置此种不安全警告,通过上述方法可以取消此种警告
VS中在项目配置中修改预处理器限制,可实现
int a=10; int b[a];
此类代码,并且可正常运行相关程序。但此种用法与C++标准相违背,C++标准中在上述情况下数组大小不允许使用变量。此种方法为gcc相关扩展。
C++中数组使用栈内存,堆栈均在运行时分配内存,但栈大小有限,若使用变量,无法提前确定栈大小,变若量大小超出限制则栈空间不足,会导致数据覆盖的问题;常量大小有助于编译时确定栈大小。因此,不建议使用上述方法,动态数组使用动态分配即可,上述情况知道就行。
详细可参照:http://t.csdn.cn/vjfn9
3. 读取文件时文件格式问题
读取文件的方法有很多,但是需注意,在读取时一定要注意文件内容的存放格式,若为通常UTF-8,则无问题,但如果文件的内容是从其他软件复制过来,则可能会出现数据存放类型不同,从而导致使用UTF-8类型读取的代码无法正确读取其他类型的数据。(此时数据在txt中的显示均正常)如:
正常情况输出到文件中的存储类型(编码方式)为UTF-8,此时可正常读取
此处举例为matlab中复制过来的数据,编码为UTF-16 L,此时便无法正常读取
若文件中数据为matlab中直接写入文件,则类型相同,此处应该是显示时的格式不同,从而导致复制的结果格式也不同
注:文件路径中有中文时,打开文件可能会失败
4. 全局变量及命名空间中的全局变量
全局变量的定义建议放于cpp中(防止使用时出现重定义问题,放头文件中往往被包含不止一次,若头文件只被包含一次,则无问题),使用时需注意,全局变量的定义只能存在一份,而声明可以由多份
// a.cpp
int a = 1; // 定义
// b.cpp
extern int a; // 声明
// c.cpp
extern int a; // 声明
命名空间中的全局变量声明及定义与正常(全局命名空间下)的全局变量定义及声明使用方式相同,只不过相关代码需写在相关命名空间中
// a.cpp
namespace tjz
{
int a = 1;
}
// b.cpp
namespace tjz
{
extern int a;
}
5. acos输入要求及输入精度问题
acos要求输入数据范围为[-1, 1],但在某些情况下入数据可能非常接近1或-1但精度上不是(例如:1.000000000457,此时输出结果在未显示多位小数情况下是1),从而导致结果计算错误显示nan。
此种问题不一定是中间计算过程有误,可能为精度导致的结果偏差从而使输入与-1和1不匹配。此时若确定输入无误只有精度问题时,可使用fmaxl和fminl或其他方法修改输入数据使数据保持在[-1, 1]之间。
其余函数可能存在类似问题,故在此提供一种思想。
6. Win32中内存复制错误
VS中若一数组或vector数据过大,则在Win32环境下内存中会出现复制错误,此时应更换为x64环境。(项目中遇见3G大小数据复制出现问题)
7. C++贝塞尔函数
相关贝塞尔函数存在于cmath头文件中,且输入类型不存在复数类型
第一类贝塞尔函数:
double cyl_bessel_j(double nu, double x);
float cyl_bessel_jf(float nu, float x);
long double cyl_bessel_jl(long double nu, long double x);
第一类修正贝塞尔函数:
double cyl_bessel_i(double nu, double x);
float cyl_bessel_if(float nu, float x);
long double cyl_bessel_il(long double nu, long double x);
第二类贝塞尔函数:
double cyl_neumann(double nu, double x);
float cyl_neumannf(float nu, float x);
long double cyl_neumannl(long double nu, long double x);
第二类修正贝塞尔函数:
double cyl_bessel_k(double nu, double x);
float cyl_bessel_kf(float nu, float x);
long double cyl_bessel_kl(long double nu, long double x);
8. C++多线程中使用随机数需注意
基本随机数使用方式:
#include <ctime>
int main()
{
srand((unsigned)time(NULL));
// srand()中设置随机数种子,从而使得rand()中获得的随机数序列不同,种子默认为1
// 故若不设置随机数种子,rand()函数每次获得的随机数序列相同
// 一般采用当前系统时间作为种子,从而确保每次种子均不同
// 采用srand(time(0))写法相同
int ra = rand() % 10;
return 0;
}
- srand()在使用时一般只使用一次即可满足后续对随机数的需求,time的单位为1s
- 若使用多次,则当程序运行速度过快时,在1s内重复执行多次srand函数,重新赋予相同种子,则会导致每次的随机数相同
- 故一般应确保srand函数只运行一次
多线程中随机数使用方式:
#include <ctime>
#include <thread>
void xiancheng()
{
srand(time(0));
int ra = rand() % 10;
}
int main()
{
thread th1(xiancheng);
return 0;
}
- 多线程中,srand需在每个线程内部重新使用
- 在主线程中使用srand不会对子线程有影响,此时若子线程直接调用rand则相当于未调用srand,主线程中的srand只对主线程中rand起作用,每个子线程均需重新调用srand
多线程中多子线程随机数种子相同解决方案:
#include <ctime>
#include <thread>
#include <windows.h>
void xiancheng()
{
LARGE_INTEGER nStartCounter;
QueryPerformanceCounter(&nStartCounter);
srand((unsigned)nStartCounter.LowPart);
int ra = rand() % 10;
}
int main()
{
thread th1(xiancheng);
thread th2(xiancheng);
thread th3(xiancheng);
return 0;
}
- 多子线程随机数种子相同的原因是:多个线程在1s内同时产生从而导致time(0)读取到相同的时间
- time(0)单位为1s,故而使用毫秒或微秒级的时钟即可解决此类问题,上诉代码只是一种方案,其余能获得更高精度时钟的方法具有相同效果