0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

怎么像整数一样计算字符?

AGk5_ZLG_zhiyua 来源:未知 作者:佚名 2017-09-14 10:47 次阅读

周立功教授数年之心血之作《程序设计与数据结构》,电子版已无偿性分享到电子工程师与高校群体,经周立功教授授权,本公众号特对本书内容进行连载,愿共勉之。

第一章为程序设计基础,本文为1.8.1 字符常量。

>>>1.字符常量的引用

字符常量是使用一对单引号“''”包围起来的,比如,'O','编译器知道这个符号指的是字母O的ASCII值,即79。同样可以用' '指出空格,或用'9'指出数字9。常量'9'指的是一个字符,不应该与整数值9混淆。除非程序员能记住ASCII码表,否则任何人看到79都不会联想到字母O,而字符常量'O' 则可以直接传递它的意义。

C语言中,字符能象整数一样计算,不需要特别的转换。基于此,既可以给一个字符加上一个整数,比如,字符c与整数n相加,即c+n表示c后面的第n个字符。也可以从一个字符减去一个整数,比如,表达式c-n表示c前面的第n个字符。还可以从一个字符减去另一个字符,比如,c1和c2都是字符,那么c1-c2表示两个字符的距离。

更进一步地,还可以比较两个字符,如果在ASCII表中,c1在c2前面,那么c1

if( ch >= '0' && ch <= '9' )    { … }

这样一来就将数字字符与ASCII码表中的其它字符区分开了。虽然标准C接口ctype.h提供了相应的函数,但如果你从头到尾实现它们,则有助于进一步深入了解它们的操作。如果ch是大写字母,返回它对应的小写字母,否则返回ch本身,详见程序清单 1.35。

程序清单1.35 tolower()函数范例程序

1 char tolower(char ch)

2 {

3 if( ch >= 'A' && ch <= 'Z' ){                              //标识大写字母

4 return (ch + ('a' - 'A'));

5 }else{

6 return (ch);

7 }

8 }

>>>2. 字符的输入输出

虽然转换符%c允许scanf()函数和printf()函数对一个单独的字符进行读写操作。比如:

char ch;

scanf("%c", &ch);

printf("%c", ch);

但在读入字符前,scanf()函数不会跳过空格符,即会将空格作为字符读入变量ch。为了解决这个问题,则必须在%c的前面加一个空格:

scanf(" %c", &ch);

虽然scanf()函数不会跳过空格符,却很容易检测到读入的字符是否为换行符'\n'。比如:

while(ch != '\n'){

scanf("%c", &ch);

}

当然也可以调用getchar()和putchar()读写一个单独的字符,它们是在stdio.h中定义的宏,分别用于从键盘读取数据和将字符打印到屏幕上。虽然宏和函数在技术上存在一些区别,但它们的用法是一样的。比如:

int getchar(void);//输入一个字符

int putchar(int ch);//输出一个字符

getchar()函数不带任何参数,它从输入队列中返回一个字符。比如,下面的语句读取一个字符输入,并将该字符的值赋给变量ch:

ch = getchar();

该语句与下面的语句等效:

scanf("%c", &ch);

putchar()函数打印它的参数,比如,下面的语句将之前赋给ch的值作为字符打印出来:

putchar(ch);

该语句与下面的语句效果相同:

printf("%c", ch);

由于这些函数只处理字符,因此它们比scanf()和printf()函数更快,这两个函数通常定义在stdio.h中,实际上它们是预处理宏,不是真正的函数。虽然这些宏看起来很简单,但有时出了问题,却找不出原因。比如:

char ch1, ch2;

ch1 = getchar();

ch2 = getchar();

printf("%d %d\n", ch1, ch2);

此时,如果输入字符'a',而打印结果却是“97,10”。因为从键盘输入一个字符后,就打印出了结果,还没有输入第二个字符程序就结束了。由于键盘输入一次结束后,会将数据存储在一个被称为缓冲区的临时存储区,按下Enter键后程序才可使用用户输入的字符,因此scanf()和getchar()也是从输入流缓冲区中取值的,而人们常常会产生这样的错觉,误以为它们是从键盘缓冲区取值的。实际上,数据是通过cin函数直接从输入流缓冲区中取走的,所以,当缓冲区中有残留数据时,cin函数会直接读取这些残留数据而不会请求键盘输入。

这里的10恰好是Enter键输入的换行符'\n',当读取数据遇到换行符'\n'结束时,换行符会一起读入输入流缓冲区,所以第一次接受输入时,取走字符后会留下字符'\n',于是第二次直接从缓冲区中将\n取走。

为何要有缓冲区呢?首先,将若干字符作为一个块进行传输比逐个发送这些字符节约时间。其次,如果用户打错字符,可以直接通过键盘修正错误。当最后按下Enter键时,传输的是正确的输入。虽然输入缓冲区的好处很多,但在某些交互式程序中也需要无缓冲区输入。比如,在游戏中,如果希望按下一个键就执行相应的命令,因此缓冲输入和无缓冲输入各有各的用武之地,但本书假设所有的输入都是缓冲输入。

缓冲分为两类:完全缓冲I/O和行缓冲I/O,完全缓冲输入指的是当缓冲区被填满时才刷新缓冲区,内容被发送到目的地,通常出现在文件输入中。缓冲区的大小取决于系统,常见的大小为512字节和4096字节。行缓冲区I/O指的是在出现换行符时刷新缓冲区,键盘输入通常是行缓冲区输入,所以在按下Enter键后才刷新缓冲区。

getchar()和scanf()

getchar()读取每个字符,包括空格、制表符和换行符;而scanf()在读取数字时,则会跳过空格、制表符和换行符。虽然这两个函数都很好用,但不能混合使用。

虽然putchar()的参数ch定义为int类型,但实质上它接收的是一个char类型字符,因为在putchar()内部,系统会将ch强制转换为char类型后再使用。如果字符输出成功,则putchar()返回输出的字符((char)ch),而不是输入的参数ch;如果不成功,则返回预定义的常量EOF(end of file,文件结束),EOF是一个整数。

getchar()没有输入参数,其返回值为int型,而不是char型。这里需要区分文件中的有效数据和输入结束符,当有字符可读时,getchar()不会返回文件结束符EOF,所以

ch = getchar() != EOF //相当于ch = (getchar() != EOF)

取值为true,变量ch被赋值为1。

当程序没有输入时,则getchar()返回文件结束符EOF,即表达式取值为false,此时变量ch被赋值为0,程序结束运行。如果将getchar()函数的返回值定义为int型,则既能存储任何可能的字符,也能存储文件结束符EOF,将输入复制到输出的例程序详见程序清单1.36。

程序清单1.36将输入复制到输出范例程序

1 #include

2 int main(int argc, char *argv[])

3 {

4 int ch;

5

6 while((ch = getchar()) != EOF){

7 putchar(ch);

8 }

9 return 0;

10 }

当然,也可以用getchar()的另一种惯用法替代程序清单1.36(6):

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

即将读入的一个字符与换行符比较,如果测试结果为true,则执行循环体,接着重复测试循环条件,再读入一个新的字符,同时getchar()用于搜索字符和跳过字符等效。比如:

while((ch = getchar()) == ' ')

当循环终止时,变量ch将包含getchar()遇到的第一个非空字符。

do-while

do-while循环远比for和while循环用得小,因为它至少需要执行循环体一次,且在代码的最后而不是开始执行条件循环测试。逻辑条件应该出现在它们所“保护”的代码之前,这也是if、while和for的工作方式。通常阅读代码的习惯是从前向后,当使用do/while循环时,需要对这段代码读两次。同时,这种方式在很多情况下是不正确的,比如:

? do{

? ch = getchar();

? putchar(ch);

? }while(ch != EOF);

由于测试被放在对putchar()的调用之后,因此该代码无端地多写了一个字符。只有在某个循环体必须至少执行一次的情况下,使用do-while循环才是正确的。

另一个让人迷惑的是,do/while循环中的contiune语句:

do{

continue;

}while(false);

它会永远循环下去还是只执行一次?虽然它只会循环一次,但大多数人都会想一想。C++的开创者Bjarne Stroustrup是这样说的,“do语句是错误和困惑的来源,我倾向于将条件放在前面我能看到的地方,避免使用do语句。”

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据结构
    +关注

    关注

    3

    文章

    573

    浏览量

    40092

原文标题:周立功:字符能像整数一样计算

文章出处:【微信号:ZLG_zhiyuan,微信公众号:ZLG致远电子】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    程序设计基础:字符整数一样计算

    周立功教授数年之心血之作《程序设计与数据结构》,电子版已无偿性分享到电子工程师与高校群体,在公众号回复【程序设计】即可在线阅读。书本内容公开后,在电子行业掀起片学习热潮。经周立功教授授权,本公众号特对本书内容进行连载,愿共勉之。
    的头像 发表于 08-29 14:36 4489次阅读

    DSP能ARM一样跑系统吗?

    本帖最后由 mr.pengyongche 于 2013-4-30 03:25 编辑 平时听的太多ARM跑系统了,不知道在DSp上能跑系统不??刚开始学DSP,感觉上DSP一样很强大啊,怎么没听过在DSP上跑系统的呢??好希望DSP也能ARM
    发表于 03-23 13:52

    易语言可以labview一样简单吗

    labview可以易语言一样简单吗
    发表于 08-20 09:36

    allegro能AD一样打印负片吗?

    求教allegro能AD一样打印负片吗?如何操作?
    发表于 03-29 01:39

    请问AD做的原理图能否ORCAD一样能加下页间符数字符号?

    想请教个问题,AD做的原理图能否orcad一样能加下页间符数字符
    发表于 09-16 10:27

    LabVIEW是否能C语言一样

    LabVIEW是否能C语言一样
    发表于 09-11 18:41 38次下载

    机器鱼能真鱼一样游泳

    本周麻省理工学院的研究人员揭开了种看上去一样游泳的软体机器人,他们说类似的东西可能会渗透到真正的鱼的学校,并收集有关他们行为的数据。
    的头像 发表于 04-30 05:48 3468次阅读

    如何设计线性稳压器一样简单的复杂开关稳压器

    如何设计线性稳压器一样简单的复杂开关稳压器 - MicroModules_zh
    的头像 发表于 08-15 06:02 2996次阅读

    如何使工业用以太网标准以太网一样简单

    如何使工业用以太网标准以太网一样简单
    发表于 11-04 09:51 0次下载
    如何使工业用以太网<b class='flag-5'>像</b>标准以太网<b class='flag-5'>一样</b>简单

    让洗衣机蝙蝠一样会怎么?用声音来提供我们的生活品质.

    让洗衣机蝙蝠一样会怎么?用声音来提供我们的生活品质.
    发表于 11-04 09:51 0次下载
    让洗衣机<b class='flag-5'>像</b>蝙蝠<b class='flag-5'>一样</b>会怎么<b class='flag-5'>样</b>?用声音来提供我们的生活品质.

    Daniel一样为您计算饮料的设备

    电子发烧友网站提供《以Daniel一样为您计算饮料的设备.zip》资料免费下载
    发表于 12-19 10:47 0次下载
    以<b class='flag-5'>像</b>Daniel<b class='flag-5'>一样</b>为您<b class='flag-5'>计算</b>饮料的设备

    DJ一样控制 NeoPixels

    电子发烧友网站提供《DJ一样控制 NeoPixels.zip》资料免费下载
    发表于 12-28 09:28 0次下载
    <b class='flag-5'>像</b>DJ<b class='flag-5'>一样</b>控制 NeoPixels

    交通灯系统一样监控您的机器

    交通灯系统一样监控您的机器
    的头像 发表于 03-09 15:16 582次阅读
    <b class='flag-5'>像</b>交通灯系统<b class='flag-5'>一样</b>监控您的机器

    让超声波仪听诊器一样便携

    让超声波仪听诊器一样便携
    的头像 发表于 11-24 16:20 764次阅读
    让超声波仪<b class='flag-5'>像</b>听诊器<b class='flag-5'>一样</b>便携

    如何 awk一样分割字符

    ' ] 与我预想的结果不符,多个空格会被分割多次。 那有什么办法可以达到 awk 一样的效果呢? 有两种方法。 第种方法 不加参数,这
    的头像 发表于 11-02 11:14 670次阅读
    如何<b class='flag-5'>像</b> awk<b class='flag-5'>一样</b>分割<b class='flag-5'>字符</b>串