限制輸入
輸入與輸出是程式中最常用也是最重要的一部份,但在某些情況下,限制使用者
輸入資料是有必要的,除了能減少程式中因資料不符時所產生的意外錯誤及為了
因檢驗資料是否正確符合而另外加入與主題無關的程式碼,在討論輸入之前,你
必須先瞭解輸入資料所對應的ASCII碼,以做為限制輸入時比較之用.
	
	資料型態        ASCII範圍

      數字'0'~'9'            48 ~ 57	
			
   大寫英文字母'A'~'Z'      65 ~ 90
   小寫英文字母'a'~'z'       97 ~ 122
C++中所提供的輸入函數(cin,cin.get,cin.getline...)中,基本上資料會
先被放置到輸入串流(Input Stream)中,等到使用者送出完成輸入的動作時,
函數才開始動作,所以你無法在資料輸入的同時做檢驗資料的動作。舉個例子
程式如下:
::::::::::::::::::::::::::::::::::::::::::::::
  cin>>i;            //i is an int variable
  cin>>ch;         //ch is a char variable
  cin>>x;          //x is a float varible
::::::::::::::::::::::::::::::::::::::::::::::
假設使用者輸入如下(△表示空格,\n表示按Enter結束)25△A△16.9\n
這些資料在被放置到輸入串流中,並有一個get pointer控制讀取的位置,
灰色底色表示get pointer的位置,這是資料輸入完畢在輸入串流的結果:
25△A△16.9\n
1. cin>>i ;
=>行執行完畢時i等於25,而串流的狀態:25A△16.9\n
2.cin>>ch;
=>這行執行完畢時,ch等於'A',而串流的狀態:25△A16.9\n
3.cin>>x;
=>這行執行完畢時,x等於16.9,而串流的狀態:25△A△16.9\n
所以你應該能瞭解C++串流的一些概念。
C的輸入函式中提供了使用者基本的輸入函式,使用者能撰寫出符合自己要求的
函式,以下介紹幾個函式:

(1)getchar():可以讓我們從鍵盤上輸入一個字元,您所輸入的字元會立即顯示
             出來,並且當您按下Enter鍵後,這個字元才會被變數接收。
(2)getche() :可以讓我們從鍵盤上輸入一個字元,當您輸入字元後不需要按下
             Enter鍵,剛才所輸入的字元會立即顯示出來,變數也會馬上接收這個字元。
(3)getch()  :可以從鍵盤上輸入一個字元,不需要按下Enter鍵,變數會馬上接 收這個字元,
             而螢幕上看不到這個被輸入的字元。

函數的使用方法請參考C語言相關書籍,接著開始談論限制輸入的判斷方式,先看個範例

範例1
::::::::::::::::::::::::::::::::::::::::::::::
#include <stdio.h>

void main()
{
	char ch;

	for( ; ; )
	{
		ch = getche();
		if( ch<48 || ch>57 )	//最好寫成 if( ch< '0' || ch>'9' )比較易懂
			printf("\a\b \b");
		else
			break;
	}
}
::::::::::::::::::::::::::::::::::::::::::::::
[說明]
此程式的目的是要求使用者只能輸入0~9的數字,若不符合時,電腦會""一聲
並且要求使用者重新輸入,直到使用者輸入正確。
ch接收使用者輸入的字元,接著做判斷 : ch<48 || ch>57,這個判斷式並不難解釋
,數字的ASCII碼是48 ~ 57,若輸入的字元小於48或大於57時,表示他輸入的資料不
符合要求,不符合要求是必須警告使用者('\a')退回('\b')原位置並清除(' ')之前所輸
入的資料,接著退回('\b')原位置,等待輸入。
接著在看幾個範例
範例2
::::::::::::::::::::::::::::::::::::::::::::::
#include <stdio.h>

void main()
{
	char ch;
	for( ; ; )
	{
		ch = getche();
		if( (ch< 'A' || ch>'Z' ) && (ch< 'a' || ch>'z' ) )
			printf("\a\b \b");
		else
			break;
	}
}
::::::::::::::::::::::::::::::::::::::::::::::
[說明]
此程式的目的不難猜得出來,要求使用者只能輸入英文字母,判斷式就是
如果不在'A'~'Z'之間且不在'a'~'z'之間,則不符合輸入條件,請注
意邏輯哦!!!會出錯就錯在這裡了!!!但這可程式真得沒有問題了嗎?相信
有人一定認為這個程式輸入英文字母才能通過,那請試試看功能鍵F7,F8,F9
,F10及方向鍵看行不行,試了之後你會發現原來也符合英文字母呀!!!嘿嘿!!!
你有沒有聽到""一聲呢?有的話,代表它也不符合英文字母,那到底符合什麼啦!
先提供一個程式讓使用者測試輸入的按鍵所對應的ASCII碼:
範例3
::::::::::::::::::::::::::::::::::::::::::::::
#include <stdio.h>

void main()
{   
	int key1,key2;   
	
	do   
	{      
		printf("Input:");      
		key1=getch();      
		if(key1==0)      
		{         
			key2=getch();         
			printf("key_id = %d + %d\n",key1,key2);      
		}     
		else if(key1==224)
		{
			key2=getch();
			printf("key_id = %d + %d\n",key1,key2);      
		}
		else         
			printf("key_id = %d\n",key1);   
	} while(!(key1==27));	
}
::::::::::::::::::::::::::::::::::::::::::::::
ESC鍵的ASCII碼是27,此程式設計當使用者按ESC鍵時,離開。
你可以從程式中測試出,其實F1~F10是由二個Byte所組成的,第一個Byte00
而由第二個Byte區別你按的是那一個按鍵,F1~F10對應的ASCII碼如下:
F1  = 0 + 59
F2  = 0 + 60
F3  = 0 + 61
F4  = 0 + 62
F5  = 0 + 63
F6  = 0 + 64
F7  = 0 + 65
F8  = 0 + 66
F9  = 0 + 67
F10 = 0 + 68
而方向鍵也是由二個Byte組成的,第一個Byte224,而由第二個Byte區別:
224 + 72
↓224 + 80
←224 + 75
→224 + 77
現在你清楚了為什麼在前一個程式中按下功能鍵F7F8F9F10及方向鍵時,
會符合輸入條件,再不清楚沒有關係,我跟蹤程式一次讓大家看看:
在範例2中,按下F7:
ch = getche();
=>ch等於0值,0表示' '
=>由於不符合限制條件,所以迴圈重來一次
再一次碰到
ch = getche();
=>注意因為按F7時,會產生2ByteASCII碼,而前一次迴圈已經讀取第1Byte
  還剩下第2Byte,所以getche()會讀取之前所未讀取完畢的值,故畫面並不會
  有任何的顯示
=>ch等於65值,65剛好符合輸入限制條件,所以離開迴圈
由於按功能鍵會誤動作,所以必須把範例2加以修改才行,要怎麼修改呢?看囉:
範例4(範例2之修改版)
::::::::::::::::::::::::::::::::::::::::::::::
#include <stdio.h>

void main()
{
	char ch;
	for( ; ; )
	{
		ch = getche();
		if(ch == 0 || ch==224)                      //如果按功能鍵時
			getche();                                    //將第2Byte的值給吸收掉

		if( (ch< 'A' || ch>'Z' ) && (ch< 'a' || ch>'z' ) )
			printf("\a\b \b");
		else
			break;
	}
}
::::::::::::::::::::::::::::::::::::::::::::::
你按方向鍵看看,竟然能夠離開迴圈,怎麼搞的,有人開始懷疑我的文章的正確性了!!!
就算你的用的編譯器能夠真確的顯示符合的結果,那你的語法不太嚴謹!!!錯在那呢?
那為什麼不夠嚴謹呢?char為大小為1Byte,請問它能表示的範圍是多少呢?如果是
unsigned的話,就是0~255,如果是signed的話,就是-128~127,那請問沒有寫
是unsigned還是signed呢?有的編譯器是預設signed有的是unsigned,但不管如
何,建議你還是要加上unsignedsigned,這對於在各種平台上撰寫程式的網友來說
是非常重要的。另外型態相關表示的範圍可在標題檔limits.h裡找到類似這樣的資料:

...

#define CHAR_BIT      8            /* number of bits in a char */
#define SCHAR_MIN   (-128)      /* minimum signed char value */
#define SCHAR_MAX     127       /* maximum signed char value */
#define UCHAR_MAX     0xff       /* maximum unsigned char value */

...

在我的編譯器VC6.0上,預設是Signed,所以224的值已經超越它能處理的數值,會得到
錯的結果,所以你將char ch;改為unsigned char ch;就能正確的執行!!!
注意有些舊的編譯char型態並沒有signedunsigned之分,而是依據編譯之本身的定義
,這些數值都不是絕對的關係,在使用之前,你倒不如查查看自己編譯器的定義!!
最適當的方式就是以int型態來取代char型態,這種方式已經在很多書上出現了!!!
那如果限定輸入只能有英文字母、數字呢?要怎麼寫呢?自己試試看囉!!!那有函數可以
用呀!!!有的,不過當你知道這個原理之後,函數就變得不是那麼需要了,但在此還是提
供各位函數,但請使用方式請查詢相關資料:
(1)isalnum:是否為英文字母或數字
(2)isalpha:是否為英文字母
(3)isupper:是否為大寫英文字母
(4)islower:是否為小寫英文字母
相信以上的介紹,各位已經能撰寫出屬於自己的輸入函數,如輸入密碼,輸入數字…etc.

回目錄
Written By James On 2004/02/08 

Hosted by www.Geocities.ws

1