C语言基础入门----(3)垃圾字符回收及程序的三大基本结构

Tips:本文主要面向C语言初学者及新手,属于系列文章,笔者借此巩固自身同时也希望帮助更多新人更快的入门,如有不当或错误,欢迎指正。

前言

        前面文章我们介绍了C中常见的数据类型及基础的输入输出函数,本文主要是针对输入输出常见问题——垃圾字符的产生及解决方式展开,也会同时简单介绍下编程中的三大基本结构,属于基础内容,难度较低,建议速读了解掌握即可。


一、垃圾字符的产生

上一篇文章我们介绍了基本的输入输出函数printf(),scanf()等使用方法,现在我们来看下面这一段程序:

给a,b,c三个变量分别赋值并输出

#include <stdio.h>

int main(void)
{
        char a,b,c;
        printf("please input a:");    
        scanf("%c",&a);             
        printf("a=%c",a);

        printf("please input b:");
        scanf("%c",&b);
        printf("b=%c\n",b);

        printf("please input c:");
        scanf("%c",&c);
        printf("c=%c\n",c);

 //上述代码中的输出均可使用getchar()替换


    return 0;
}

 按照我们的逻辑来看,理应是输出

 但是事实上当我们运行完毕,发现执行的结果居然是这个样子:

 这就是本文标题提及到的垃圾字符,此时这种情况便是产生了垃圾字符,影响到了我们的正常使用,读者不妨先思考下造成这种情况的原因是什么,接下来再继续进行讲解。

二、为什么会产生垃圾字符?

        相信经过思考,有一些读者已经发觉了问题所在。当我们向终端输入数据时,按下回车的瞬间,我们的getchar()或者scanf(),实际获取的是上次残留的换行符\n,无法正确的获取到我们想要的字符。由此才导致了上文中举例产生的影响。

        事实上,垃圾字符是比较常见的问题,但是不经意间的一点问题就有可能导致整个程序的崩溃错误或者轮询失败等大问题。以下情况是普遍易产生垃圾字符的情况,各位读者日后可以多加注意以下情况时的编程习惯:

1、使用scanf() 连续获取多个字符。

2、多个scanf()连续获取字符。

3、代码比较长,不确定前面有没有出现垃圾字符。

三、如何解决垃圾字符?

常见的垃圾字符回收方式有以下三种:

1.利用空格实现垃圾字符的回收

//只需要在使用scanf()函数时,控制格式的%c等字符前加上空格,即可实现垃圾字符的回收

        char a,b,c;
        printf("please input a:");
        scanf(" %c",&a);
        printf("a=%c\n",a);

        printf("please input b:");
        scanf(" %c",&b);
        printf("b=%c\n",b);

        printf("please input c:");
        scanf(" %c",&c);
        printf("c=%c\n",c);

实现效果如下: 

该方式可以回收一个或多个的空格、回车、tab。

 2.scanf()连续获取多个字符

该方式可以指定输入,但是使用起来较为繁琐。

3.使用getchar()函数回收垃圾字符

 

在每次使用完scanf函数后紧跟一个getchar()用以回收垃圾字符,该种方式一般只能回收任意一个字符,一般用于循环里面

while((getchar()!='\n'))

无论用户是输入多少个多余的字符,最后只能按一次回车。只要用户按回车,则回车之前的所有字符就都会被 getchar() 取出来,只要 getchar() 取出来的不是回车 ('\n') ,则表示用户输入尚未完成,用户按下回车输入完成,就会将输入的字符全部取完。

 4.强制刷新缓冲区fflush()

在每次输入字符型数据之前,调用fflush(stdin)函数来强制刷新缓冲区

此处涉及到缓冲区及文件流部分知识,初学者可仅作了解,后续会讲解这部分知识,感兴趣的读者可以自行查询探索或等待后续讲解。

稍微深入来看,上述造成垃圾字符的原因是这样的:

        scanf单字符输入时规定只接收一个字符,当我们输入更多的内容时,例如我们给a赋值时键盘上输入的是    1+回车    ,则1顺利传给了a,但是多余的回车带来的换行符 \n 却被遗留在了我们的缓冲区,再继续给b赋值时,我们又进行了一次    2+回车   的操作。从而造成   “b=”  后没有值,而且进行了一次换行的情况。

笔者习惯性的使用空格的方式吸收垃圾字符,诸位可自行探索自己习惯的方式用以解决垃圾字符。

四、编程的三大基本结构介绍

        在C语言中有三大基本结构,分别是顺序结构分支结构以及循环结构

想象以下生活情景:

        在自己卧室的你现在想要喝一杯热水,于是你执行了不同的步骤。

4.1顺序结构

        顺序结构,顾名思义,就是按顺序执行的结构,代码依次从前往后逐步执行,没有任何的跳转,所有的语句都会被执行,直至程序执行结束 。该类结构的程序最为常见,可以说一个C中的程序即使不含有分支结构和循环结构,也必然会有顺序结构,因为程序只要执行,就是自上而下逐步顺序执行。

你要喝一杯热水,首先你要拿到自己的水杯,这是第一步。

第二步,便是烧水。

第三步,用杯子接热水。

成功喝到了热水,这就是顺序结构,一步一步执行下来。

4.2分支结构

        分支结构,即为有分支。该类结构的特点就是依据某个变量的值或其他情况来进行判断,执行不同的程序。

还是喝热水这个情景,但是这个时候你发现水杯没有放在卧室,你需要去其他屋子里找到自己的杯子,于是你去了厨房、客厅、书房等房间寻找杯子,终于在书房找到。

第二步,烧水。

第三步,接热水。

成功喝到了热水

 

在这个时候,你第一次没有找到杯子于是去执行了其他的操作(去往其他房间寻找杯子),这就是分支结构。

常玩游戏的也可以理解为类似于“支线任务”,不影响你的主线体验。

4.3循环结构

        循环结构,就是在达到指定条件前,重复执行某些语句。

仍然是喝热水的场景:

        第一步,找杯子

        第二步,烧水

        第三步,接水

        第四步,喝水

但是,你喝了一杯发现不解渴,于是你又喝了一杯,可是你还是觉得不解渴,继续又喝了一杯......直到你觉得不再口渴,你才停止了喝水的行为。

        此时,刚刚你喝水的那部分便是  循环结构  ,而口渴,便是你执行“循环”的条件。


总结

        至此,本文讲解结束,希望各位斧正,下一篇将会详细讲解三种基本结构在程序中的体现,例如if...else语句,switch语句,for循环等的介绍与使用。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Objective-C程序设计》(作者杨正洪、郑齐心、李建国)通过大量的实例系统地介绍了Objective-C语言基本概念、语法规则、框架、类库及开发环境。读者在阅读本书后,可以掌握Objective-C语言基本内容,并进行实际的iPhone/iPad和Mac应用开发。   《Objective-C程序设计》共分成11章。前6章讲述Objective-C语言,包括数据类型、运算符、表达式、条件语句、循环语句、类、协议、继承、类别、编译预处理等内容。第7章到第10章讲述Objective-C的基础框架,以及文件操作、内存管理、数据保存等内容。第11章讲述了应用工具框架。第12、13章分别讲述了如何开发iPhone/iPad应用程序。第14章讲述了Objective-C++和访问Mysql数据库的编程知识。 第1章 启程.1 1.1 预备知识1 1.2 历史背景1 1.3 内容简介2 1.4 小结3 第2章 对C的扩展4 2.1 最简单的Objective-C程序4 2.2 解构HelloObjective-C程序7 2.2.1 #import7 2.2.2 NSLog()和@"字符串"8 2.3 布尔类型10 2.3.1 BOOL强大的实用功能11 2.3.2 比较13 2.4 小结14 第3章 面向对象编程基础知识15 3.1 间接15 3.1.1 变量与间接16 3.1.2 使用文件名的间接18 3.2 在面向对象的编程中使用间接24 3.2.1 过程式编程24 3.2.2 实现面向对象编程29 3.3 学习有关的术语33 3.4 Objective-C中的OOP34 3.4.1 @interface部分34 3.4.2 @implementation部分38 3.4.3 实例化对象40 3.4.4 扩展Shapes-Object41 3.5 小结43 第4章 继承45 4.1 为何使用继承45 4.2 继承语法48 4.3 继承的工作机制51 4.3.1 方法调度51 4.3.2 实例变量53 4.4 重写方法55 4.5 小结57 第5章 复合58 5.1 什么是复合58 5.1.1 Car程序58 5.1.2 自定义NSLog()59 5.2 存取方法62 5.2.1 设置发动机的属性64 5.2.2 设置轮胎的属性64 5.2.3 跟踪汽车的变化66 5.3 扩展CarParts程序67 5.4 复合还是继承68 5.5 小结69 第6章 源文件组织70 6.1 拆分接口和实现部分70 6.2 拆分Car程序73 6.3 使用跨文件依赖关系75 6.3.1 重新编译须知75 6.3.2 让汽车开动77 6.3.3 导入和继承79 6.4 小结80 第7章 深入了解Xcode82 7.1 改变公司名称82 7.2 使用编辑器的技巧与诀窍83 7.3 在Xcode的帮助下编写代码85 7.3.1 首行缩进85 7.3.2 代码自动完成85 7.3.3 括号匹配88 7.3.4 批量编辑88 7.3.5 代码导航91 7.3.6 emacs不是Mac程序91 7.3.7 任意搜索92 7.3.8 芝麻开门93 7.3.9 书签93 7.3.10 集中注意力94 7.3.11 开启导航条95 7.4 获取信息98 7.4.1 研究助手98 7.4.2 文档管理程序99 7.5 调试100 7.5.1 暴力调试100 7.5.2 Xcode的调试器100 7.5.3 精巧的调试符号101 7.5.4 开始调试101 7.5.5 检查程序104 7.5 备忘表105 7.6 小结106 第8章 FoundationKit快速教程107 8.1 一些有用的数据类型108 8.1.1 范围的作用108 8.1.2 几何数据类型108 8.2 字符串109 8.2.1 创建字符串109 8.2.2 类方法109 8.2.3 关于大小110 8.2.4 比较的策略110 8.2.5 不区分大小写的比较112 8.2.6 字符串内是否还包含别的字符串..112 8.3 可变性113 8.4 集合家族115 8.4.1 NSArray115 8.4.2 可变数组118 8.4.3 枚举“王国”119 8.4.4 快速枚举120 8.4.5 NSDictionary120 8.4.6 使用,但不要扩展122 8.5 各种数值122 8.5.1 NSNumber122 8.5.2 NSValue123 8.5.3 NSNull124 8.6 示例:查找文件124 8.7 小结128 第9章 内存管理129 9.1 对象生命周期129 9.1.1 引用计数130 9.1.2 对象所有权132 9.1.3 访问方法中的保留和释放133 9.2 自动释放134 9.2.1 所有对象全部入池135 9.2.2 自动释放池的销毁时间135 9.2.3 自动释放池的工作过程136 9.3 Cocoa内存管理规则138 9.3.1 临时对象138 9.3.2 拥有对象139 9.3.3 垃圾回收141 9.4 小结142 第10章 对象初始化143 10.1 分配对象143 10.2 初始化对象143 10.2.1 编写初始化方法144 10.2.2 初始化时做什么146 10.3 便利初始化函数146 10.4 更多部件改进147 10.4.1 Tire类的初始化147 10.4.2 更新main()函数149 10.4.3 清理Car类152 10.5 支持垃圾回收风格的Car类清理155 10.6 指定初始化函数156 10.6.1 子类化问题157 10.6.2 改进Tire类的初始化函数159 10.6.3 添加AllWeatherRadial类的初始化函数160 10.7 初始化函数规则160 10.8 小结161 第11章 特性162 11.1 修改特性值162 11.1.1 简化接口163 11.1.2 简化实现164 11.1.3 点表达式的妙用166 11.2 特性扩展167 11.2.1 名称的使用171 11.2.2 只读特性172 11.2.3 特性不是万能的173 11.3 小结173 第12章 类别175 12.1 创建类别175 12.1.1 声明类别175 12.1.2 实现类别176 12.1.3 类别的局限性178 12.1.4 类别的作用178 12.2 利用类别分散实现178 12.3 使用类别创建前向引用182 12.4 非正式协议和委托类别183 12.4.1 ITunesFinder项目184 12.4.2 委托和类别187 12.4.3 响应选择器187 12.4.4 选择器的其他应用188 12.5 小结189 第13章 协议190 13.1 正式协议190 13.1.1 声明协议190 13.1.2 采用协议191 13.1.3 实现协议192 13.2 复制192 13.2.1 复制Engine192 13.2.2 复制Tire194 13.2.3 复制Car196 13.2.4 协议和数据类型199 13.3 Objective-C2.0的新特性199 13.4 小结200 第14章 AppKit简介201 14.1 构建项目201 14.2 构建AppController@interface203 14.3 InterfaceBuilder203 14.4 布局用户界面205 14.5 连接207 14.5.1 连接输出口207 14.5.2 连接操作208 14.6 AppController实现210 14.7 小结212 第15章 文件加载与保存213 15.1 属性列表213 15.1.1 NSDate213 15.1.2 NSData214 15.1.3 写入和读取属性列表215 15.2 编码对象216 15.3 小结221 第16章 键/值编码222 16.1 入门项目222 16.2 KVC简介224 16.3 路径225 16.4 整体操作226 16.4.1 中途小憩227 16.4.2 流畅地运算231 16.5 批处理233 16.6 nil仍然可用234 16.7 处理未定义的键235 16.8 小结236 第17章 NSPredicate237 17.1 创建谓词237 17.2 燃料过滤器239 17.3 格式说明符240 17.4 运算符241 17.4.1 比较和逻辑运算符242 17.4.2 数组运算符243 17.5 SELF足够了243 17.6 字符串运算符245 17.7 LIKE运算符245 17.8 小结246
这是书的光盘。共分为两个部分,这是第一部分。 本书由浅入深、循序渐进地介绍了Windows驱动程序的开发方法与调试技巧。本书共分23章,内容涵盖了 Windows操作系统的基本原理、NT驱动程序与WDM驱动程序的构造、驱动程序中的同步异步处理方法、驱 动程序中即插即用功能、驱动程序的各种调试技巧等。同时,还针对流行的PCI驱动程序、USB驱动程序 、虚拟串口驱动程序、摄像头驱动程序、SDIO驱动程序进行了详细的介绍,本书最大的特色在于每一节 的例子都是经过精挑细选的,具有很强的针对性。力求让读者通过亲自动手实验,掌握各类Windows驱动 程序的开发技巧,学习尽可能多的Windows底层知识。   本书适用于中、高级系统程序员,同时也可用做高校计算机专业操作系统实验课的补充教材。 原创经典,威盛一线工程师倾力打造。深入驱动核心,剖析操作系统底层运行机制,通过实例引导,快 速学习编译、安装、调试的方法。   从Windows最基本的两类驱动程序的编译、安装、调试入手讲解,非常容易上手,用实例详细讲解 PCI、USB、虚拟串口、虚拟摄像头、SDIO等驱动程序的开发,归纳了多种调试驱动程序的高级技巧,如 用WinDBG和VMWARE软件对驱动进行源码级调试,深入Windows操作系统的底层和内核,透析Windows驱动 开发的本质。 本书是作者结合教学和科研实践经验编写而成的,不仅详细介绍了Windows内核原理,而且介绍了编程技 巧和应用实例,兼顾了在校研究生和工程技术人员的实际需求,对教学、生产和科研有现实的指导意义 ,是一本值得推荐的专著。              ——中国工程院院士   院士推荐   目前,电子系统设计广泛采用通用操作系统,达到降低系统的设计难度和缩短研发周期。实现操作 系统与硬件快速信息交换是电子系统设计的关键。   通用操作系统硬件驱动程序的开发,编写者不仅需要精通硬件设备、计算机总线,而且需要Windows 操作系统知识以及调试技巧。学习和掌握Windows硬件驱动程序的开发是电子系统设计人员必备的能力。   本书是作者结合教学和科研实践经验编写而成的,不仅详细介绍了Windows内核原理,并且介绍了编 程技巧和应用实例,兼顾了在校研究生和工程技术人员的实际需求,对教学、生产和科研有现实的指导 意义,是一本值得推荐的专著。 第1篇 入门篇 第1章 从两个最简单的驱动谈起 本章向读者呈现两个最简单的Windows驱动程序,一个是NT式的驱动程序,另一个是WDM式的驱动程序。 这两个驱动程序没有操作具体的硬件设备,只是在系统里创建了虚拟设备。在随后的章节中,它们会作 为基本驱动程序框架,被本书其他章节的驱动程序开发所复用。笔者将带领读者编写代码、编译、安装 和调试程序。   1.1 DDK的安装   1.2 第一个驱动程序HelloDDK的代码分析    1.2.1 HelloDDK的头文件    1.2.2 HelloDDK的入口函数    1.2.3 创建设备例程    1.2.4 卸载驱动例程    1.2.5 默认派遣例程   1.3 HelloDDK的编译和安装    1.3.1 用DDK环境编译HelloDDK    1.3.2 用VC集成开发环境编译HelloDDK    1.3.3 HelloDDK的安装   1.4 第二个驱动程序HelloWDM的代码分析    1.4.1 HelloWDM的头文件    1.4.2 HelloWDM的入口函数    1.4.3 HelloWDM的AddDevice例程    1.4.4 HelloWDM处理PNP的回调函数    1.4.5 HelloWDM对PNP的默认处理    1.4.6 HelloWDM对IRP_MN_REMOVE_DEVICE的处理    1.4.7 HelloWDM对其他IRP的回调函数    1.4.8 HelloWDM的卸载例程   1.5 HelloWDM的编译和安装    1.5.1 用DDK编译环境编译HelloWDM    1.5.2 HelloWDM的编译过程    1.5.3 安装HelloWDM   1.6 小结  第2章 Windows操作驱动的基本概念  驱动程序被操作系统加载在内核模式下,它与Windows操作系统内核的其他组件进行密切交互。本章主 要介绍Windows操作系统内核的基本概念,同时还介绍应用程序和驱动程序之间的通信方法。   2.1 Windows操作系统概述    2.1.1 Windows家族    2.1.2 Windows特性    2.1.3 用户模式和内核模式    

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值