C++学习路线(十九)

devtools/2024/10/23 7:18:01/

函数返回值指针

#include <iostream>
using namespace std;int* add(int x, int y) {// 定义一个指针int* sum = NULL;// 让指针指向堆内存 也就是sum的值是堆的地址sum = new int;*sum = x + y;// 返回指针 以拷贝的方式返回// 也就是 外部的sum指针指向的地址和堆内存的地址是一样的return sum;
}
int* add1(int x, int y) {int sum = x + y;//将这个局部变量的地址返回return &sum;
}
//因为 上面的sum的存储期是 auto 所以 它会在函数执行完毕后自动释放内存
//也就是sum这个地址里面存的是垃圾值 因为是在栈上分配的// 因为是静态变量 所以只会在第一次调用的时候分配内存 分配到静态区 不会被清理
int* add2(int x, int y) {static int num = 0;num = x + y;return &num;
}
int main() {int a = 3, b = 5;int* sum = NULL;sum = add2(a, b);cout << "Sum is: " << *sum << endl;return 0;
}

常见错误总结

1.申请的内存多次释放
2.内存泄漏
3.释放的内存不是申请时的地址
4.释放空指针
5.释放一个内存块,但继续引用其中的内容
6.越界访问

#include <iostream>
using namespace std;int main() {//1.多次释放内存int* p = new int[10];delete[] p;//--------//2.内存泄漏do {int* p = new int[1000000000];} while (1 == 1);//3.释放的时候不是申请时候的地址int* p2 = new int[10];for (int i = 0; i < 10; i++) {cout << *(p2++) << endl;}delete[] p2; // 这个时候的p2 已经不是申请时候的地址了,所以会导致内存泄漏//4,释放空指针//我们构造一种情况int* pfile = NULL;if (1) { // 加入能打开文件pfile = new int[2048];}// 这里的if语句中,有可能发生异常,导致pfile为NULL,此时应该释放pfiledelete[] pfile; // 释放空指针//5.释放一个内存块 但在引用里面的内容int* p4 = new int[10];delete[] p4; // 释放p4p4[0] = 1; // 引用里面的内容//6.越界访问int* p5 = new int[10];for (int i = 0; i <= 10; i++)p5++; // 越界访问}

具体开发需求

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

算法设计

1)读取文件头并分配内存;
2)从数据文件读取地震数据,从键盘读取计算能量的短时间和长时间窗口测量值的数目;
3)计算各个时间点上的短时间窗口和长时间窗口的能量值,打印出可能的地震事件时间。在这里,因为会涉及到频紧调用短窗口和长窗口量位我们可以将计算能量值设计为单独的一个函数

#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;
#define MAXN 1024
double threshold = 1.5;
int dot[MAXN] = { 0 };double calValue(int left, int right) {double sum = 0;for(int i  =left ; i <= right ; i ++ )sum += pow(dot[i] , 2);return sum / (right - left + 1);
}int main() {string path = "E:\\c++file\\地震.txt";ifstream file(path);if (!file.is_open()) {cout << "文件打开失败!" << endl;exit(1);}int dotLen;double betweenLen;file >> dotLen >> betweenLen;for (int i = 0; i < dotLen; i++) {if(file.eof()) break;file >> dot[i];if (file.fail()) {cout << "数据格式错误!" << endl;exit(1);}}int longLen, shortLen;cout << "请输入长波峰长度:";cin >> longLen;cout << "请输入短波峰长度:";cin >> shortLen;assert(longLen > 0 && shortLen > 0);assert(longLen > shortLen && longLen < dotLen && shortLen < dotLen);for (int index = longLen - 1; index < dotLen; index++ ) {double longValue = calValue(index - longLen + 1, index);double shortValue = calValue(index - shortLen + 1, index);double diff = shortValue / longValue;if (diff > threshold) {cout << betweenLen * index << endl;}}file.close();return 0;
}

编程思维修炼

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

列出已知条件

  1. C 不是第一名。
  2. D 比 E 低两个名次。
  3. A 既不是第一名,也不是最后一名。
  4. B 比 C 低一个名次。

 步骤 1: 分析条件 1 和 3

  • C 不是第一名,因此 C 只能是第 2、3、4 或 5 名。
  • A 既不是第一名也不是最后一名,所以 A 只能是第 2、3 或 4 名。
  • C=2,3,4,5 
  • A = 2,3,4

 步骤 2: 分析条件 2 和 4

  • D 比 E 低两个名次。如果 D 是第 3 名,那么 E 必须是第 1 名;如果 D 是第 4 名,E 就是第 2 名;如果 D 是第 5 名,E 就是第 3 名。
  • B 比 C 低一个名次。这意味着如果 C 是第 2 名,B 就是第 3 名;如果 C 是第 3 名,B 就是第 4 名;如果 C 是第 4 名,B 就是第 5 名。
  • E,D 1,3 2,4 3,5
  • C,B 1,2 2,3 3,4 4,5

 我的想法 遍历 c , 可以确定b 然后我们遍历a和 e  可以确定d 然后看看有没有符合的

#include <iostream>
#include <map>
using namespace std;int main() {// 我们遍历C 2-5for (int c = 2; c <= 4; c++) {int b = c + 1;for (int a = 2; a <= 4; a++) {for (int e = 1; e <= 3; e++) {if (e == 2) continue;int d = e + 2;map<int, int> mp;mp[a] = 1;mp[b] = 1;mp[c] = 1;mp[d] = 1;mp[e] = 1;if(mp.size() == 5)cout << "a:" << a << " b:" << b << " c:" << c << " d:" << d << " e:" << e << endl;}}}return 0;
}

内存泄漏工具

使用 c++库来检测内存泄露

第一步  包含头文件

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

第二步 接管new操作符

#ifdef _DEBUG
#ifndef DBG_NEW
#define DBG_NEW new ( _NORMAL_BLOCK, __FILE__, __LINE__ )
#define new DBG_NEW
#endif
#endif 

第三步 在代码结束输出泄露的信息

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>#include <iostream>
#include <Windows.h>
using namespace std;#ifdef _DEBUG
#ifndef DBG_NEW
#define DBG_NEW new ( _NORMAL_BLOCK, __FILE__, __LINE__ )
#define new DBG_NEW
#endif
#endif void func() {int* p = new int[128];
}
int main() {for (int i = 0; i < 5; i++) {func();Sleep(100);}_CrtDumpMemoryLeaks();
}

点击本地调试 不要点击release

内存泄漏工具

Windows : Purify,BoundsCheaker 、Deleaker、VisualLeak Detector(VLD )

Linux:Valgrind memcheck

项目练习

1.编写一个程序,链接两个字符串字面常量,将结果保存在一个动态分配的 char数组中。重写这个程序,连接两个标准string 对象。

#include <iostream>
using namespace std;char* linkTwoString(const char* str1, const char* str2) {char* result = new char[strlen(str1) + strlen(str2) + 1];strcpy(result, str1);strcat(result, str2);return result;
}char* linkTwoString_2(const string& str1, const string& str2) {char* result = new char[str1.length() + str2.length() + 1];strcpy(result, str1.c_str());strcat(result, str2.c_str());return result;
}int main() {char* result = linkTwoString("Hello", "World");cout << result << endl;delete[] result;char* result2 = linkTwoString_2("Hello", "World");cout << result2 << endl;return 0;
}

2.编写一个程序,使用 cin,从标准输入输入3段文字,保存到一段动态分配的内存中,每一段文字输入后,必须要即时保存到动态内存中。

#include <iostream>
#include <cstring> // For strcpy, strcat, strlen
#include <cstdlib> // For malloc, free
#include <string>int main() {// 初始分配一小块内存char* dynamicMemory = (char*)malloc(1);if (dynamicMemory == nullptr) {std::cerr << "内存分配失败!" << std::endl;return 1;}dynamicMemory[0] = '\0'; // 初始化为一个空字符串// 定义每段文本的最大长度const int maxLength = 100;for (int i = 1; i <= 3; ++i) {std::cout << "请输入第 " << i << " 段文字(最多 " << maxLength - 1 << " 个字符): ";// 使用std::string临时存储输入std::string inputString;std::getline(std::cin, inputString);// 计算新的内存大小size_t newLength = strlen(dynamicMemory) + inputString.size() + 1; // +1 for null terminatorchar* temp = (char*)realloc(dynamicMemory, newLength * sizeof(char));if (temp == nullptr) {std::cerr << "内存分配失败!" << std::endl;return 1;}dynamicMemory = temp;// 将输入的字符串复制到动态内存中strcat(dynamicMemory, inputString.c_str());}// 输出结果std::cout << "您输入的所有文本:" << std::endl;std::cout << dynamicMemory << std::endl;// 释放动态分配的内存free(dynamicMemory);dynamicMemory = nullptr;return 0;
}

3.下列程序的功能是:首先,根据输入的二维数组的行数和列数,动态地为该数组分配存储空间;

其次,向二维数组中输入数据;最后输出该数组中的所有元素。请完善下面的程序。

#include <iostream>
using namespace std;
int main() {int rows, cols;printf("Enter the number of rows and columns: ");cin >> rows >> cols;int** arrays = (int**)malloc(rows * sizeof(int*));if (!arrays) {printf("Memory allocation failed.\n");return 1;}//为每一行分配内存for (int i = 0; i < rows; i++) {arrays[i] = (int*)malloc(cols * sizeof(int));if (!arrays[i]) {printf("Memory allocation failed.\n");return 1;}}printf("Enter the elements of the matrix:\n");for(int i = 0 ; i < rows ; i ++ )for(int j = 0 ; j < cols ; j ++ )cin >> arrays[i][j];printf("The matrix is:\n");for(int i = 0 ; i < rows ; i ++ ) {for(int j = 0 ; j < cols ; j ++ )printf("%d ", arrays[i][j]);printf("\n");}//释放内存for (int i = 0; i < rows; i++) {free(arrays[i]);}free(arrays);return 0;
}

这个是使用指针 

#include <iostream>
using namespace std;
int main() {int rows, cols;printf("Enter the number of rows and columns: ");cin >> rows >> cols;int** arrays = (int**)malloc(rows * sizeof(int*));if (!arrays) {printf("Memory allocation failed.\n");return 1;}//为每一行分配内存for (int i = 0; i < rows; i++) {*(arrays + i) = (int*)malloc(cols * sizeof(int));if (!(arrays + i)) {printf("Memory allocation failed.\n");return 1;}}printf("Enter the elements of the matrix:\n");for (int i = 0; i < rows; i++)for (int j = 0; j < cols; j++)cin >> *(*(arrays + i) + j);printf("The matrix is:\n");for(int i = 0 ; i < rows ; i ++ ) {for(int j = 0 ; j < cols ; j ++ )printf("%d ", *(*(arrays + i) + j));printf("\n");}//释放内存for (int i = 0; i < rows; i++) {free(arrays[i]);}free(arrays);return 0;
}


http://www.ppmy.cn/devtools/128099.html

相关文章

三维重建新范式对比与发展趋势

1.概述 本文重点对比三维视觉的新范式&#xff0c;主要是NeRF与 3D gausslain splatting在3维重建发展的趋势进行对比与说明。 2.NeRF趋势 3.3D GS趋势 4.动态场景重建的趋势

k8s中的存储

一 configmap 1.1 configmap的功能 configMap用于保存配置数据&#xff0c;以键值对形式存储。 configMap 资源提供了向 Pod 注入配置数据的方法。 镜像和配置文件解耦&#xff0c;以便实现镜像的可移植性和可复用性。 etcd限制了文件大小不能超过1M 1.2 configmap的使用场…

计算机网络最后错题本-cy

第一章 边缘部分并不能为应用程序进程通信提供服务&#xff0c;它基于核心部分提供的数据传输服务从而实现设备间的互相通信&#xff0c;正确的说法应是“核心部分为应用程序进程通信提供服务” 电路交换 电路交换方式的优点是传输时延小、通信实时性强&#xff0c;适用于交互式…

RabbitMQ系列学习笔记(五)--持久化机制

文章目录 一、概念二、队列持久化三、消息持久化 本文参考&#xff1a; 尚硅谷RabbitMQ教程丨快速掌握MQ消息中间件rabbitmq RabbitMQ 详解 Centos7环境安装Erlang、RabbitMQ详细过程(配图) 一、概念 在RabbitMQ系列学习笔记&#xff08;四&#xff09;–消息应答机制中我们已…

C语言初阶小练习4(不用临时变量交换数值)

题目&#xff1a;不能创建临时变量&#xff08;第三个变量&#xff09;&#xff0c;实现两个整数的交换 1.用临时变量来实现(常规写法) 这种方法是最直观的&#xff0c;但题目要求不使用临时变量&#xff0c;所以这里仅作为对比参考。 用创建临时变量来写&#xff1a;逻辑清晰…

【付费】Ambari集成Dolphin实战-002-bigtop下编译dolphin——下

3.2 编译过程记录 3.2.1 do-component-build 执行 17:28:50.944 [ERROR] [system.err] + STATUS=0 17:28:50.944 [ERROR] [system

某ai gpt的bug

某ai gpt的bug 背景 遇到了一个奇怪的现象&#xff1a; 输入内容 2024-10-21 10:09:31,052 ERROR o.a.j.t.JMeterThread: Test failed! java.lang.IllegalArgumentException:输出结果

Python实现基于WebSocket的stomp协议调试助手工具分享

stomp协议很简单&#xff0c;但是搜遍网络竟没找到一款合适的客户端工具。大多数提供的都是客户端库的使用。可能是太简单了吧&#xff01;可是即便这样&#xff0c;假如有一可视化的工具&#xff0c;将方便的对stomp协议进行抓包调试。网上类似MQTT的客户端工具有很多&#xf…