首页 / 资讯中心 / 文章详情

C语言第二周编程题精讲:变量、类型与输入输出实战

C语言第二周编程题精讲:变量、类型与输入输出实战 ★ FEATURED ARTICLE
1. 从题目到思维第二周编程题到底在练什么很多人第一次打开这套编程题的时候心里想的都是“不就是写几个C程序吗”。但真正动手做了几道之后你会发现第二周的题目设计其实很有讲究。它不像第一周那样只是让你熟悉编译环境和最基本的输入输出而是开始逼着你去理解变量、数据类型、运算符、表达式这几个C语言最底层的东西。说白了这一周的核心目标只有一个让你学会用计算机的方式去描述一个计算过程。我见过不少同学第一周跑通了“Hello World”就觉得自己会C语言了结果第二周第一道题就卡住——因为题目要求你计算一个数学表达式的结果而你不清楚整数除法和浮点数除法的区别也不清楚%运算符到底能用在什么类型上。这些坑几乎每一个初学者都会踩一遍。第二周的题目通常包含这几类温度转换、时间换算、求平均值、计算圆的面积和周长、数字拆分、简单数学公式求解。看起来都是小学数学水平但用C语言写出来就会暴露出一堆问题输入格式不对、输出格式差一个空格、整数溢出、精度丢失、变量没初始化……这些问题在以后写大程序的时候会放大一百倍所以第二周其实是在帮你打地基。这篇文章我会把第二周编程题里最典型的几类题目拆开来讲不光告诉你代码怎么写更重要的是告诉你为什么这么写以及我当时踩过哪些坑。如果你正在做这套题或者刚开始学C语言这篇内容应该能帮你省下不少调试时间。2. 核心知识点拆解变量、类型与输入输出2.1 为什么int和float的区别在第二周就变得致命第二周很多题目都会涉及除法。比如“输入两个整数输出它们的商”。如果你写的是int a, b; scanf(%d %d, a, b); printf(%d, a / b);那么当输入是5 2的时候输出是2而不是2.5。原因很简单两个整数相除结果还是整数小数部分直接被截断。这不是bug这是C语言的规则。很多初学者在这里会懵觉得计算机算错了。其实计算机没错是你没告诉它你要的是小数。正确的做法是把其中一个操作数转成浮点数printf(%.2f, (float)a / b);或者直接定义成float或double类型。这里还有一个细节%.2f表示保留两位小数如果题目要求输出两位小数你写成%f就会输出六位导致格式错误。这种格式错误在在线评测系统里是直接判错的哪怕你的计算逻辑完全正确。注意float和double在scanf和printf里的格式符不一样。float用%fdouble用%lfscanf和%fprintf。这个细节在第二周就会用到记错了就会读入错误的数据。2.2scanf的返回值你检查过吗第二周的题目通常输入格式很固定比如“输入一行包含两个整数用空格分隔”。但如果你写的scanf格式和题目要求不匹配比如题目要求用逗号分隔而你写了空格那么第二个变量就不会被正确赋值程序会用一个垃圾值去计算结果自然不对。我当时的习惯是写完scanf之后先打印一下读到的值确认没问题再继续写后面的逻辑。这个习惯看起来笨但能帮你省下大量时间。比如int a, b; scanf(%d %d, a, b); printf(a%d, b%d\n, a, b); // 调试用提交前删掉另外scanf的返回值是成功读入的变量个数。如果返回值不等于你期望的个数说明输入格式有问题。虽然第二周的题目一般不需要做输入校验但养成检查返回值的习惯以后写复杂程序会轻松很多。2.3 运算符优先级为什么你的表达式总算错第二周会涉及一些数学公式比如计算(ab)*c或者ab*c。如果你不熟悉运算符优先级很容易写错。C语言里*、/、%的优先级高于和-而括号的优先级最高。所以ab*c是先算b*c再算a而(ab)*c是先算ab再算*c。还有一个容易被忽略的点赋值运算符的优先级很低。比如a b c * d是先算c*d再算b最后赋值给a。这个一般不会错但如果你写a b c它是从右往左结合的先把c赋给b再把b的值赋给a。第二周虽然不会用到这么复杂的赋值但理解优先级对后面写条件判断很有帮助。3. 典型题目实战从温度转换到数字拆分3.1 温度转换浮点数输入输出的标准模板温度转换是第二周最经典的题目之一。通常是要求输入一个摄氏温度输出对应的华氏温度或者反过来。公式是F C * 9 / 5 32。看起来很简单但这里有一个陷阱如果你写C * 9 / 5而C是整数那么9/5会先算成1结果就完全错了。正确的写法是C * 9.0 / 5.0 32或者把C定义成double。#include stdio.h int main() { double c, f; scanf(%lf, c); f c * 9.0 / 5.0 32.0; printf(%.2f\n, f); return 0; }这段代码里%.2f表示保留两位小数\n表示换行。很多在线评测系统要求输出末尾有换行没有的话会判格式错误。这个细节在第一周可能不会强调但第二周开始就要养成习惯。实操心得如果你不确定题目要求保留几位小数先按两位小数提交如果错了再试一位或六位。但更好的做法是仔细读题题目里一般会写“保留两位小数”或者“输出精确到小数点后两位”。3.2 时间换算整数除法和取模的经典组合时间换算题目通常是“输入一个秒数输出对应的小时、分钟和秒”。比如输入3661输出1小时1分1秒。这道题的核心是整数除法和取模运算。#include stdio.h int main() { int total, h, m, s; scanf(%d, total); h total / 3600; m (total % 3600) / 60; s total % 60; printf(%d %d %d\n, h, m, s); return 0; }这里total / 3600得到小时数total % 3600得到剩下的秒数再除以60得到分钟数最后total % 60得到秒数。这个思路可以推广到任何单位换算的题目比如“输入一个天数输出多少周零几天”。我当时的坑是忘了处理输出格式。题目可能要求输出1:1:1而不是1 1 1或者要求输出1小时1分1秒。格式不对逻辑再对也是零分。所以做这类题的时候先把输出格式看清楚再动手写代码。3.3 求平均值浮点数精度和类型转换求平均值题目通常是“输入三个整数输出它们的平均值保留两位小数”。这道题的坑在于如果你写(abc)/3结果是整数除法小数部分丢失。正确的写法是(abc)/3.0或者(float)(abc)/3。#include stdio.h int main() { int a, b, c; double avg; scanf(%d %d %d, a, b, c); avg (a b c) / 3.0; printf(%.2f\n, avg); return 0; }这里还有一个隐藏问题如果abc的值很大比如三个1000000那么abc是3000000在int范围内没问题。但如果题目给的范围更大比如三个10亿那么abc就会溢出。第二周的题目一般不会这么极端但养成用double或者long long的习惯没坏处。注意3.0是double类型3.0f是float类型。在printf里double用%ffloat用%f也可以因为float会自动提升为double。但在scanf里float必须用%fdouble必须用%lf不能混。3.4 数字拆分取模和除法的反复运用数字拆分题目通常是“输入一个三位数输出它的百位、十位和个位”。比如输入123输出1 2 3。这道题的核心是#include stdio.h int main() { int n, b, s, g; scanf(%d, n); b n / 100; s (n / 10) % 10; g n % 10; printf(%d %d %d\n, b, s, g); return 0; }这里n/100得到百位(n/10)%10得到十位n%10得到个位。这个思路可以推广到任意位数的拆分比如四位数、五位数。关键是理解整数除法是向下取整而取模是取余数。我当时的坑是忘了考虑负数。如果输入是-123那么-123/100是-1-123%10是-3输出就不对了。第二周的题目一般不会涉及负数但如果你以后遇到记得先取绝对值或者单独处理符号。4. 常见问题与排查技巧实录4.1 为什么我的程序在本地能跑提交就错这是初学者最常遇到的问题。原因通常有三个第一输出格式不对。本地跑的时候你看到结果对了就以为没问题但在线评测系统是逐字符比对的。多一个空格、少一个换行、小数位数不对都会判错。解决办法是仔细读题把输出格式要求抄下来写完代码后逐字对照。第二输入格式不对。题目要求输入用空格分隔你写了逗号或者题目要求先输入一个整数再输入一个字符串你顺序搞反了。解决办法是先用printf把读到的值打印出来确认无误再继续。第三变量没初始化。比如你定义了int sum;然后直接sum a;sum的初始值是垃圾值结果自然不对。解决办法是定义变量时直接初始化比如int sum 0;。4.2 常见错误速查表错误现象可能原因解决办法输出结果差一点整数除法截断把操作数转成浮点数输出格式错误空格、换行、小数位数不对逐字对照题目要求读入数据错误scanf格式符不匹配检查%d、%f、%lf结果随机变化变量未初始化定义时赋初值程序崩溃数组越界或指针错误第二周一般不会遇到检查循环边界计算结果溢出int范围不够改用long long或double4.3 调试技巧打印中间变量第二周的题目逻辑简单但如果你卡住了最快的办法是在关键步骤后打印中间变量。比如printf(a%d, b%d, sum%d\n, a, b, sum);这样你能看到每一步的值是否符合预期。如果不符合问题就出在上一步。这个技巧看起来笨但比盯着代码发呆有效得多。我当年做第二周题目的时候几乎每道题都会打印中间变量确认无误后再删掉调试语句提交。实操心得提交前一定要把调试用的printf删掉或者注释掉。有些在线评测系统对多余输出是零容忍的哪怕你的计算结果正确多一行调试信息也会判错。5. 从第二周看C语言学习的正确姿势5.1 不要跳过任何一道题第二周的题目看起来简单但每一道都在训练一个特定的技能点。温度转换训练浮点数运算时间换算训练整数除法和取模求平均值训练类型转换数字拆分训练取模和除法的组合。如果你跳过其中一道后面遇到类似问题的时候就会卡住。我见过不少同学觉得题目太简单直接抄答案提交结果到了第三周、第四周题目难度上来了就完全跟不上。原因就是第二周的基础没打牢。C语言的学习是层层递进的第二周没搞懂的东西后面一定会以更复杂的形式出现。5.2 理解比记忆更重要第二周的题目涉及很多公式和格式比如F C * 9 / 5 32、h total / 3600、b n / 100。这些公式如果你死记硬背换一道题就不会了。但如果你理解了背后的原理——浮点数运算、整数除法、取模运算——那么不管题目怎么变你都能自己推导出来。比如时间换算你理解了“总秒数除以3600得到小时数余数再除以60得到分钟数最后余数就是秒数”那么不管题目是换算成天、小时、分钟还是秒你都能灵活应对。5.3 养成好习惯缩进、注释、命名第二周的代码很短很多人觉得没必要注意代码风格。但习惯是从一开始养成的。如果你现在写代码不缩进、变量名用a、b、c、x、y、z那么到了后面写几百行的程序时你自己都看不懂自己写了什么。我的建议是变量名尽量有意义。比如温度转换用celsius和fahrenheit时间换算用total_seconds、hours、minutes、seconds。这样即使过了一个月再看代码你也能快速理解。缩进用四个空格或者一个Tab保持一致性。注释不用多但关键步骤写一句比如// 计算小时数以后回头看会感谢自己。5.4 在线评测系统的提交策略第二周的题目一般是在线评测提交后立刻出结果。我的策略是先本地测试再提交。本地测试的时候把题目给的样例输入跑一遍确认输出和样例一致。如果样例过了再提交。如果提交后判错先检查输出格式再检查边界情况。边界情况包括输入为0、输入为负数、输入为最大值、输入为最小值。第二周的题目一般不会这么刁钻但养成考虑边界的习惯以后受益无穷。注意有些在线评测系统对时间复杂度和空间复杂度有要求但第二周的题目一般不会卡这些。如果你提交后提示“运行超时”那可能是你的程序里有死循环检查一下while或for的终止条件。6. 第二周题目背后的编程思维6.1 从“计算”到“描述计算过程”第二周的题目表面上是在做数学计算实际上是在训练你用计算机的方式描述一个计算过程。数学里你可以写F C * 9 / 5 32但在C语言里你必须考虑C是什么类型、9/5会不会被截断、结果怎么输出。这就是编程思维和数学思维的区别。编程思维的核心是把一个大问题拆成若干个小步骤每一步都用计算机能理解的方式表达出来。第二周的题目虽然小但已经包含了这种思维的雏形。比如时间换算你先算小时再算分钟最后算秒每一步都是一个独立的计算组合起来就是完整的结果。6.2 输入、处理、输出程序的基本结构第二周的所有题目都遵循同一个结构读入数据、处理数据、输出结果。这个结构是几乎所有程序的基础。你以后写再复杂的程序本质上也是这三步只是每一步变得更复杂而已。读入数据的时候你要考虑数据的类型、格式、范围。处理数据的时候你要考虑算法、精度、边界。输出结果的时候你要考虑格式、精度、换行。第二周的题目把这三点都涉及到了只是规模很小。如果你能把第二周的每一道题都吃透后面学循环、数组、函数、指针的时候就会轻松很多。6.3 错误处理从第二周开始培养意识第二周的题目一般不会要求你做错误处理比如输入非法字符怎么办、除数为零怎么办。但你可以自己加一些检查比如if (b 0) { printf(除数不能为零\n); return 1; }这样做的好处是你养成了考虑异常情况的习惯。以后写实际项目的时候用户输入什么都有可能如果你不做检查程序就会崩溃。第二周虽然不要求但你可以自己加当作练习。7. 我当年踩过的坑和总结的技巧7.1 格式错误是最冤的丢分我当年做第二周题目的时候有一道题是“输入一个整数输出它的绝对值”。我写了int n; scanf(%d, n); if (n 0) n -n; printf(%d, n);逻辑完全正确但提交后判错。我检查了半天最后发现题目要求输出后换行而我忘了写\n。就这么一个字符导致整道题零分。从那以后我每次提交前都会检查输出格式确认换行、空格、小数位数都符合要求。7.2 整数溢出一个容易被忽略的问题第二周的题目一般不会涉及大数运算但如果你做“求两个整数的乘积”这类题目就要注意溢出了。比如int的范围是-2147483648到2147483647如果两个100000相乘结果是10000000000超出了int的范围就会溢出。解决办法是用long longlong long a, b; scanf(%lld %lld, a, b); printf(%lld\n, a * b);long long的范围是-9223372036854775808到9223372036854775807足够应付第二周的所有题目。这个知识点第二周可能不会考但提前知道没坏处。7.3 浮点数比较不要用第二周可能不会涉及浮点数比较但如果你做“判断两个浮点数是否相等”这类题目千万不要用。因为浮点数在计算机里是近似存储的0.1 0.2不等于0.3。正确的做法是判断它们的差值是否小于一个很小的数比如1e-6if (fabs(a - b) 1e-6) { printf(相等\n); }这个知识点以后会经常用到第二周先了解一下。7.4 提交前的检查清单我总结了一个提交前的检查清单每次提交前都过一遍输出格式是否和题目要求完全一致空格、换行、小数位数变量是否都初始化了整数除法是否需要转浮点数是否有调试用的printf没删掉边界情况是否考虑到了0、负数、最大值代码是否缩进整齐、变量名是否有意义这个清单看起来简单但能帮你避免90%的低级错误。我当年如果早点有这个清单能省下不少时间。7.5 从第二周往后看基础不牢地动山摇第二周的题目虽然简单但它们是后面所有内容的基础。第三周会学循环第四周会学数组第五周会学函数第六周会学指针。如果你第二周的变量、类型、运算符没搞懂后面学循环的时候就会卡在“循环变量是什么类型”“循环条件怎么写”这些问题上。我的建议是第二周的每一道题都自己动手写一遍不要抄答案。写完之后再想想有没有别的写法比如用不同的数据类型、不同的运算符组合。这样你才能真正理解C语言的运作方式而不是死记硬背几行代码。最后分享一个小技巧如果你在做第二周题目的时候卡住了先把题目要求用中文写一遍再把每一步的计算过程用中文写一遍最后再翻译成C语言。这个“中文到代码”的翻译过程就是编程思维的核心。练多了之后你看到题目就能直接写出代码不需要中间步骤了。
阅读完成 · 觉得有帮助?
咨询建站