基礎知識
C語言中所有輸入輸出都用流(stream)完成。流按行組織字符序列,每一行用一個換行符結束。至少3種流與程序連接:stdin,stdout,stderr。一個流是內存中的一個緩沖區,程序運行中輸入輸出數據都被收集在相應緩沖區中。
字符數據的輸入
1.輸入單字符函數getchar:從標准輸入流stdin中當前讀入位置讀入一個字符(包括空格、\n、Tab),讀取成功返回該字符編碼,出錯或遇到EOF則返回-1。成功讀入后stdin當前讀入位置自動后移一個字符。
2.getchar是帶參數的類函數宏定義:
#define getchar() getc(stdin)
字符數據的輸出
1.輸出單字符函數putchar:將程序中的一個字符的編碼不加處理地送到標准輸出流stdout的當前輸出位置,並把對應的符號顯示在屏幕上。正確時返回送出的字符編碼,出錯時返回-1。成功后將stdout當前位置后移一個字符。
2.putchar是帶參數的類函數宏定義:
#define putchar(c) putc(c,stdout)
3.參數總是按無符號整數解釋。在0~255之外的值按256取模。
//輸出換行符 putchar('\n'); putchar('\12'); putchar('\xa');
格式化輸出
1.格式化輸出函數printf:將調用時給出的輸出項按指定的格式轉換為字符序列送到stdout並在屏幕上顯示。返回值為實際輸出的字符個數。
printf(格式控制字符串,輸出項表)
2.格式控制字符串包括轉換說明(% 轉換修飾符 轉換說明符)和普通字符。這里不再贅述。
3.輸出項表:由若干個輸出項構成,各輸出項之間用逗號分隔。
4.pritnf函數工作原理:執行printf函數時,首先計算各個輸出項的值,但各個編譯器求值順序可能不同。每個輸出項表達式求值后按其結果類型被順序儲存到“堆棧”。然后掃描格式控制字符串,若遇到非轉換說明則直接把該字符放入輸出緩沖區的當前位置;當遇到轉換說明時,則按指出的類型從堆棧中取出對應長度的數據,按要求轉換成字符序列順序放入輸出緩沖區(buffer)。最后把輸出緩沖區中加工好的內容傳送到屏幕上。
把輸出緩沖區內容傳送到屏幕稱為刷新緩沖區(flushing the beffer),C標准規定了輸出緩沖區三種情況:
①當輸出緩沖區滿時
②當遇到換行符時
③當有新的輸入請求時
5.printf輸出不同類型數據:
①輸出整數:
- 采用%d輸出long型數時,只取該數的低16位;
- 以八進制或十六進制輸出整數是將整型數的所有位(包括符號位)按對應形式輸出,因此輸出的數值不帶符號;
- 當輸出字符個數大於域寬修飾符時,域寬修飾符無效;
- 域寬不足時整數輸出右端補以空格;
②輸出實數:
- 使用%e, %g輸出實數若使用精度修飾符(.n), n指有效數字位數;
③輸出字符:
- 若輸出數據為整型數,則把整型數理解成無符號數對256取模作為輸出字符的編碼;
④輸出字符串:
- 使用%s將從第一個字符開始一直輸出到字符串結束標志'\0'為止;
- 域寬修飾符小於字符串長度時域寬修飾符無效;
- 域寬修飾符小於精度修飾符時域寬修飾符無效;
#include<stdio.h> int main() { printf("%s", "hello \0 world"); return 0; } //輸出"hello "
⑤ 修飾符" * ": 可以利用" * "暫時代替域寬或精度,其值由輸出項表中對應的輸出項決定, 如:
printf("%*.*f", x, y, z); //表示輸出域寬x,精度y的浮點數z
格式化輸入
1.格式化輸入函數scanf:將從stdin讀取的若干字符按格式字符串的轉換說明轉換為指定類型的數據,並保存到對應得輸入項中。返回值為實際讀入並成功轉換的輸入項個數。
scanf(格式控制字符串,輸入項表)
2.格式控制字符串包括轉換說明、普通字符和空白字符(空格、\n、Tab)。
- 普通字符用來指出輸入輸出流中字段間的特殊分隔符;
- 空白字符與輸入流中作為數據分隔符的空白字符不必一一對應;
- 普通字符與輸入流中作為數據分隔符的普通字符必須一一對應;
3.一個字段有以下幾種含義:
- 由一系列非空白字符組成;
- 從stdin當前讀入位置的第一個非空白字符起到下一個空白字符之間的讀入字符;
- 從stdin當前讀入位置的第一個非空白字符起到轉換說明指定的寬度為止的已讀入字符;
- 從stdin當前讀入位置的第一個非空白字符起到一個當前轉換說明不能轉換的字符為止的已讀入內容;
#include<stdio.h> int main() { int a = 10; scanf("%d", &a); printf("%d", a); return 0; } /* 輸入12 -> 12 輸入12a -> 12 輸入a -> 10 */
4.輸入項表:由若干地址組成,地址之間用逗號隔開。
5.scanf輸入不同類型數據:
①輸入整數:
- 使用%i可以接受十進制整數,八進制和十六進制常量書寫形式的輸入字段;
②輸入浮點數:
- 不能使用精度修飾符輸入指定精度的數據;
- %f和%e都可以用指數形式和小數形式輸入數據;
- 輸入double型數必須使用%lf或%le, 輸入long double必須使用%Lf或%Le;
③輸入字符:
- %c可以從鍵盤上輸入任何字符,包括組合鍵;
④輸入字符串:
- %s輸入時總是從第一個非空白字符開始讀入, 直到遇到空白字符停止讀入;
- gets允許輸入的字符序列中含有空格,總是以回車換行符或EOF結束輸入;
# include <stdio.h> int main() { char str[30]; char ch; scanf("%s",str); printf("%s\n", str); scanf("%c", &ch); printf("ch=%c\n", ch); return 0; } /* 輸入 hay 輸出 hay ch= */
# include <stdio.h> int main() { char str[30]; char ch; gets(str); printf("%s\n", str); scanf("%c", &ch); printf("ch=%c\n", ch); return 0; } /* 輸入 hay 輸出 hay 輸入 a 輸出 a */
⑤賦值抑制符壓縮修飾符" * "把正常讀入的字段丟掉, 並不賦給某個輸入對象, 如:
scanf("%d%*c%d%*c%d", &y, &m, &d);
⑥域寬修飾符: 從輸入數據中截取與域寬值相同的字符數作為一個字段轉換成指定類型的數據, 如:
scanf("%3d%4d%3c%c",&a, &b, &c, &d); 輸入 1234567abcd 賦值 123 4567 a d