7.24,《C Primer Plus》復習第十五章第二小題
編寫一個程序,通過命令行參數讀取兩個二進制字符串,對這兩個二進制數使用~運算符,&運算符、|運算符,并以二進制字符串形式打印結果(如果無法使用命令行環(huán)境,可以通過交互式讓程序讀取字符串)
編寫程序的時候,在檢查二進制函數bcheck()中遇到了問題,我當時的思路是,如果函數檢查后發(fā)現輸入錯誤導致is置0,就調用s_gets()函數(規(guī)范輸入,輸入太長丟棄規(guī)定位數后的輸出,輸入太短把換行符置為'\0')改變原來的字符串,再講改好的結果送回bcheck中重新檢驗,直至輸入正確才繼續(xù)程序的下一步,
這就像過飛機場檢查,如果檢查員覺得你不符合規(guī)定,你得把違規(guī)物品留在檢口外(用輸入函數重新改變輸入),再讓檢查員檢查你一次,直到你符合規(guī)定才能放你過去
我當時的修改為
#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; }
可在運行的時候發(fā)現,函數運行完竟回彈了回去!

原來是我遺忘了關于函數遞歸的知識,如果想在不觸發(fā)遞歸的情況下正常得再跑完一次函數,怎么辦呢?
我再聯想到那個過檢查的例子,發(fā)現檢查函數最大的作用其實就是返回判斷值is=0或者1(檢查員告訴你有沒有違規(guī))。然后你根據檢查函數的判斷確定是否修改輸入,在現實中,丟掉不合格的物品,重新回到關口,讓檢查員檢查都可以看作一個過程函數,且“”不合規(guī)定“是”“丟掉不合格的物品”的充分條件,“丟掉不合格的物品”是回到“回到關口”的充分條件
基于這樣的想法我重新設計了函數:
/*實驗效果:運行程序,程序要求輸入兩個字符串,輸入后返回
兩個字符串經過“~,&,|,^”運算后的二進制值
偽代碼:
定義字符數組bin1,bin2,bin3存儲兩個二進制數,定義整數v1,v2存儲兩個十進制數;
向bin1 bin2輸入要運算的二進制數,輸入結果須通過bcheck(){1}函數檢驗;
由于位運算符的參數都是十進制數,需要bstr_to_dec(){2}函數將兩字符轉化為
十進制數,賦值給v1,v2;
在打印結果中讓v1,v2作為位運算符“~,&,|,^”的參數,運算結果要用dec_to_bstr(){3}函數
轉化為十進制;
運算結束后,詢問用戶是否重新輸入,若是從第二行偽代碼起重復循環(huán),否則退出;
{1}:輸入為二進制字符串,原理為遍歷二進制字符,以整數is作為鑒定標記,檢查標準為字符中沒有0和1以外的數
如果檢查成功,is置1,返回檢測值is
如果檢查失敗,is置0
新輸入的字符串重新返回檢查進行檢驗,若檢查成功is置1,否則置0
(后繼:程序根據is作出判斷,如果為1,則字符串不變;如果為0,則報錯并要求重新輸入該字符串
(利用modify()函數修改[4])
在本例中兩個函數都得輸對才能通過下一個函數
{2}:輸入為二進制字符串,循環(huán)遍歷每一位并將其與2的對應冪相乘并相加,中止條件為
到達字符串的底部'\000
{3}:輸入為十進制數n,循環(huá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字符串就檢查了兩次),這種代碼看起就像,到了關口檢查員告知你不符合規(guī)定,你不是返回去而是直接進入想象世界,想象中你丟掉了你那些不合格的物品,讓檢查員放你過去,但你當回過神來時你還在關口,檢查員卻突然告知你“你可以過去了一樣”,一臉懵逼。


浙公網安備 33010602011771號