c++入门题(易错)~
1隐藏的排序
题目描述
每个箱子都有长宽高,我们需要判断一个箱子能否放入另一个箱子中。
例如有箱子A的尺寸是 3 x 4 x 5,箱子B的尺寸 是 5 x 6 x 4,经过比较判断,可以知道箱子A能够放入箱子B中,我们就说箱子A匹配箱子B。
注意,当两个箱子尺寸相等,我们也认为它们匹配。
输入给你的是 “长、宽、高” 三个数,但没规定哪个是哪个,箱子可以旋转,所以不能直接按输入顺序比,必须先排序。
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
long a[3];
long b[3];
cin>>a[0]>>a[1]>>a[2];
cin>>b[0]>>b[1]>>b[2];
sort(a,a+3);
sort(b,b+3);
if((a[0]<=b[0]&&a[1]<=b[1]&&a[2]<=b[2])||(a[0]>=b[0]&&a[1]>=b[1]&&a[2]>=b[2]))
{
cout<<"yes"<<endl;
}
else
{
cout<<"no"<<endl;
}
}
return 0;
}
2字符串
题目描述
有一种古典加密方法就是按照字母表顺序,把每个字母循环右移k位,从而转换为加密的另一个字母。
例如偏移2位,即A对应C,B对应D,……X对应Z,Y对应A,Z对应B;同样a对于c,b对应d,……x对应z,y对应a,z对应b。
如果输入的不是字母则忽略无需加密,例如数字和标点符号就不用加密
当前设定加密规则是:循环右移4位,对于输入的字符,只对字母进行加密,字母区分大小写,其他字符例如数字、标点符号等不做加密,直接输出。
提示:字符串处理可以使用C++的string
#include<iostream>
#include<string>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
string a;
cin>>a;
for(int i=0;i<a.size();i++)
{
if(a[i]>='A'&&a[i]<='Z')
{
a[i]=a[i]+4;
if(a[i]>'Z')
{
a[i]=a[i]-26;
}
}
else if(a[i]>='a'&&a[i]<='z')
{
a[i]=a[i]+4;
if(a[i]>'z')
{
a[i]=a[i]-26;
}
}
}
cout<<a<<endl;
}
return 0;
}
3矩阵转置
题目描述
写一个函数,使给定的一个二维数组(3×3)转置,即行列互换。
输入
一个3x3的矩阵
输出
转置后的矩阵
转置的本质就是:把 a[i][j] 和 a[j][i] 交换
你的困惑很关键:void 函数不 return 任何东西,那它是怎么把转置后的矩阵交给外界的?
答案:通过修改数组本身来实现
你的 transpose 函数直接修改了传入的二维数组 a 的内容。
而数组在 C++ 中是按地址传递的(更准确地说,数组名会退化为指向首元素的指针)。
所以函数里对 a[i][j] 的任何修改,都会直接作用在原数组上,不需要 return 一个值。
#include<iostream>
using namespace std;
void trans(int a[3][3])
{
for(int i=0;i<3;i++)
{
for(int j=i+1;j<3;j++)//只换上三角:1因为若换两次则相当于没换,不能换下三角;2,对角线可以不用换
{
int tem=a[i][j];
a[i][j]=a[j][i];
a[j][i]=tem;//这样才能实现双方互换!
}
}
}
int main()
{
int a[3][3];
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
cin>>a[i][j];
}
}
trans(a);
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
cout<<a[i][j];
if(j<2)//每三个换一行
{
cout<<" ";
}
}
cout<<endl;
}
return 0;
}
4
题目描述
编写一个函数int substr(char str1[],char str2[],int index),其作用是,将从字符串str1 (长度超过30) 的第index个字符开始的所有字符复制,生成新的字符串str2,如果成功生成,函数返回1,如果不能成功生成,返回0
-
人类说“第 1 个字符”,指的是字符串开头的第一个。
-
计算机里,数组位置从 0 开始编号。所以“第 1 个”在计算机里是下标 0,“第 2 个”是下标 1……
公式:计算机下标 = 人类的第几个 - 1
getline(cin, a) 和 cin >> t 之间的换行符冲突
你在 cin >> t; 后使用了 getline(cin, a);。
但 cin >> t; 会在输入流里留下一个换行符 '\n',getline 一上来会读到一个空行,导致 a 是一个空字符串。
解决方法:在 cin >> t; 后面加一个 cin.ignore(); 吃掉这个换行符。
并且用cin.getline(数组,数组有多少个)
substr 函数没有给 str2 末尾添加 '\0'
字符串必须以 '\0' 结尾,否则输出时会乱码或越界。
解决方法:在复制完字符后手动补一个 '\0'
#include<iostream>
#include<cstring>
using namespace std;
int substr(char str1[],char str2[],int index)
{
int len=strlen(str1) ;
if(index>len||index<1)
{
return 0;
}
for(int i=0;i<strlen(str1)-index+1;i++)
{
str2[i]=str1[index+i];
}
str2[strlen(str1)-index+1]='\0';
//如何判断成功与否? 通过对比长度和index
return 1;
}
int main()
{
int t;
cin>>t;
cin.ignore();
while(t--)
{
char a[100]={0};
char b[100]={0};
cin.getline(a,100);//数组,个数
int index;
cin>>index;
cin.ignore();
if(substr(a,b,index)==1)
{
cout<<b<<endl;
}
else
{
cout<<"IndexError"<<endl;
}
}
return 0;
}
5指针
题目描述
请定义一个基类型为int的指针变量p。
读入一个变量i,若i为0,将p赋值为空;若为1,将p赋值为变量i的地址。
判断该指针变量值是否为空。
若为空输出“NULL”;否则,输出“Initialized”。
⚠️ 易错点
-
判断对象错误
-
题目要求判断指针本身是否为空(
p == NULL),而不是指针指向的值(*p == 0)。 -
如果写成
if (*p == 0),当i恰好为 0 时也能输出"NULL",但这不符合题意:题目是要根据i来设置指针的空与非空,再判断指针状态。
-
✅ 正确逻辑(步骤)
-
读入整数
i。 -
声明指针
int* p = NULL;(安全初始化为空)。 -
根据
i的值设置p:-
若
i == 0,p = NULL; -
否则(题目暗示
i为 1),p = &i;
-
-
判断指针
p是否等于NULL:-
若
p == NULL,输出"NULL"; -
否则,输出
"Initialized"。#include<iostream> using namespace std; int main() { int* p=NULL; int i; cin>>i; if(i==0) { p=NULL; cout<<"NULL"<<endl; } else { p=&i; cout<<"Initialized"<<endl; } return 0; }
-
6动态矩阵
题目描述
未知一个整数矩阵的大小,在程序运行时才会输入矩阵的行数m和列数n
要求使用指针,结合new方法,动态创建一个二维数组,并求出该矩阵的最小值和最大值,可以使用数组下标法。
不能先创建一个超大矩阵,然后只使用矩阵的一部分空间来进行数据访问、
创建的矩阵大小必须和输入的行数m和列数n一样
#include<iostream>
using namespace std;
int main()
{
//1,输入行列
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
//2,建立二维数组,new
int**a=new int* [n];
for(int i=0;i<n;i++)
{
a[i]=new int [m];
}
//3,输入二维数组
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>a[i][j];
}
}
//4,遍历数组得到最大最小值
int max;
int min;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(i==0&&j==0)
{
max=min=a[0][0];
}
else
{
if(a[i][j]<min)
{
min=a[i][j];
}
if(a[i][j]>max)
{
max=a[i][j];
}
}
}
}
cout<<min<<" "<<max<<endl;
//6,释放内存
for(int i=0;i<n;i++)
{
delete[]a[i];
}
delete[]a;
}
return 0;
}
7常量指针
const int* p;
拆开读:
-
int→ 整数 -
*→ 指针(存放地址) -
const在*前面 → 指针指向的那个整数是“只读”的
翻译成人话:p 是一张纸条,上面写着一个门牌号。你拿着纸条可以去那个房间看里面的东西,但不能在房间里乱涂乱画(不能通过 *p 修改值)。
但是,纸条本身可以擦掉重写,让它指向另一个房间(让 p 指向别的变量)。
题目描述
设定以下汇率常量
美元汇率为6.2619,表示1美元兑换6.2619元人民币
欧元汇率为6.6744,表示1欧元兑换6.6744元人民币
日元汇率为0.0516,表示1元日元兑换0.0516元人民币
港币汇率为0.8065,表示1元港币币兑换0.8065元人民币
定义一个常量指针,根据需求指针指向不同的汇率,然后计算出各种货币兑换为人民币的数量
要求:不能直接使用汇率常量进行计算,必须使用常量指针,只能使用一个指针
#include<iostream>
#include<iomanip>//涉及浮点输出小数多少位
using namespace std;
int main()
{
//1,输入一个t表示有t个测试实例
int t;
cin>>t;
int t1=t;
double result=0;
double a=6.2619;
double b=6.6744;
double c=0.0516;
double d=0.8065;
while(t--)
{
//2, 定义一个常量指针
const double* p=0;
//3,输入货币类型和数量
char type;
double num;
cin>>type>>num;
//4,输出兑换后的人民币数量
if(type=='D')
{
p=&a;
}
else if(type=='E')
{
p=&b;
}
else if(type=='Y')
{
p=&c;
}
else if(type=='H')
{
p=&d;
}
result=(*p)*num;
cout<<fixed<<setprecision(4)<<result<<endl;
}
return 0;
}
8字符串和字符
题目描述
输入一个字符串,判断这个字符串是否一个完全整数值的字符串,例如输入"1234",那么表示整数1234,输入"12a3"就表示只是一个字符串,不是一个整数
要求编写函数isNumber,参数是一个字符指针,返回值是整数类型
如果字符串表示一个整数,则计算出这个整数并且返回
如果字符串不是表示一个整数,则返回-1
主函数必须调用isNumber来判断字符串,不能使用任何C++自带或第三方的类似函数
❌ 错误分析
| 代码 | 错误 |
|---|---|
int isNumber(char* p[]) |
参数应为 char* p 或 char s[],不是指针数组 |
p[i] < '\0' |
p[i] 是 char*,不能与字符比较 |
p[i] >= 0 && p[i] <= 9 |
判断数字字符应写 '0' ~ '9',不是 ASCII 码 0~9 |
return p |
返回类型是 int,却返回指针 |
✅ 正确逻辑
正确写法:直接写 isNumber(a)。数组名 a 会自动退化为指向首元素的指针(char*)
-
遍历字符串每个字符,如果某个字符不是
'0'~'9',直接返回-1。 -
如果全部是数字字符,则用“霍纳法则”转换为整数:(char转为int)
result = result * 10 + (当前字符 - '0') -
返回计算结果。
-
不需要处理前导零,因为算法会自动忽略(如
"0012"会算出12)。 -
char*或char[]是字符串(字符数组),可以用[] - 以
isNumber(const char* s)中的参数s虽然写的是char*,但它指向的是一个字符数组(字符串),自然可以用s[i]来遍历每一个字符。 -
为什么
isNumber(&a)类型不对?a是char[1000],&a的类型是char (*)[1000](指向整个数组的指针),不是char*。函数isNumber的参数是char*,类型不匹配,编译会报错。#include<iostream> using namespace std; //1编写函数isNumber,参数是一个字符指针,返回值是整数类型 //2字符串表示一个整数,则计算出这个整数并且返回 //3字符串不是表示一个整数,则返回-1 int isNumber(char* p) { int result=0; for(int i=0;p[i]!='\0';i++) { if(p[i]<'0'||p[i]>'9') { return -1; } else { result=result*10+(p[i]-'0'); } } return result; } //4输入一个字符串 int main() { int t; cin>>t; char a[1000]={0}; while(t--) { cin>>a; cout<<isNumber(a)<<endl; } return 0; } //5输出8字符串数组
题目描述
已知每个月份的英文单词如下,要求创建一个指针数组,数组中的每个指针指向一个月份的英文字符串,要求根据输入的月份数字输出相应的英文单词
#include<iostream> #include<string> using namespace std; int main() { string* p[13]; string a1="January"; string a2="February"; string a3="March"; string a4="April"; string a5="May"; string a6="June"; string a7="July"; string a8="August"; string a9="September"; string a10="October"; string a11="November"; string a12="December"; p[1]=&a1; p[2]=&a2; p[3]=&a3; p[4]=&a4; p[5]=&a5; p[6]=&a6; p[7]=&a7; p[8]=&a8; p[9]=&a9; p[10]=&a10; p[11]=&a11; p[12]=&a12; int t; cin>>t; while(t--) { int num; cin>>num; if(num<1||num>12) { cout<<"error"<<endl; } else { cout<<*p[num]<<endl; } } return 0; } /*string months[12] = {"January", "February", "March", ...}; for (int i = 0; i < 12; i++) { p[i+1] = &months[i]; // p[1]指向January,... }*/9指针访问数组
题目描述
有一种方式是使用密钥进行加密的方法,就是对明文的每个字符使用密钥上对应的密码进行加密,最终得到密文
例如明文是abcde,密钥是234,那么加密方法就是a对应密钥的2,也就是a偏移2位转化为c;明文b对应密钥的3,就是b偏移3位转化为e,同理c偏移4位转化为g。这时候密钥已经使用完,那么又重头开始使用。因此明文的d对应密钥的2,转化为f,明文的e对应密钥的3转化为h。所以明文abcde,密钥234,经过加密后得到密文是cegfh。
如果字母偏移的位数超过26个字母范围,则循环偏移,例如字母z偏移2位,就是转化为b,同理字母x偏移5位就是转化为c
要求:使用三个指针p、q、s分别指向明文、密钥和密文,然后使用指针p和q来访问每个位置的字符,进行加密得到密文存储在指针s指向的位置。
除了变量定义和输入数据,其他过程都不能使用数组下标法,必须使用三个指针来访问明文、密钥和密文。
提示:当指针q已经移动到密钥的末尾,但明文仍然没有结束,那么q就跳回密钥头
#include<iostream> #include<cstring> using namespace std; int main() { char* p; char* q; char* s; char a[1000]; char b[1000];//数字串也是字符串 char c[1000]; int t; cin>>t; while(t--) { cin>>a; cin>>b; p=a; q=b; s=c; while(*p!='\0') { if(*q=='\0') { q=b; } int offset=*q-'0';//数字串转整数 if(*p>='a'&&*p<='z') { *s=(*p-'a'+offset)%26+'a'; } else if(*p>='A'&&*p<='Z') { *s=(*p-'A'+offset)%26+'A'; } p++; q++; s++; } cout<<c<<endl; } return 0; }*s = (*p - 'a' + offset) % 26 + 'a';的原理 -
公式部分 作用 对应的题目要求 *p - 'a'将小写字母 'a'~'z'转换成数字0~25方便进行数值偏移计算 + offset加上密钥中对应的数字(由 *q - '0'得到)“每个字符使用密钥上对应的密码进行加密” % 26若加完后的数字 ≥26,则取余数,自动绕回开头 “字母偏移的位数超过26个字母范围,则循环偏移”(例如 z偏移2位变成b)+ 'a'将 0~25的数字重新转换回小写字母 ASCII 码得到最终的密文字符,确保是字母 -
int offset=*q-'0';//数字串转整数
-
这一行是把密钥中的数字字符转换成真正的整数。
题目给的密钥是一个“数字串”,比如
"234",它在程序里实际上是字符'2'、'3'、'4',而不是可以直接运算的整数 2、3、4。 -
'2'的 ASCII 码是 50,'0'的 ASCII 码是 48,相减得到整数 2。 -
'3' - '0'= 51-48 = 3 -
'4' - '0'= 52-48 = 4
更多推荐

所有评论(0)