• C++学习 day--21 地震监测系统实现、内存泄漏检测工具


    1、项目需求

    地震监测系统主要是利用地震检波器收集到的地壳运动信息,从而预测和确定地震的震中以
    及强度。
    预测方法
    地震检波器每隔固定的时间间隔采样一次预测地震的能量数据,并保存到文件中,地震监测
    系统会从文件中读取相应的能量数据,测试在给定的时间点上,一个短时间窗口内的取样值
    与一个长时间窗口内取样值的商,如果这个比例高于给定的阈值,那么在这个事件点上极有
    可能发生地震。
    取样方法 :无论短/长时间内的取样值都是使用给定点 8能量数据的 平方加上该点之前的一小部分点能量值的平方之和再求平均值
    如:某个时间点的及之前的7个能量数据如下,时间间隔是:0.01秒,短时间周期取2
    个点,长时间周期取5个点:
    则: 短时间窗口内的取样值:
    (5x5 + 4x4 + 2x2) / 3 = 15
    长时间窗口内的取样值:
    (5x5 + 4x4 + 2x2 +1x1 + 1x1) / 5 = 9

    1.问题描述:

    使用数据文件中的一组地震检波器测量值确定可能的地震事件的位置。

    2. 输入输出描述:

    (1)程序的输入是名为seismic.dat的数据文件和用于计算短时间能量和长时间能量的取样值的数目。 输出是给出关于潜在的地震事件次数的报告
    (2)seismic.dat 的结构是这样的,第一行包含两个值: 地震检波器能量值的数目和时间间隔 ,从第二行开始就是能量值的数据,以空格分开。
    (2) 短时间窗口和长时间窗口的值可以由键盘读入。
    (3) 判定地震事件给定的阀值是 1.5
    seismic.dat 中的数据如下:
    11 0.01
    1 2 1 1 1 5 4 2 1 1 1

     可能还没有人搞懂这个项目的意思,我画一张图来帮助理解:

    这是我们提供的数据,一共11个地震检波器的数值,间隔为0.01秒,间隔为0,01秒是什么意思,很多人没搞懂。

    假设我们现在输入的短窗口值为2,长窗口值为5,那么我们先选中最前面5个数字,如上图黄色部分的数值,从右边往左算,计算每个值的平方然后求和,最后除以5。即:1*1+1*1+1*1+2*2+1*1=8,然后8/5=1.6这是计算长窗口的,同理短窗口也一样的,如上图红色部分,1*1+1*1=2,然后2/2=1,然后用1/1.6=0.625<1.5,1.5是我们规定的一个阈值,如果短窗口与长窗口的平均能量值比例大于1.5那么就会发生地震,我们知道现在长窗口有5个值,每个值间隔时间为0.01。那么最后一个值的下标为4,间隔为0.04,即4*0.01=0.04。说白了每一个时间点的能量值的时间为它的下标*0.01。

    然后项目就结束了??当然没有,我们还要往后检索,直到所有数据都检查完为止,那么接下来往后移一个位置,如下:

    按上边的方法计算:

    短窗口的平均能量值比例:1*1+1*1=2,2/2=1

    长窗口的平均能量值比例:1*1+1*1+1*1+1*1+2*2=8,8/5=1.6

    1/1.6  = 0.625 < 1.5,说明还是没有可能发生地震的点。

    再往右移一位:

    短窗口的平均能量值比例:5*5+4=26,  26/2=13

    长窗口的平均能量值比例:26+3=29,29/5=5.8

    然后13/5.8 = 2.24137>1.5,我们发现大于1.5,大于规定的阈值了,那么我们认为这个时间点可能会发生地震事件。此时长窗口最右边那个值为5,它的下标为6,那么这个时间点就是0.01*6=0.06秒。这个时间点可能发生地震事件。

    然后再往右移一位,做同样的计算,知道算到最右边的值。然后记录中间哪些时间点可能发生地震事件。

    代码实现如下:

    1. #include <fstream>
    2. #include <string>
    3. #include <iostream>
    4. #include <cmath>
    5. using namespace std;
    6. const double THRESHOLD = 1.5;//阈值
    7. //统计短/长事件窗口对应能量的采样值
    8. double power_w(double arr[], int length, int n) {
    9. double xsquare = 0;
    10. for (int i = 0; i < n; i++) {
    11. xsquare += pow(arr[length - i], 2);
    12. }
    13. return xsquare / n;
    14. }
    15. int main() {
    16. string filename;
    17. ifstream fin;
    18. int num = 0, short_window = 0, long_window = 0;
    19. double time_incr = 0, * sensor = NULL, short_power = 0, long_power = 0;
    20. double ratio;
    21. cout << "Enter name of input file:" << endl;
    22. cin >> filename;
    23. fin.open(filename.c_str());
    24. if (fin.fail()) {
    25. cerr << "error opening input file:" << endl;
    26. exit(-1);
    27. }
    28. else {
    29. fin >> num >> time_incr;//分别读入地震检波器能量值的数目和时间间隔
    30. cout << "num: " << num << " time_incr: " << time_incr << endl;
    31. if (num >= 0) {
    32. sensor = new double[num];
    33. for (int i = 0; i < num; i++) {
    34. fin >> sensor[i]; //读入能量值
    35. }
    36. cout << "Enter number of points for short-window:" << endl;
    37. cin >> short_window;
    38. cout << "Enter number of points for long-window:" << endl;
    39. cin >> long_window;
    40. //分析能量数据找出地震事件
    41. for (int i = long_window - 1; i < num; i++){
    42. short_power = power_w(sensor, i, short_window);
    43. long_power = power_w(sensor, i, long_window);
    44. ratio = short_power / long_power;
    45. if (ratio > THRESHOLD) {
    46. cout << " Possible event at " << time_incr * i << "seconds\n";
    47. }
    48. }
    49. delete[] sensor;
    50. }
    51. fin.close();
    52. }
    53. return 0;
    54. }

    运行结果:

     

    可以根据运行结果自己手动检验一遍。

    到此这个小项目完整结束。我们发现编程序并不难,理解项目的功能有点费劲,因此很多软件开发前期都大量在做需求分析,真正编码的时间很少。

    到这里我们看一到小题来训练一下编程思维吧:

    在一次竞赛中, A B C D E 等五人经过激烈的角逐,最终取得了各自的名次,他们的一个好朋友很遗憾没有观看到比赛,在比赛结束后这个朋友询问他们之间的名次是得知:C 不是第一名, D E 低二个名次,而 E 不是第二名, A 即不是第一名,也不是最后一名,B C 低一个名次。编写程序,计算这五个人各自的名次并输出。

    1. #include<iostream>
    2. using namespace std;
    3. int main() {
    4. int A, B, C, D, E;
    5. for (A = 2; A <= 4; A++) {
    6. for (B = 2; B <= 5; B++) {
    7. for (C = 2; C <= 5; C++) {
    8. for (D = 3; D <= 5; D++) {
    9. for (E = 1; E <= 3; E++) {
    10. if (B - 1 == C && D - 2 == E && A != B && A != C && A != D && A != E
    11. && B != C && B != D && B != E && C != D && C != E && D != E) {
    12. cout << "A:" << A << endl;
    13. cout << "B:" << B << endl;
    14. cout << "C:" << C << endl;
    15. cout << "D:" << D << endl;
    16. cout << "E:" << E << endl;
    17. }
    18. }
    19. }
    20. }
    21. }
    22. }
    23. }

    注意:B比C低一名的数量关系,比如,A第3,那么B就是第2名,即B - 1 = C。

    运行结果:

    2、职场修炼 

    面对老鸟抱怨 , 比较妥善的态度 :

    礼貌谦逊的态度

    态度很重要,不仅仅体现的是你个人的素质问题,更重要的是影响你和他人的互动关系,社会就是人与人的关系综合体。 职场如战场,充斥着形形色色的人,也就会有各种各样复杂的关系。礼貌、谦虚的人总是更受他人喜欢,无论是领导还是同事,都讨厌那些耍个性的人。生僻怪异的性格只能让你无法融入到团队。

    积极乐观的心态

    任何一个行业都不是我们一眼看起来那么简单的,必须要有时间和实践的沉淀,方能获得真知。一年入门,三年入行,五年入道,七年入定,十年入化,请记住! 遇到困难时,要乐观面对,遇到工作不顺时,要及时调整好心态,心存希望,你才会有希望。少一点抱怨,因为抱怨解决不了任何问题,只会让事情更糟糕。多与传递正能量的人交流相处,不要被那些消极负面的人带进黑暗的深渊。

    3、逼格提升:内存泄漏检测工具

    VisualC++ debugger CRT
    第一步: 包含以下头文件
    #define _CRTDBG_MAP_ALLOC
    #include
    #include
    第二步: 接管 new 操作符
    #ifdef _DEBUG
    #ifndef DBG_NEW
    #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ ,__LINE__)
    #define new DBG_NEW
    #endif
    #endif
    第三步: 在代码结束出输出内存泄漏信息
    _CrtDumpMemoryLeaks();
    内存泄漏工具:
    Windows : Purify,BoundsCheaker Deleaker VisualLeak Detector VLD ,
    Linux 平台: Valgrind memcheck

    这个步骤试试过了,并没有输出内存泄漏信息,可能是编译器的问题。 

    1. #define _CRTDBG_MAP_ALLOC
    2. #include
    3. #include
    4. #include
    5. #ifdef _DEBUG
    6. #ifndef DBG_NEW
    7. #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ ,__LINE__)
    8. #define new DBG_NEW
    9. #endif
    10. #endif
    11. using namespace std;
    12. int main() {
    13. int* p = new int[10];
    14. for (int i = 0; i < 10; i++) {
    15. p[i] = i;
    16. }
    17. //打印
    18. for (int i = 0; i < 10; i++) {
    19. cout << i << " ";;
    20. }
    21. //未释放申请的内存区域
    22. _CrtDumpMemoryLeaks();
    23. }

    发现并没有输出泄漏信息,但是在Visual C++ 2010上好像可以输出泄漏信息。 

    为了检测内存泄漏建议大家安装一个VLD工具就可以查看内存泄漏信息了。 我已经安装好了,自己可以找教程安装一下,但是据说VLD工具暂停更新了,对VS2015后的版本不适用,要手动设置才能使用。

    现在我惊安装好了,我们来看一下:

    1. #include<vld.h> //内存泄漏检测工具头文件
    2. #include<stdio.h>
    3. #include<iostream>
    4. using namespace std;
    5. int main() {
    6. int* p = new int[10];
    7. for (int i = 0; i < 10; i++) {
    8. p[i] = i;
    9. }
    10. //打印
    11. for (int i = 0; i < 10; i++) {
    12. cout << i << " ";;
    13. }
    14. cout<<endl;
    15. //未释放申请的内存区域
    16. }

    #include 

    这个是内存泄漏头文件!!不用的时候不添加即可,用的时候在添加

    我们只申请了40个字节没有释放,下面那个76不是我们关心的,是数据结构中的东西。我们只需要关注前面带Block块那部分发生的内存泄漏即可。如果代码改为如下再运行看看:

     

     我们发现,没有发横内存泄漏了。

  • 相关阅读:
    r5 5600g和i5 12400选哪个好
    DevOps 必备的 Kubernetes 安全清单
    字面量运算符/字面量操作符
    python SCPClient 远程文件 到 本地
    AVUE 富文本编辑器 avue-plugin-ueditor 图片上传 ver.0.2.7
    【论文阅读笔记】NTIRE 2022 Burst Super-Resolution Challenge
    【微信小程序】三分钟学会小程序的列表渲染
    三.Postman接口实践
    uniapp开发的多端APP源码
    dflow入门2——Slices
  • 原文地址:https://blog.csdn.net/qq_51956388/article/details/134081545