輸入輸出函數
1、簡單概述
前面在介紹中也提到了,計算機需要來處理數據,然后將處理完成后的結果輸出。
在計算機中,任何數據的輸入都是靠字符來輸入進去的,然后轉換成01代碼來保存到內存空間中去,這里暫時不考慮硬盤的問題。
所以將01代碼存儲到內存空間中去,以怎樣的數據類型來進行保存到內存空間中去以及從內存空間中取出來。
在C語言中提供了兩個函數來操作輸入和輸出的,其實都是對緩沖區中的數據來進行操作的。
我們鍵盤上的任意一個字符都會在緩沖區中有對應的表示。比如說Tab、Enter和空格,這三個是最明顯的。
printf():打印,將緩沖區中的結果打印在控制台上;
scanf():掃描鍵盤上敲下的數據到緩沖區中,然后讀取賦值給變量;
關於緩沖區的介紹,類似流這種概念。
2、printf函數
輸出函數,四種用法:
2.1、第一種用法
# include <stdio.h>
int main(void){
printf("hello,c\n");
return 0;
}
控制台顯示:
hello,c
--------------------------------
Process exited after 0.3468 seconds with return value 0
請按任意鍵繼續. . .
那么一直這樣寫,為何要加上一個\n呢?
再看下不加的情況:
# include <stdio.h>
int main(void){
printf("hello,c");
return 0;
}
看下控制台顯示:
hello,c
--------------------------------
Process exited after 0.5481 seconds with return value 0
請按任意鍵繼續. . .
對比下,可以看到,不加\n和加了\n,控制台中少了一行空格。那么這個空格就是因為\n造成的。
因為計算機中無法通過一個字符來描述空格,所以只能通過多個來進行描述。這種字符是比較特殊的,叫做轉義字符。
2.2、第二種用法
直接看程序,然后總結:
# include <stdio.h>
int main(void){
int i = 520;
printf("%d",i);
return 0;
}
看下控制台輸出:
520
--------------------------------
Process exited after 0.1145 seconds with return value 0
請按任意鍵繼續. . .
其中,%是輸出控制符,d表示的是將i變量對應的01代碼以十進制的格式輸出。這里終於明白了以前為什么要這么來寫了。
說明了在C語言中使用的編碼是ASCII碼表的方式,在idea中使用的UTF-8,可以輸出任意的字符和數據。
也就是手將變量對應的二進制數據以什么樣的格式進行輸出。
%d:輸出變量對應的01代碼以十進制格式輸出整數;
%ld:輸出變量對應的01代碼以十進制格式輸出長整型整數(long int);
%x(%X或者%#X):輸出變量對應的01代碼以十六進制輸出整數;其中#X是常用的,因為要以十六進制為標識輸出;保證可讀性好,java里面采用的也是十六進制的;
%o:輸出變量對應的01代碼以八進制格式輸出整數;
%c:輸出變量對應的01代碼以字符格式輸出;
%f:輸出變量對應的01代碼以小數格式輸出;
%lf:輸出變量對應的01代碼以成小數格式輸出長類型小數(double);
# include <stdio.h>
int main(void){
int i = 10;
printf("%x\n",i);
printf("%X\n",i);
printf("%#x\n",i);
printf("%#X\n",i);
return 0;
}
控制台輸出:
a
A
0xa
0XA
--------------------------------
Process exited after 0.1815 seconds with return value 0
請按任意鍵繼續. . .
控制台顯示更加通俗易懂。
2.3、第三種用法
# include <stdio.h>
int main(void){
int i = 10;
int j = 5;
printf("%d %d\n",i,j);
return 0;
}
控制台輸出多個變量的值,一個輸出控制符對應的是一個變量的值,不能夠多一個,也不能少一個,一一對應:
10 5
--------------------------------
Process exited after 0.1213 seconds with return value 0
請按任意鍵繼續. . .
2.4、第四種用法
# include <stdio.h>
int main(void){
int i = 100;
printf("value is:%#X\n",i);
return 0;
}
控制台顯示:
value is:0X64
--------------------------------
Process exited after 0.1651 seconds with return value 0
請按任意鍵繼續. . .
非控制符以原來的字符進行了輸出。
2.5、為什么需要輸出控制符
首先明確一點:01所組成的代碼既可以表示成指令,也可以表示成數據;因為01代碼本身沒有含義,但是如何去解讀01代碼成為了關鍵
01代碼以不同的格式進行解讀,那么得到的值可能是不一樣的。最簡單的方式驗證如下:
# include <stdio.h>
int main(void){
int i = 100;
printf("value is:%d\n",i);
printf("value is:%f\n",i);
printf("value is:%lf\n",i);
printf("value is:%#X\n",i);
printf("value is:%0\n",i);
return 0;
}
控制台顯示如下:
value is:100
value is:0.000000
value is:0.000000
value is:0X64
value is:
--------------------------------
Process exited after 0.6483 seconds with return value 0
請按任意鍵繼續. . .
可以看到對於存儲在內控空間中的一段01代碼,以不同的格式來進行解讀,發現對應的值也是不同的;
3、scanf函數
從鍵盤上錄入字符,將字符轉換成輸入函數中對應格式的數據。一定要記住,從控制台錄入進去的都是字符!
操作系統將字符轉換成對應的類型,所以這里就可能會出現問題。所以要找規定的數據類型來進行轉換。
# include <stdio.h>
int main(void){
int i ;
// scanf("i value is: %d",&i);
printf("請輸入i的值: \n");
// 不能夠在前面加上非操作符,因為要是加上了,在控制台上進行輸入的時候,還得加上:i value is: ,比較麻煩,所以這里用輸出函數代替一下
scanf("%d\n",&i);
printf("i vlaues is:%d\n",i);
return 0;
}
控制台輸出:
請輸入i的值:
10
10
i vlaues is:10
--------------------------------
Process exited after 3.174 seconds with return value 0
請按任意鍵繼續. . .
發現了三個問題:
1、輸入的時候,指定對應的數據格式;不要多寫,要是多寫的話要加上對應的數據;
2、輸入的時候,發現輸入了兩次i的值,然后才輸出了變量i的值;
3、在輸出控制符中,對於變量的操作沒有加&,而對於輸入控制符來說,卻加上了。為何?規定而已
對於輸入函數來說,加上了&表示的是,將i變量對應的內存地址取出來,然后將01代碼寫入內存地址空間中去;
對於輸出函數來說,直接操作變量i對應的內存地址空間中的01代碼取出來,然后按照輸出格式來進行輸出;
這跟java中是一模一樣的,但是java使用了utf-8之后,將對應變量的地址中的值取出來之后,因為變量規定了數據類型,那么就按照指定的數據類型來進行顯示。
所以注意的是在輸入控制符中,不要輸入於輸入控制符無關的非輸入控制符
繼續去看上面的問題:為什么輸入完一個值之后,還需要我輸入第二個值才能夠進行輸出呢?
原因就在於scanf這個函數,\n是它的結束,這個是隱式的,而不是顯示的。鍵盤上的Tab和Enter都是隱式的。如果顯示的寫上了,那么scanf要求,你輸入的就需要帶上\n
# include <stdio.h>
int main(void){
int i ;
printf("請輸入i的值: \n");
// 這里加上了\n,發現怎么輸入都沒有用,於是加上了\n,發現輸入成功了。那么也就是說scanf里面要求顯示的寫了什么非操作符在輸入的時候就得加上什么非操作符
// 所以說這里是非常不好的輸入格式
scanf("%d\n",&i);
printf("i vlaues is:%d\n",i);
return 0;
}
這里從網上查了一下資料:
Enter對應的ASCII碼表中的的\n;Tal對應的是空格,對應的是ASCII碼表中的0;
在C語言中,輸入函數把用戶輸入的鍵盤上的內容全部當做是字符來處理,利用了一個緩沖區
比如說:鍵盤上輸入:
123456789abcd
如果代碼中寫的是:
# include <stdio.h>
int main(void){
printf("請輸入i的值:\n");
int i;
scanf("%d",&i);
scanf("%d",&i);
printf("i的值是:%d\n",i);
return 0;
}
我在控制台上進行輸入的時候:
請輸入i的值:
12m
i的值是:12
--------------------------------
Process exited after 4.391 seconds with return value 0
請按任意鍵繼續. . .
將我從控制台上的m給過濾掉了,因為操作系統在將字符串轉換的時候,發現m無法存入到int類型的變量中去,就從這里開始自動忽略掉了
但是不能夠將m放在最前面,dev編譯器自動賦值為0;
再看一種情況:
# include <stdio.h>
int main(void){
printf("請輸入i的值:\n");
int i,j;
scanf("%d",&i);
scanf("%d",&j);
printf("i的值是:%d\n",i);
return 0;
}
我從控制台輸入:
123456a
發現沒有報錯,直接輸出了:
請輸入i的值:
123456a
i的值是:123456
j的值是:1
--------------------------------
Process exited after 3.26 seconds with return value 0
請按任意鍵繼續. . .
發現無論在123456后面寫什么,j輸出的都是1。
為了解決這種問題,引用了比較常見的解決方式:
# include <stdio.h>
int main(void){
printf("請輸入i的值:\n");
int i,j;
scanf("%d",&i);
char ch;
printf("請輸入j的值:\n");
while( (ch = getchar() ) != '\n'){
continue;
}
scanf("%d",&j);
printf("i的值是:%d\n",i);
printf("j的值是:%d\n",j);
return 0;
}
在控制台輸入:
請輸入i的值:
12345 jkljkljkkjfdklsjafljslf dklsafjldsjafkldjsalfjdasdkljsfjas
請輸入j的值:
1
i的值是:12345
j的值是:1
--------------------------------
Process exited after 11.41 seconds with return value 0
請按任意鍵繼續. . .
這里說明了,操作系統只會從控制台挑選出來指定的符合的來給變量賦值,不符合不賦值;
然后選擇隱式的\n來作為換行,輸入下一行,知道選擇到用戶輸入的合適的地方,所以這一塊的內容很有意思。
但是第一次輸入的賦值上了,如果第二次依然無法和對應的數據類型匹配,那么依然會有默認值。
所以輸入函數比較強大。所以輸入函數掌握好。
也就是說從緩沖區中將\n從緩存區中取走了,那么接下來的繼續從緩存區來進行讀取,然后來進行賦值。
gets()以回車符作為字符串的終止符,同時將回車符從緩沖區讀走,但不作為字符串的一部分
scanf()以空格、回車、制表符作為字符串的終止符,不讀走空格、制表符、回車符,仍留在緩沖區中
所以這里也就導致了,如果是兩次進行輸入的,那么第一次會取到合適的內容來進行賦值;然后對於第二次賦值來說,如果是賦值的話,一般我們在輸入之后,會遺留下來一個'\n',
那么這個是無法來進行賦值的。所以就導致了無法賦值成功的情況,所以一般來說會用getChar()方法來解決。