ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

C++零基础入门:从变量、指针到分支循环的习题式学习指南

C++零基础入门:从变量、指针到分支循环的习题式学习指南

简介:广州大学计算机C++课程的习题答案合集,面向C++初学者、在校本科生及考研复习者。内容覆盖变量与数据类型、运算符与表达式、控制结构、函数、数组、指针等核心章节,以选择题与解答形式梳理常见易错点,如标识符合法性、八进制和十六进制常量写法、运算符优先级、逻辑表达式求值,以及指针与引用交换变量等问题;同时配有将数学表达式改写为C++算术表达式、用逻辑表达式表示条件的习题解答,方便对照自查。资源共1个doc文件,压缩包约1.55MB,轻量易用,下载后可直接按章节查阅。已有442人学习使用,尤其适合课后刷题巩固与考前快速复习,可帮助读者进一步检查对C++语法细节的把握,减少编译和运行阶段的常见错误。

1. C++零基础入门最容易被卡死的瞬间:不是代码难,是该从哪句开始读

很多零基础同学翻开C++教材,第一感受是“全是英文,是不是得先背单词”。其实C++没你想的那么玄——它就是让计算机照做的指令,比发朋友圈的输入格式更严格而已。这份资料是一套“带答案的C++入门练习册”,用选择、改错、读程序、写程序四类题目,把变量、运算符、分支循环、指针这些第一学期最常考的知识点挨个过一遍。它不把原理讲成天书,只负责让你确认“我想对了没”。刚开C++课、连编译器都没装过的新手,完全可以把它当同伴。别急着背答案,先自己写,再对照——这是它最好用的方式。

2. 先搞懂一个关键问题:C++到底怎么把代码变成结果的

在动手做题之前,有三个问题值得先想明白:C++是什么、程序怎么跑起来、这份答案式资料到底能帮你什么。这一章不写代码,只帮你把脑子里的模糊印象擦干净。

2.1 为什么第一门编程课几乎都选C++:你是在学“指挥计算机”的思维方式

为什么零基础入门往往从C++开始,而不是那些“更好上手”的语言?因为C++愿意把底层的东西摊开给你看。你写int a = 5,它就真的在内存里找一块地方,放进一个整数5;你写int *p = &a,它就把这块地方的地址交到你手里。这种“看得见内存”的感觉,是很多更省事的语言不会主动展示给你的。新手学C++,与其说是背语法,不如说是在建立一种“我说一句,机器做一步”的思维方式。

C++也没有传说中那么不近人情。变量名可以起成age、score这种一眼能看懂的名字;每条语句用一个分号告诉编译器“这句话到此结束”。习题1第3题专门考了这一点:C++程序中的简单语句必须以分号结束。看起来是送分题,但新手写完程序被编译器打回来,十有八九就是漏了分号。这些细节单看都很小,连在一起,就是你能否顺利写完第一个程序的差距。

我第一次学C++时的感受是:它像一套乐高说明书,每个零件都有固定的插法,不按规则拼,机器就不理你。这份习题集里的选择题,大部分就是在帮你确认“零件这么插对不对”。你不需要把每个选项背下来,但要把“为什么对、为什么错”想明白。这样到了考试或者自己写程序的时候,你才能真正用出来,而不是靠蒙。

2.2 从源代码到可执行程序:编译器、编译错误和运行错误要分清

你写的.cpp文件是给人看的,计算机只认机器码。把源代码翻译成可执行程序的过程,叫作编译。习题1第2题问“源程序要变为目标程序必须要经过什么”,答案就是编译。你用任意一款常见C++开发环境写完代码,点“运行”按钮时,编译器会在后台做这样几件事:检查单词和符号拼得对不对、括号配没配齐、变量类型用没用对,全部通过后才生成能运行的程序。

新手经常把编译错误和运行错误混为一谈,看到报错就慌。其实只要分清两类:第一类是编译阶段报的错,通常是语法写错了,比如少个分号、多个花括号,编译器会明确告诉你“第几行出了什么问题”,按提示改就行;第二类是运行阶段的错,程序能启动,但执行到某一步出了状况,比如习题1第5题说的“溢出”——数字太大,超出了变量能装的范围。做题时养成先看报错类别的习惯,后面自己调程序能少走很多弯路。

这里有一个很常见的“黑匣子”误区:新手总以为代码过了编译就等于程序对了。其实编译通过只说明语法没问题,逻辑对不对还得靠运行结果判断。习题2.3思考题6就是典型案例:程序能编译,但因为把==写成了=,运行结果完全错误。所以跑通一次程序之后,一定要盯着输出结果追问一句:它真的符合我的预期吗?

2.3 这套带答案的习题怎么用:先做题、再对答案、把错题重写一遍

这套资料里的题目大致分四类:选择题帮你确认概念、读程序题练你“在脑子里运行代码”、思考题把易混点掰开讲、编程题让你真正动手。新手最容易犯的错,是拿到带答案的资料就直接看解答,看完觉得“这不难嘛”,合上书自己一写就卡住。这种“眼睛会了手不会”的落差,几乎每个人都会经历一次。

我建议你按这个顺序用:第一步,做题前把书合上,只拿题目当任务。编程题想不出完整代码,也至少要写出思路,比如“先取百位、再取十位、最后取个位”。第二步,选择题不要只看正确选项,把每个错误选项为什么错也标出来。比如习题1第7题问合法标识符,正确选项是_abc,那你就要知道new是关键字、π是特殊字符、双引号括起来的“age”是字符串常量,都不能当标识符。第三步,对答案时重点看自己卡在哪一步,而不是只看结果对不对。这样才能让错误变成经验。

读程序题是性价比最高的训练。每一道都先别运行,在纸上写出你认为的输出结果,再拿上机结果对照。最开始一定会写错,错了正好——你从错误里学到的,比看十遍答案都多。这套方式坚持下来,你对变量、运算符、分支、循环这几个基础主题的理解,会比单纯看解答扎实得多。

另外,别担心学C++会和“做实际项目”脱节。很多你以后会接触的技术,比如操作系统、嵌入式开发、游戏引擎的底层,都和C++关系密切。第一学期把它学扎实,后面学其他语言会轻松很多。这份习题覆盖的变量、运算符、分支循环、指针和引用,恰恰就是C++第一学期最重要的一层地基。

3. 跑通你的第一个C++程序:把三位整数倒过来输出

概念讲再多,不如亲手跑通一个程序。这一章我们直接做编程题里最简单的那道:输入一个三位整数,程序把它反向输出。全程跟着做,做完你会对“写代码到底是怎么回事”有真实的感觉。

3.1 动手前先准备环境:装一个能编译运行的C++工具

跑程序之前,你得先有一个能“翻译并执行”C++代码的环境。这里我不推荐具体某一款软件,因为每台电脑情况不一样,你只要记住一个原则:装好任意一款带C++编译器的开发环境,能让你新建文件、写代码、点一下运行、看到结果就行。安装完成后,新建一个源代码文件,把下面的代码完整粘贴进去,先别管每行什么意思,让程序跑起来再说。

第一次运行如果报错,不要慌。把报错信息读一遍,多半是以下几类:代码没保存、文件名后缀不对、或者粘贴时漏掉了某个符号。环境准备这一步,很多新手会卡在“装了好几个软件还是不行”上,我的建议是一条路走到黑:选定一个环境,把它的新建、保存、运行三个按钮找齐,就够了。

3.2 每一行代码在做什么:从输入到取位再到输出

我们要完成的题目是从键盘输入一个三位整数,比如123,程序立刻输出它的反向排列321。完整代码如下:

#include <iostream> using namespace std; int main() { int x, i, j, k; cout << "please input x:"; cin >> x; i = x / 100; // 取百位:123 / 100 == 1 j = x / 10 % 10; // 取十位:123 / 10 == 12,12 % 10 == 2 k = x % 10; // 取个位:123 % 10 == 3 cout << k << j << i << endl; return 0; }

逐行看。第一行#include 是让程序能用cin读入、cout输出,这一行是固定“头文件”,初学者先照抄即可。第二行using namespace std;意思是“我接下来要用的标准功能都在std这个命名空间里”,也是一句固定开场白。int x, i, j, k;声明了4个整数变量:x保存你输入的数,i、j、k分别保存百位、十位、个位。

cin >> x;会等待你在键盘上输入,按回车后把数字放进x。接着三行是出题人精心设计过的取位写法:x / 100是整数除法,123除以100等于1,小数部分直接丢掉;x / 10 % 10先整除得到12,再对10取余得到2;x % 10直接取个位得到3。最后cout << k << j << i把三个数字按“个位、十位、百位”的顺序打印,于是得到321。

运行结果演示:屏幕显示please input x:,你输入123回车,程序输出321。如果你输入987,输出789。

这里的运算规则很关键:整数之间做除法时,C++会丢弃小数部分,而不是四舍五入。比如7 / 2的结果是3不是3.5。想保留小数,需要把操作数写成浮点类型,比如double。习题1第4题就考了类似的类型混用问题。

3.3 把这个例子改着玩:从三位数到回文数判断

程序跑通之后,别急着做下一题。试着改一改,改完你会更理解这三条取位语句。

第一个改动:输入12会怎样?12 / 100等于0,百位取出来是0;12 / 10 % 10是1;12 % 10是2。输出情况会变成“021”。这说明程序只能正确处理三位数。想要程序更健壮,可以先判断输入是否在100到999之间,再决定是否执行取位运算。这个思考过程,比背下代码更重要。

第二个改动:把“反向输出”改成“判断回文数”。回文数是指正着读和倒着读一样的数,比如121。你只需要在取位之后加一个判断:

if (i == k) { cout << "是回文数" << endl; } else { cout << "不是回文数" << endl; }

注意这里是比较相等,用两个等号==,写成一个等号=就变成赋值了,这是新手最容易翻车的地方。

第三个改动:把三位数改成四位数。你需要再增加一个变量,用 x / 1000 取千位,原来的百位变成 x / 100 % 10,十位和个位不变。改完对照运行结果检查一遍,你会对“整除取位”这个套路形成肌肉记忆。下次遇到“把一个整数拆成各个数位”的题,你就能条件反射地写出取模和整除的组合了。

4. 新手第一道真正的坎:变量、指针和引用到底是什么关系

选择题做到指针和引用那几题,很多人会开始怀疑人生:p、*p、&p、int &ra,怎么全是符号?这一章我用三个类比,把这组概念彻底讲清楚。

4.1 变量是贴了标签的盒子:先搞懂“名访问”

把内存想象成一排排储物柜,每个格子都能放东西。int a = 5;做的事是:找到一个能放整数的格子,把5放进去,然后在格子外面贴上一张写着a的标签。之后你写a,就等于说“打开贴有a标签的那个格子”。这在C++里叫“名访问”,也就是通过变量名直接读写格子里的值。

习题1.5思考题2里说的“普通数据类型变量通过名访问即直接访问”,就是这个意思。给变量赋值、读取输出,都是打开盒子看内容。而“类型”决定了这个格子里能放什么、能做什么运算。习题1第4题里,int a=0是整数格子,double x=5.16是浮点格子,a % x会对浮点数取余,这种操作C++不允许,所以编译直接报错。

变量的格子还有一个特点:同一时刻只能装一个值。你往里面放新值,旧值就被覆盖。交换两个变量的值,必须借助第三个格子临时中转,这就是习题1第13题的考点。选项d“a=b; b=a;”为什么不能交换?因为第一句执行后a已经变成b的值,第二句再把a赋给b,等于把同一个值来回倒,原来a的值早丢了。

4.2 指针是写着地址的纸条:*号和&号别再用混

现在问题来了:如果有一个格子,它里面放的不是数字,而是“另一个格子的编号”——这个格子就是指针变量。int a = 5; int *p = &a;可以这样理解:&a是“取a这个格子的编号”,也就是地址;int *p是定义一张写着地址的纸条;把&a填进纸条,p里面存的就是a的地址。

那么*p是什么?它是“顺着纸条找到的那个格子里的内容”。习题1第14题专门考这个:int i = 10, *p = &i; 正确的说法应该是“p的值是变量i的地址”、“*p表示变量i的值”、“p指向整型变量i”,而“p的值为10”是错误的——p的值是地址,不是10。习题15也一样,int *p1 = &a, *p2 = &b; 选项b“p1 = a”为什么错?因为p1只能接受地址,a是一个整数,把整数塞给指针变量,类型对不上。

新手最容易把和&弄混,这里有个记忆方法:声明语句里的是“我要一张纸条”,&是“我要取格子的编号”;使用语句里的是“沿着纸条找格子”,&是“告诉我这个格子编号是多少”。习题1.5第7题就是一道专门辨析和&含义的题,做完那道题,你会彻底分清楚。

4.3 引用是同一个盒子的第二个标签:它和指针有三个重要区别

引用比指针更好理解:int a = 5; int &ra = a; 意思是给同一个格子再贴一张写着ra的标签。你不是新建了一个格子,只是给旧格子起了个新名字。之后你写ra等于写a,打开的都是同一个格子。习题1第16题里,int &pa=a, &pb=b; 用pa、pb去读写a、b,所以“pb = pa”是正确的,“*pb =pa”反而是错的——因为引用不需要用。

引用和指针有三个区别,是考试也爱考的:第一,引用名不占内存空间,它只是个别名;指针变量自己要占一个格子来存地址。第二,引用在定义时就必须绑定某个变量,而且之后不能改绑;指针变量可以随时换指向,今天指向a,明天指向b。第三,用引用访问变量,写法和直接用变量名一模一样;用指针访问,必须写*。

习题1第17题就是用引用交换a和b的值,整个过程不需要指针,也不用临时变量去操作地址,直接用引用就能完成:ra、rb相当于a、b的别名,三句赋值就完成交换。做完这道题,再看习题1.5思考题3的验证程序,把输出结果逐行分析一遍,指针和引用就算真正入门了。

5. 常见问题排查:新手最容易踩的五个C++坑

这一章全部来自真实出题人最爱布置的“陷阱题”。每一条我都按“现象 → 原因 → 解决”来讲,你踩过也好、没踩过也好,提前看一遍能省下不少调试时间。

5.1 把比较写成赋值:if(a=b) 为什么会输出“9等于9”

现象:输入a=4、b=9,程序却显示“9等于9”。

原因:if(a=b)里用的是赋值号=而不是比较符==。a=b会把b的值赋给a,整个赋值表达式的值就是b的值,也就是9。9非0,被当成逻辑真,于是走了第一个分支。习题2.3思考题6就是这个问题的完整版本。

解决:比较相等一律用==。如果担心自己手滑,可以把常量写在左边,写if(9==a)。这样万一漏写一个等号,编译器会直接报错,因为“把值赋给常量”不合语法。

5.2 变量定义进花括号:一出作用域就变“未定义”

现象:代码编译时报错,提示某个变量“undeclared identifier”(未定义的标识符)。

原因:变量定义写在if或else的执行体里,它的作用域只限制在那对花括号内。分支结束,变量就“消失”了,后面再使用它,编译器找不到这个名字。习题2.3思考题5就是典型。

解决:需要在程序多处使用的变量,定义在函数开头、所有分支之外。分支里只写赋值语句,不写定义语句。这个习惯越早养成越好,等到写复杂程序时,你会感谢自己没把变量定义撒得满函数都是。

5.3 switch少了break:case会一路往下“穿透”

现象:switch(i)里i=2,进入case 2后执行了i--,结果紧接着把case 3里的++i也执行了,最后i的值和自己预想的不一样。习题2.1第3题就是这种陷阱。

原因:case只是入口标记,不是“执行完就自动退出”。不写break,执行流会继续往下穿过后面的case,直到遇到break或switch结束。

解决:每个case分支的末尾都要检查有没有break。如果有多个case要共享同一段逻辑,也可以故意写成连续case,例如习题2.4第4题把score/10得到的10、9都归为'a',这是“穿透”的合法用法。但要写清楚注释,否则别人看代码会误以为你忘写了break。

5.4 整数除法丢小数:想算平均值却得到0

现象:int a=1; int b=2; 计算a/b的结果是0,而不是0.5。

原因:两边都是整数时,C++做的是整数除法,结果直接截掉小数部分,不四舍五入。习题1.2里把数学表达式转成C++表达式时,所有除法都要小心这一点。

解决:想让结果保留小数,至少让其中一个操作数是浮点类型,例如1.0 * a / b,或者把结果变量声明成double。判断能不能整除,用取模运算a % b == 0,而不是看除法结果。

5.5 continue和break用反:循环结果和预想完全不同

现象:while循环里写了continue,本以为会“跳过这次继续循环”,结果循环提前结束了,或者多跳了好几轮,输出结果和自己手推的对不上。习题2.2第3题就是continue的典型,++i写在条件判断里,导致输出的数不是1到10,而是4、7、10。

原因:continue是“跳过本轮剩下的语句,立刻回到循环条件判断”,不是“跳到循环末尾”那么简单。当continue写在循环体前部,并且循环变量的更新发生在continue之后的语句里,那么循环变量可能来不及更新,甚至造成死循环。

解决:把循环变量的更新放在循环体最前面,或者改用for循环,把i++写在for的第三个表达式里。做题时先在纸上手推一遍循环流程,再上机验证,这是判断循环题对不对的最快方法。

6. 下一步往哪走:把这份习题吃透之后该学什么

6.1 把已经会的题目改造成新题:反向输出三位数怎么变成任意位

学编程最有效的进阶方式,不是做更多新题,而是把做过的题“升级”。以第3章的反向输出为例,改成“输入任意正整数,反向输出每一位”,你只需要在循环里反复取模和整除:

while (x > 0) { cout << x % 10; // 输出当前最后一位 x = x / 10; // 去掉最后一位 }

这段代码里:x % 10永远取当前个位,x / 10则把它丢掉。循环不断重复这两个动作,直到x变成0。你会发现,用循环实现之后,三位数、四位数、任意位数都不再需要单独写取百位、取千位的公式了。这就是从“会一题”到“会一类”的跳跃。

6.2 接下来按这个顺序学:函数、数组、类与对象、文件

这套习题覆盖的是C++第一学期的前半程。把它吃透之后,建议按这个顺序继续:先学函数,把重复代码拆成可复用的小积木;再学数组,一次性处理一批相同类型的数据;然后学类与对象,体会C++里最核心的“把数据和操作打包在一起”的思想;最后学文件读写,让程序能把结果保存下来。每一步都可以像前面那样,找几道带解答的题,先做再对答案。

另外提醒一句:读程序题不要只读不想。每到一段代码,都先问自己三个问题——它声明了什么类型?每个运算符的优先级是什么?循环到底执行几次?这三个问题想清楚,你的读代码能力会明显上一个大台阶。如果你手边正好缺一套能对照的练习题,在各个课程资料平台搜“计算机C++习题答案”就能找到与本文同源的资料,按第2章教的顺序用起来即可。

学到这里,你已经不是那个看见C++就发怵的新手了。说实话,当年我也被那一堆选择题和指针题折磨过,后来养成了一个习惯:每学一个新知识点,就逼自己在上机前先手写一遍输出结果或思路,再运行验证。从那以后,我每次写完程序都强制走一遍“先手推、再运行、最后对答案”的流程,翻车的次数直线下降。希望这个方法也能帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进