7.24,《C Primer Plus》复习第十五章第二小题
编写一个程序,通过命令行参数读取两个二进制字符串,对这两个二进制数使用~运算符,&运算符、|运算符,并以二进制字符串形式打印结果(如果无法使用命令行环境,可以通过交互式让程序读取字符串)
编写程序的时候,在检查二进制函数bcheck()中遇到了问题,我当时的思路是,如果函数检查后发现输入错误导致is置0,就调用s_gets()函数(规范输入,输入太长丢弃规定位数后的输出,输入太短把换行符置为'\0')改变原来的字符串,再讲改好的结果送回bcheck中重新检验,直至输入正确才继续程序的下一步,
这就像过飞机场检查,如果检查员觉得你不符合规定,你得把违规物品留在检口外(用输入函数重新改变输入),再让检查员检查你一次,直到你符合规定才能放你过去
我当时的修改为
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "s_gets.h"
#include <math.h>
#define SIZE 8
char* bcheck(char* pb);
int bstr_to_dec(char* pb);
int main()
{
char bin1[SIZE],bin2[SIZE],bin3[SIZE];
int v1,v2;
printf("input bin1 bin2:\n");
s_gets(bin1,SIZE);
s_gets(bin2,SIZE);
bcheck(bin1);
bcheck(bin2); v1=bstr_to_dec(bin1);
v2=bstr_to_dec(bin2); printf("Check pass.Your binarynumber is:%s %s\n",bin1,bin2);
printf("and decimal number is:%d %d\n",v1,v2); }
char* bcheck(char* pb)
{
int is=1; while(*st!='\000')
{
char* st = pb;
if(*st!='1'&& *st!='0')
{
is=0;
}
while(is!=1)
{
printf("%s is not a binary number,input again:\n",pb);
s_gets(pb,SIZE);
}
*st++;
}
return pb;
} int bstr_to_dec(char* pb)
{
int len=strlen(pb),i=1,dec=0;
char* st = pb;
while(*st!='\000')
{
dec=dec+((int)*st-48)*pow(2,len-i);
*st++;
i++;
}
return dec;
}
可在运行的时候发现,函数运行完竟回弹了回去!
原来是我遗忘了关于函数递归的知识,如果想在不触发递归的情况下正常得再跑完一次函数,怎么办呢?
我再联想到那个过检查的例子,发现检查函数最大的作用其实就是返回判断值is=0或者1(检查员告诉你有没有违规)。然后你根据检查函数的判断确定是否修改输入,在现实中,丢掉不合格的物品,重新回到关口,让检查员检查都可以看作一个过程函数,且“”不合规定“是”“丢掉不合格的物品”的充分条件,“丢掉不合格的物品”是回到“回到关口”的充分条件
基于这样的想法我重新设计了函数:
/*实验效果:运行程序,程序要求输入两个字符串,输入后返回
两个字符串经过“~,&,|,^”运算后的二进制值 伪代码:
定义字符数组bin1,bin2,bin3存储两个二进制数,定义整数v1,v2存储两个十进制数; 向bin1 bin2输入要运算的二进制数,输入结果须通过bcheck(){1}函数检验; 由于位运算符的参数都是十进制数,需要bstr_to_dec(){2}函数将两字符转化为
十进制数,赋值给v1,v2; 在打印结果中让v1,v2作为位运算符“~,&,|,^”的参数,运算结果要用dec_to_bstr(){3}函数
转化为十进制; 运算结束后,询问用户是否重新输入,若是从第二行伪代码起重复循环,否则退出; {1}:输入为二进制字符串,原理为遍历二进制字符,以整数is作为鉴定标记,检查标准为字符中没有0和1以外的数
如果检查成功,is置1,返回检测值is
如果检查失败,is置0
新输入的字符串重新返回检查进行检验,若检查成功is置1,否则置0 (后继:程序根据is作出判断,如果为1,则字符串不变;如果为0,则报错并要求重新输入该字符串
(利用modify()函数修改[4]) 在本例中两个函数都得输对才能通过下一个函数 {2}:输入为二进制字符串,循环遍历每一位并将其与2的对应幂相乘并相加,中止条件为
到达字符串的底部'\000 {3}:输入为十进制数n,循环不断将n除2,取n%2赋值给赋值给字符串的对应位
(从size起倒数),中止条件为n除2等于0,返回结果是二进制字符串bstr {4}:输入为输错的二进制字符串,用s_gets函数做修改,输入完毕后返回给bcheck函数做检查 伪代码:
获取第一字符串()已经由s_gets处理)
当第一字符串不是二进制数,报错,重新输入(即再调用s_gets函数输入值),直至其是为止,
第二类推,两个都得输入正确才能进入下一个步骤 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "s_gets.h"
#include <math.h>
#define SIZE 8 char* bcheck(char* pb);
int bstr_to_dec(char* pb);
char* modify(char* pb); int main()
{
char bin1[SIZE],bin2[SIZE],bin3[SIZE];
int v1,v2;
printf("input bin1 bin2:\n");
s_gets(bin1,SIZE);
s_gets(bin2,SIZE);
bcheck(bin1);
bcheck(bin2); v1=bstr_to_dec(bin1);
v2=bstr_to_dec(bin2); printf("Check pass.Your binarynumber is:%s %s\n",bin1,bin2);
printf("and decimal number is:%d %d\n",v1,v2); } char* bcheck(char* pb)
{
char* st=pb;
int is=1;
while(*st!='\000')
{
if(*st!='0' && *st!='1') //检查条件
{
is=0;
modify(pb);
}
*st++;
} return pb;
} int bstr_to_dec(char* pb)
{
int len=strlen(pb),i=1,dec=0;
char* st = pb;
while(*st!='\000')
{
dec=dec+((int)*st-48)*pow(2,len-i);
*st++;
i++;
}
return dec;
} char* modify(char* pb)
{
printf("%s is not a binary number,input again:",pb);
s_gets(pb,SIZE);
bcheck(pb);
return pb;
}
结果一切正常:
input bin1 bin2:
1010
11111
Check pass.Your binarynumber is:1010 11111
and decimal number is:10 31
但是美中不足的就是,modify()函数(重置输入,即“丢掉不合格的物品”)与bcheck()函数是互相调用的,当modify()函数的使命完成后bcheck仍会检查因modify()调用而改变的st字符串(尽管它已经随着pb的纠正而纠正,这样正确的st字符串就检查了两次),这种代码看起就像,到了关口检查员告知你不符合规定,你不是返回去而是直接进入想象世界,想象中你丢掉了你那些不合格的物品,让检查员放你过去,但你当回过神来时你还在关口,检查员却突然告知你“你可以过去了一样”,一脸懵逼。
7.24,《C Primer Plus》复习第十五章第二小题的更多相关文章
- CSS3秘笈复习:十三章&十四章&十五章&十六章&十七章
第十三章 1.在使用浮动时,源代码的顺序非常重要.浮动元素的HTML必须处在要包围它的元素的HTML之前. 2.清楚浮动: (1).在外围div的底部添加一个清除元素:clear属性可以防止元素包围浮 ...
- C++ Primer Plus学习:第十五章
第十五章 友元.异常和其他 友元 友元类 表 0-1 class Tv { public: friend class Remote; } Remote类可以使用Tv的数据成员,Remote类在Tv类后 ...
- 【C++】《C++ Primer 》第十五章
第十五章 面向对象程序设计 一.OOP:概述 面向对象程序设计(OOP)的核心思想是数据抽象.继承和动态绑定. 通过使用数据抽象,可以将类的接口和实现分离. 使用继承,可以定义相似的类型并对其相似关系 ...
- 《Linux命令行与shell脚本编程大全》 第十五章 学习笔记
第十五章:控制脚本 处理信号 重温Linux信号 信号 名称 描述 1 HUP 挂起 2 INT 中断 3 QUIT 结束运行 9 KILL 无条件终止 11 SEGV 段错误 15 TERM 尽可能 ...
- Gradle 1.12 翻译——第十五章. 任务详述
有关其他已翻译的章节请关注Github上的项目:https://github.com/msdx/gradledoc/tree/1.12,或访问:http://gradledoc.qiniudn.com ...
- Gradle 1.12用户指南翻译——第二十五章. Scala 插件
其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...
- 15第十五章UDF用户自定义函数(转载)
15第十五章UDF用户自定义函数 待补上 原文链接 本文由豆约翰博客备份专家远程一键发布
- Gradle 1.12用户指南翻译——第四十五章. 应用程序插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- Gradle 1.12用户指南翻译——第三十五章. Sonar 插件
本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
随机推荐
- Python中判断字符串是否为数字、字母、标识符、浮点数、大小写、可打印的方法
1.判断s是否都是大写字母:s.isupper(): 2.判断s是否都是小写字母:s.islower(): 3.判断s中的每个单词首字母是否都是大写字母且其他位置无大写字母:s.istitle(),要 ...
- 自学linux——21. NFS服务器的搭建
NFS服务器的搭建 1.NFS的认识 NFS(Network File System即网络文件系统)服务最大的功能就是可以透过网络,让不同的机器.不同的操作系统.可以彼此分享文件,可以将远程 Linu ...
- 团队作业三——需求改进&系统设计
需求改进&系统设计 一. 需求&原型改进 1. 针对课堂讨论环节老师和其他组的问题及建议,对修改选题及需求进行修改 老师及其他组的同学在课堂讨论时尚未提出问题及修改意见,但是课后我们有 ...
- datagrip2020最新安装破解教程方法激活码安装参数
现在,datagrip的版本已更新至2020.3,尚未升级的用户请赶快升级. 本文教您如何安装datagrip2020.3版本并破解它. 此方法可以100%永久激活datagrip2020.3(低版本 ...
- POJ3565
题目大意: 给定\(n\)个蚂蚁和\(n\)颗苹果树的坐标,要求每个蚂蚁爬到一颗苹果树旁,使得每个蚂蚁路线不相交且路线总长度最小,求每个蚂蚁爬到哪个苹果树旁? 首先假设有两只蚂蚁路径相交,那么这两个蚂 ...
- BJOI2015 隐身术
落谷. Description 给你两个串 \(A.B\).询问 \(B\) 中有多少个非空子串和 \(A\) 的编辑距离不超过 \(K\). Solution 发现 \(K \le 5\),考虑可以 ...
- PhotoSwipe用法
1.自动识别data-size问题,添加以下代码 gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options) ...
- 小米k30 pro刷国际版rom
时间:2020.8.20 最新的是miui12但是普遍反映耗电量巨大,所以还是刷miui11了. 知乎上有个教程:https://zhuanlan.zhihu.com/p/86160027 但是是针对 ...
- axios 封装 跨域 实现 (后端跨域配置白名单)
1. 始vue化项目 vue init webpack deaxios # 使用脚手架创建项目 deaxios(项目名,随便取得) cd deaxios # 进入项目cnpm install npm ...
- centos 7 让脚本开机运行
按照网上搜索的文章指导,有三种方式可以实现,个人觉得比较简单的是修改/etc/rc.d/rc.local,添加要开机执行的命令. 修改后,重启,发现要运行的服务没有启动. 搜索发现下面这篇博客解释了原 ...