首页 > 编程语言 >C++学习路线(十九)

C++学习路线(十九)

时间:2024-10-18 11:50:14浏览次数:3  
标签:rows int ++ C++ 路线 arrays printf include 十九

函数返回值指针

#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,此时应该释放pfile
	delete[] pfile; // 释放空指针

	//5.释放一个内存块 但在引用里面的内容
	int* p4 = new int[10];
	delete[] p4; // 释放p4
	p4[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-5
	for (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 terminator
        char* 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;
}

标签:rows,int,++,C++,路线,arrays,printf,include,十九
From: https://blog.csdn.net/weixin_45169583/article/details/143023109

相关文章

  • 这会是你见过最全的AI产品经理学习路线!你学会了吗?我学废了!
    AI产品经理学习路线:从新手到专家的全面指南引言AI产品经理的角色结合了人工智能技术和产品管理的精髓,是一个新兴且充满挑战的领域。本指南旨在为你提供一个全面的学习路线,从基础到高级,帮助你逐步成为一名出色的AI产品经理。了解AI基础目标:建立对人工智能的基本理解,包括......
  • 初学者浅析C++类与对象
    C++类与对象classclass基本语法classClassName{public://公有成员TypememberVariable;//数据成员ReturnTypememberFunction();//成员函数声明private://私有成员TypeprivateMemberVariable;//数据成员ReturnTypepriva......
  • 运维工程师的发展路线
    运维行业近年来随着技术的快速发展发生了显著的变化,从传统的服务器管理到自动化、云计算和DevOps等方向都有巨大的发展潜力。以下是几个在运维领域可以考虑的发展方向,它们结合了当下技术趋势,有助于为你提供更多职业选择:1.云运维与云架构师随着越来越多的企业转向云计算,云......
  • 嵌入式学习路线,大学四年规划:从大一小白到嵌入式大佬
    大学四年转瞬即逝,到了找工作的时候,就会发现同学们之间的差距真的挺大的,有的同学轻轻松松就能拿到心仪的offer,而有些人却四处碰壁,甚至找不到工作。为什么会有这么大差距呢?其实主要是因为大学四年从开始就没有一个很清晰的职业定位以及针对性的学习规划。对于电子、通信、计算......
  • 2024年网络安全进阶手册:黑客技术自学路线
    ......
  • 新手入门大模型,2024最新学习路线!
    最近有很多同学想要学习大模型,于是我根据多年的学习经验,总结了一些适合你从0到1的入门经验,分享给大家呀1、几个学习大模型必备:教程:动手学大模型DiveintoLLMs《动手学大模型DiveintoLLMs》:内容丰富,从基础概念到实际操作都有详细讲解,通过实践案例帮助理解大模......
  • C++需要把析构函数定义为虚函数的场景
    C++需要把析构函数定义为虚函数的场景contentC++中将析构函数定义为虚函数的作用在C++中,将析构函数定义为虚函数(virtual)的主要目的是为了在多态(polymorphism)场景下正确地销毁对象,避免内存泄漏或资源未正确释放的问题。1.问题背景:非虚析构函数的风险在C++中,当你通过基......
  • TowardsDataScience-博客中文翻译-2022-二十九-
    TowardsDataScience博客中文翻译2022(二十九)原文:TowardsDataScience协议:CCBY-NC-SA4.0如何使用计算机视觉读取酒瓶上的标签?(第一部分)原文:https://towardsdatascience.com/how-to-read-a-label-on-a-wine-bottle-using-computer-vision-part-1-25447f97a761欢迎阅读本......
  • 南沙C++信奥赛陈老师解一本通题 1284:摘花生
    ​【题目描述】HelloKitty想摘点花生送给她喜欢的米老鼠。她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。HelloKitty只能向东或向南走,不能向西或......
  • 每日OJ题_牛客_非对称之美_最长非回文字符串_C++_Java
    目录牛客_非对称之美_最长非回文字符串题目解析C++代码Java代码牛客_非对称之美_最长非回文字符串非对称之美(nowcoder.com)题目解析找到规律就是最长非回文字符串(判断是否全同->0,否则是n-1(回文减去1)或n)。C++代码#include<iostream>usingnamespacestd;int......