1.输入与输出
本题要求根据火车的出发时间和达到时间,编写程序计算整个旅途所用的时间。
输入:
在一行中给出 2 个 4 位正整数,其间以空格分隔,分别表示火车的出发时间和到达时间。每个时间的格式为 2 位小时数(00-23)和 2 位分钟数(00- 59),假设出发和到达在同一天内。
输出:
在一行输出该旅途所用的时间,格式为“hh:mm”,其中 hh 为 2 位小时数、mm 为 2 位分钟数
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
// 读取出发和到达时间的小时和分钟
int startHour, startMin, endHour, endMin;
scanf("%2d%2d %2d%2d", &startHour, &startMin, &endHour, &endMin);
// 计算总分钟数
int startTotalMinutes = startHour * 60 + startMin;
int endTotalMinutes = endHour * 60 + endMin;
// 如果到达时间小于出发时间,则假设它是次日到达
if (endTotalMinutes < startTotalMinutes) {
endTotalMinutes += 24 * 60;
}
int durationMinutes = endTotalMinutes - startTotalMinutes;
// 计算小时和分钟
int hours = durationMinutes / 60;
int minutes = durationMinutes % 60;
// 输出结果
cout << setw(2) << setfill('0') << hours << ":" << setw(2) << setfill('0') << minutes << endl;
return 0;
}
2.循环分支与判断
从键盘输入任意正整数,判断该数是否是回文数。所谓回文数就是从左到右读这个数与从右到左读这个数是一样的。例如12321、1221都是回文数。
输入:
测试案例的个数n
第一个测试值
第二个测试值
…
第n个测试值
输出:
各个测试值是否是回文数,是,就输出Yes,不是,就输出No
#include <iostream>
#include <iomanip>
#include <vector>
std::string reverseString(const std::string &str) {
int n = str.length();
std::string reversedStr;
reversedStr.reserve(n); // 为逆序字符串预留空间
for (int i = n - 1; i >= 0; --i) {
reversedStr.push_back(str[i]);
}
return reversedStr;
}
int main(){
std::cout<<"how many integers are you going to type in ?"<<std::endl;
int n;
scanf("%d",&n);
std::vector<std::string> numbers;
numbers.reserve(n);
for(int i=0;i<n;++i){
std::string temp;
std::cout << "Enter number " << (i + 1) << ": ";
std::cin >> temp;
numbers.push_back(temp);
}
for (std::string num : numbers){
if (num==reverseString(num)){
std::cout<<"Yes"<<std::endl;
}
else{
std::cout<<"No"<<std::endl;
}
}
}
3.函数的定义和使用
本题要求实现一个简单函数,能计算给定的年份和月份的天数。使得可以利用该函数,输出给定年份中每个月的天数,其中1、3、5、7.8、10、12月有31天,4、6、9、11月有30天,2月平年有28天,闰年有29天。要求定义并调用函数month_days(year,month),该函数返回year年month月的天数
输入:
年year
输出:
该年1~12月每个月的天数
#include <iostream>
#include <iomanip>
// 判断是否为闰年
bool isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 获取指定年份和月份的天数
int month_days(int year, int month) {
switch (month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
return 31;
case 4: case 6: case 9: case 11:
return 30;
case 2:
return isLeapYear(year) ? 29 : 28;
default:
return 0; // 无效月份
}
}
int main() {
int year;
std::cin >> year; // 输入年份
// 输出该年份每个月的天数
for (int month = 1; month <= 12; ++month) {
std::cout << month_days(year, month) << " ";
}
return 0;
}
4.数组
给你一个整数数组nums,请你用冒泡排序将该数组升序排列。
示例 1:
输入: nums = [5,2,3,1]输出:[1,2,3,5]
示例 2:
输入: nums = [5,1,1,2,0,0]输出:[0,0,1,1,2,5]
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include <algorithm>
// 函数来交换两个元素的值
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
// 冒泡排序函数
void bubbleSort(std::vector<int> &arr) {
int n = arr.size();
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < n - i - 1; ++j) {
if (arr[j] > arr[j + 1]) {
swap(arr[j], arr[j + 1]);
}
}
}
}
// 主函数
int main() {
std::vector<int> arr;
std::string input;
std::getline(std::cin, input);
input.erase(0,8);
input.erase(remove(input.begin(), input.end(), ']'), input.end());
std::stringstream ss(input);
std::string item;
while (getline(ss, item, ',')) { // 使用逗号作为分隔符
arr.push_back(stoi(item)); // 将分割后的字符串转换为整数并添加到向量中
}
bubbleSort(arr); // 调用冒泡排序函数
std::cout << '[';
for (size_t i = 0; i < arr.size(); ++i) {
std::cout << arr[i];
if (i < arr.size() - 1) {
// 如果不是最后一个元素,则在后面添加逗号和空格
std::cout << ", ";
}
}
std::cout << ']';
return 0;
}
5.二维数组
方阵循环右移
题目描述:
本题要求编写程序,将给定nxn方阵中的每个元素循环在该行内右移m个位置。
输入:
第一行给出两个正整数m和n (1<=n<=6) 。接下来一共n行,每行n个整数,表示一个n阶的方阵
输出:
按照输入格式输出移动后的方阵: 即输出n行,每行n个整数,每个整数后输出一个空格。
#include <iostream>
#include <vector>
int main(){
int m,n;
std::cin>>m>>n;
std::vector<std::vector<int>> matrix(n, std::vector<int>(n)), matrix1(n, std::vector<int>(n));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
std::cin >> matrix[i][j];
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
int new_position = (j + m) % n;
matrix1[i][new_position] = matrix[i][j];
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
std::cout << matrix1[i][j]<<" ";
}
std::cout<<std::endl;
}
return 0;
}
6.结构体
结构体
题目描述:
从键盘输入若干个学生的信息,每个学生信息包括学号、姓名、3门课的成绩,计算每个学生的总分,输出总分最高的学生的信息。
输入:
首先输入一个整数n(1<=n<=100),表示学生人数,然后输入n行,每行包含一个学生的信息: 学号(12位) 、姓名(不含空格且不超过20位),以及三个整数,表示语文、数学、英语三门课成绩,数据之间用空格隔开。
输出:
输出总成绩最高的学生的学号、姓名、及三门课成绩,用空格隔开。若有多个最高分,只输出第一个。
#include <iostream>
#include <vector>
struct Student{
std::string name;
int id;
int score[3];
int total;
};
int main(){
int n;
std::cin >> n;
std::vector<Student> students(n);
for (int i =0;i<n;++i){
std::cin >> students[i].id >> students[i].name >> students[i].score[0] >> students[i].score[1] >> students[i].score[2];
students[i].total = students[i].score[0] + students[i].score[1] + students[i].score[2];
}
int maxIndex = 0;
for (int i = 1; i < n; ++i) {
if (students[i].total > students[maxIndex].total) {
maxIndex = i;
}
}
std::cout << students[maxIndex].id << " "
<< students[maxIndex].name << " "
<< students[maxIndex].score[0] << " "
<< students[maxIndex].score[1] << " "
<< students[maxIndex].score[2] << std::endl;
return 0;
}
7.指针
int n ;int *n ; int ** n 是什么意思?
在 C++ 中,指针是用于存储变量地址的变量。
int n;
:这是一个普通的整型变量n
的声明,它可以存储一个整数值。int *n;
:这是一个整型指针变量n
的声明。它可以存储一个整数的地址,而不是整数本身。你可以使用这个指针来访问和修改它指向的整数。int **n;
:这是一个指向整型指针的指针变量n
的声明,也称为二级指针。它可以存储另一个整型指针的地址。这通常用于动态数组、动态二维数组,或者当你想要通过引用来修改一个指针时。
下面是每种声明的例子和它们的使用方法:
int n = 5; // 普通整型变量
int *ptr = &n; // 指针变量,存储变量n的地址
int **pptr = &ptr; // 二级指针变量,存储指针ptr的地址
在这个例子中:
-
n
存储了一个值5
。 -
ptr
存储了n
的地址,并可以用来间接访问n
(例如*ptr
会给你n
的值)。 -
pptr
存储了ptr
的地址,并可以用来间接访问ptr
本身(例如*pptr
会给你ptr
的值,而**pptr
会给你n
的值)。
8.了解函数传参的不同方式和变量作用域
试运行以下代码,分析为什么效果不同。
#include<iostream>
using namespace std;
void swap(int a,int b){//值传递
int t=a;
a = b;
b= t;
}
void swap1(int *a,int *b){//传指针
int t=*a;
*a = *b;
*b= t;
}
int main(){
int a=2,b=3;
swap(a,b);
cout<<"a="<<a<<"b="<<b<<endl;
a=2;b=3;
swap1(&a,&b);
cout<<"a="<<a<<"b="<<b<<endl;
}
swap
函数使用值传递,它接收两个整数的拷贝,对这些拷贝进行交换。由于它们是拷贝,所以原始的 a
和 b
的值不会被交换。
swap1
函数使用指针,它接收两个整数的地址,并通过指针直接在内存中交换它们的值。这样,原始的 a
和 b
的值确实会被交换。
9.内存
介绍C++的内存分区情况。C++动态分配内存用什么方法?为什么需要这么做?用 new 关键字自定义长度的数组。
C++程序的内存分为几个部分,每部分用于存储不同类型的数据:
- 栈(Stack):由编译器自动分配释放,存放函数的参数值、局部变量等。其操作方式类似于数据结构中的栈。
- 堆(Heap):一般由程序员分配释放,若程序员不释放,则程序结束时可能由操作系统回收。用于动态内存分配。
- 全局/静态存储区(Global/Static Storage):存放全局变量和静态变量。
- 文字常量区:常量字符串就是放在这里的。程序结束后由系统释放。
- 程序代码区:存放函数体的二进制代码。
在C++中,动态内存分配是指在程序运行时(而非在编译时)分配内存。动态内存分配是必要的,因为有时候直到程序运行时我们才知道需要多少内存,例如用户输入数据的大小或者根据文件大小分配内存。
动态分配内存的方法:
在C++中,动态内存分配主要通过new
和delete
关键字来管理。
使用new
关键字可以在堆上分配内存。当你使用new
时,内存会从堆上分配,并且new
会返回指向分配的内存的指针。当你不再需要这块内存时,你应该使用delete
来释放它,防止内存泄漏。
例如,自定义长度的数组:
#include <iostream>
int main() {
int size = 0;
std::cout << "Enter the size of the array: ";
std::cin >> size;
int* myArray = new int[size]; // 动态分配数组
// 使用数组...
for (int i = 0; i < size; i++) {
myArray[i] = i;
}
for (int i = 0; i < size; i++) {
std::cout << myArray[i] << " ";
}
std::cout << std::endl;
delete[] myArray; // 释放数组
return 0;
}
在上面的例子中,new int[size]
动态地在堆上分配了一个数组。这意味着我们可以在运行时决定数组的大小。然后我们使用delete[]
来释放数组内存。
注意,动态分配的单个变量使用delete
来释放,而动态分配的数组则需要使用delete[]
来释放。
为什么需要动态分配内存:
- 灵活性:动态内存分配让程序可以根据实际需要分配内存,这在处理不确定大小的数据或大量数据时非常有用。
- 控制:它给程序员更多的控制权,可以精细地管理内存的生命周期。
- 生存期:动态分配的内存在堆上,它的生存期不受局部作用域的限制,可以在函数调用结束后继续存在,直到用
delete
释放。
正确管理动态分配的内存是非常重要的,因为不当管理会导致内存泄漏或者野指针等错误。现代C++推荐使用智能指针如std::unique_ptr
或std::shared_ptr
来自动管理内存,以避免这些问题。
10.指针与堆内存分配
动态矩阵
题目描述:
未知一个整数矩阵的大小,在程序运行时才会输入矩阵的行数m和列数n要求使用指针,结合new方法,动态创建一个二维数组,并求出该矩阵的最小值和最大值,可以使用数组下标法。不能先创建一个超大矩阵,然后只使用矩阵的一部分空间来进行数据访问、创建的矩阵大小必须和输入的行数m和列数n一样
输入:
第一行输入t表示t个测试实例
第二行输入两个数字m和n,表示第一个矩阵的行数和列数第三行起,连续输入m行,每行n个数字,表示输入第一个矩阵的数值依次输入t个实例
输出:
每行输出一个实例的最小值和最大值
#include <iostream>
#include <limits>
#include <vector>
int main() {
int t;
std::cin >> t; // 读取测试实例个数
std::vector<std::pair<int, int>> values;
while (t--) {
int m, n;
std::cin >> m >> n; // 读取矩阵大小
// 动态创建二维数组
int** matrix = new int*[m];
for (int i = 0; i < m; ++i) {
matrix[i] = new int[n];
}
// 读取数据并找到最小值和最大值
int min_value = std::numeric_limits<int>::max();
int max_value = std::numeric_limits<int>::min();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
std::cin >> matrix[i][j];
if (matrix[i][j] < min_value) {
min_value = matrix[i][j];
}
if (matrix[i][j] > max_value) {
max_value = matrix[i][j];
}
}
}
values.push_back({min_value, max_value});
// 删除二维数组
for (int i = 0; i < m; ++i) {
delete[] matrix[i];
}
delete[] matrix;
}
for (const auto& value : values) {
std::cout << value.first << " " << value.second << std::endl;
}
return 0;
}