zoukankan      html  css  js  c++  java
  • 7.24,《C Primer Plus》复习第十五章第二小题

    编写一个程序,通过命令行参数读取两个二进制字符串,对这两个二进制数使用~运算符,&运算符、|运算符,并以二进制字符串形式打印结果(如果无法使用命令行环境,可以通过交互式让程序读取字符串)

    编写程序的时候,在检查二进制函数bcheck()中遇到了问题,我当时的思路是,如果函数检查后发现输入错误导致is置0,就调用s_gets()函数(规范输入,输入太长丢弃规定位数后的输出,输入太短把换行符置为'')改变原来的字符串,再讲改好的结果送回bcheck中重新检验,直至输入正确才继续程序的下一步,

    这就像过飞机场检查,如果检查员觉得你不符合规定,你得把违规物品留在检口外(用输入函数重新改变输入),再让检查员检查你一次,直到你符合规定才能放你过去

    我当时的修改为

    复制代码
    /*实验效果:运行程序,程序要求输入两个字符串,输入后返回
    两个字符串经过“~,&,|,^”运算后的二进制值

    伪代码:
    定义字符数组bin1,bin2,bin3存储两个二进制数,定义整数v1,v2存储两个十进制数;

    向bin1 bin2输入要运算的二进制数,输入结果须通过bcheck(){1}函数检验;

    由于位运算符的参数都是十进制数,需要bstr_to_dec(){2}函数将两字符转化为
    十进制数,赋值给v1,v2;

    在打印结果中让v1,v2作为位运算符“~,&,|,^”的参数,运算结果要用dec_to_bstr(){3}函数
    转化为十进制;

    运算结束后,询问用户是否重新输入,若是从第二行伪代码起重复循环,否则退出;


    {1}:输入为二进制字符串,原理为遍历二进制字符,如果检查后发现字符中有0和1以外的数,
    提示并叫人重新输入(用指针修改参数字符串并重新返回检验函数),在本例中两个函数都得输对才能通过下一个函数

    {2}:输入为二进制字符串,循环遍历每一位并将其与2的对应幂相乘并相加,中止条件为
    到达字符串的底部'00

    {3}:输入为十进制数n,循环不断将n除2,取n%2赋值给赋值给字符串的对应位
    (从size起倒数),中止条件为n除2等于0,返回结果是二进制字符串bstr

    伪代码:
    获取第一字符串()已经由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); int main() { char bin1[SIZE],bin2[SIZE],bin3[SIZE]; int v1,v2; printf("input bin1 bin2: "); 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 ",bin1,bin2); printf("and decimal number is:%d %d ",v1,v2); } char* bcheck(char* pb) { int is=1; while(*st!='00') { char* st = pb; if(*st!='1'&& *st!='0') { is=0; } while(is!=1) { printf("%s is not a binary number,input again: ",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!='00') { 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的对应幂相乘并相加,中止条件为
    到达字符串的底部'00
    
    {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:
    ");  
        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
    ",bin1,bin2);
        printf("and decimal number is:%d    %d
    ",v1,v2);
    
    }
    
    char* bcheck(char* pb)
    {
        char* st=pb;
        int is=1;
        while(*st!='00')
        {   
            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!='00')
        {
        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字符串就检查了两次),这种代码看起就像,到了关口检查员告知你不符合规定,你不是返回去而是直接进入想象世界,想象中你丢掉了你那些不合格的物品,让检查员放你过去,但你当回过神来时你还在关口,检查员却突然告知你“你可以过去了一样”,一脸懵逼。

  • 相关阅读:
    通过模板类简单实现Spark的JobServer
    aggregate 和 treeAggregate 的对比
    IntelliJ Idea 常用快捷键列表
    dataframe 数据统计可视化---spark scala 应用
    用java api读取HDFS文件
    .net Core 简单中间件使用
    .Net Core Ocelot网关使用熔断、限流 二
    .Net Core Ocelot网关使用 一
    Docker 问题处理
    CentOS 创建用户
  • 原文地址:https://www.cnblogs.com/Tracker647/p/13371992.html
Copyright © 2011-2022 走看看