c語言中比較特殊的輸入函數(shù)舉例詳解
一.getchar()函數(shù)
getchar()是C語言中的一個標準庫函數(shù),用于從標準輸入(通常是鍵盤)讀取一個字符。它是stdio.h庫的一部分,常用于簡單的字符輸入操作。
1.基本功能
getchar()讀取標準輸入中的下一個字符,并將其作為一個int類型的值返回。盡管返回值是int類型,但它實際上是一個字符的ASCII值。
2.使用方法
int ch = getchar();
在這段代碼中,
getchar()從標準輸入中讀取一個字符,并將其返回的字符值存儲在ch變量中。
示例:
(1).讀取單個字符
#include <stdio.h>
int main() {
int ch;
printf("請輸入一個字符: ");
ch = getchar();
printf("你輸入的字符是: %c\n", ch);
return 0;
}
解釋:
- 程序等待用戶輸入一個字符。用戶輸入的字符被
getchar()讀取并存儲在ch中。 printf函數(shù)隨后輸出用戶輸入的字符。
(2).讀取多個字符(直到遇到換行符)
#include <stdio.h>
int main() {
int ch;
printf("請輸入一行文字,按回車結(jié)束: ");
while ((ch = getchar()) != '\n' && ch != EOF) {
printf("讀取字符: %c\n", ch);
}
printf("輸入結(jié)束。\n");
return 0;
}
解釋:
- 程序使用
while循環(huán)來讀取字符,直到遇到換行符('\n')或文件結(jié)束符(EOF)。 - 每次讀取的字符都會被輸出。
(3).處理輸入中的空白字符
#include <stdio.h>
int main() {
int ch;
printf("請輸入字符,輸入結(jié)束請按 Ctrl+D (Linux) 或 Ctrl+Z (Windows):\n");
while ((ch = getchar()) != EOF) {
if (ch == ' ' || ch == '\n' || ch == '\t') {
printf("[空白字符]\n");
} else {
printf("讀取字符: %c\n", ch);
}
}
printf("輸入結(jié)束。\n");
return 0;
}
解釋:
- 這個程序讀取用戶輸入的每個字符,并檢查它是否是空白字符(空格、換行符、制表符)。
- 如果是空白字符,程序會輸出
[空白字符],否則輸出字符本身。 - 當用戶按下
Ctrl+D或Ctrl+Z時,輸入結(jié)束。
3.返回值
讀取的字符: 如果讀取成功,
getchar()返回讀取的字符的ASCII值。例如,如果用戶輸入字符'A',getchar()將返回值65(即'A'的ASCII碼)。EOF (End of File): 如果在讀取時遇到文件結(jié)束符(通常是在控制臺輸入時按下
Ctrl+D或Ctrl+Z),getchar()將返回常量EOF,其值通常為-1。EOF用于指示輸入的結(jié)束或錯誤情況。
4.應(yīng)用場景
簡單字符輸入:
getchar()通常用于簡單的字符輸入操作,例如讀取單個字符或控制臺中的用戶輸入。處理空白字符: 當你需要明確處理空白字符(例如空格、制表符或換行符)時,
getchar()特別有用。相比于scanf,getchar()不會跳過空白字符,因此你可以逐字符地處理輸入。控制輸入流:
getchar()在處理輸入流時非常靈活,可以用于跳過不需要的字符。例如,在多行輸入或復(fù)雜輸入格式的情況下,它可以幫助你控制和過濾輸入內(nèi)容。
5.注意事項
返回類型為
int: 盡管getchar()用于讀取單個字符,但它的返回類型是int而不是char。這樣設(shè)計是為了能夠返回EOF來表示文件結(jié)束或錯誤。為了避免潛在的錯誤,通常應(yīng)該使用int類型來存儲getchar()的返回值。緩沖區(qū)問題: 在控制臺輸入時,用戶輸入的內(nèi)容通常會先進入緩沖區(qū)。當按下回車鍵時,緩沖區(qū)中的內(nèi)容才會被
getchar()逐個讀取。因此,getchar()不會在每個字符輸入時立即返回,而是等待用戶按下回車鍵。錯誤處理: 當使用
getchar()時,程序應(yīng)該考慮EOF的可能性,尤其是在文件輸入或批處理輸入的情況下。忽略這一點可能會導(dǎo)致程序未正確處理輸入結(jié)束的情況。
二.fgets()函數(shù)
fgets是C語言中用于從文件流中讀取一行字符串的標準庫函數(shù)。它提供了一種安全、方便的方法來讀取輸入,避免了諸如緩沖區(qū)溢出等常見問題。fgets通常用于讀取用戶輸入、從文件中讀取數(shù)據(jù)等場景。
1.函數(shù)原型
char *fgets(char *str, int n, FILE *stream);
str: 指向字符數(shù)組的指針,fgets會將讀取到的字符串存儲在該數(shù)組中。n: 要讀取的最大字符數(shù),包括結(jié)尾的空字符\0。也就是說,fgets最多讀取n-1個字符。stream: 輸入流指針,指明從哪個流中讀取數(shù)據(jù)。常見的流有標準輸入流stdin,文件流等。
返回值
- 成功: 返回指向讀取字符串的指針,即參數(shù)
str。 - 失敗或到達文件末尾: 返回
NULL。
2.工作原理
fgets函數(shù)從指定的輸入流stream中讀取字符,并將其存儲到str指向的字符數(shù)組中,直到發(fā)生以下任一情況:讀取了
(n - 1)個字符: 為了保證字符串以\0結(jié)尾,fgets最多讀取n - 1個字符。遇到換行符
\n:fgets會讀取換行符,并將其存儲在str中。到達文件末尾
EOF: 如果在讀取過程中遇到文件末尾,讀取操作結(jié)束。讀取完成后,
fgets會在讀取的字符串末尾自動添加一個空字符\0,以表示字符串的結(jié)束。
3.使用示例
(1).從標準輸入讀取一行字符串
#include <stdio.h>
int main() {
char buffer[100];
printf("請輸入一行文本:");
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
printf("您輸入的是:%s", buffer);
} else {
printf("讀取輸入時發(fā)生錯誤。\n");
}
return 0;
}
解釋:
fgets(buffer, sizeof(buffer), stdin)從標準輸入讀取最多99個字符(保留1個字符給\0),并存儲在buffer中。- 如果讀取成功,程序會輸出用戶輸入的內(nèi)容。
注意: 由于 fgets 會將換行符 \n 一并讀取并存儲,如果不想要這個換行符,需要手動去除。
(2).從文件中讀取內(nèi)容
#include <stdio.h>
int main() {
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {
perror("無法打開文件");
return 1;
}
char line[256];
while (fgets(line, sizeof(line), fp) != NULL) {
printf("%s", line);
}
fclose(fp);
return 0;
}
解釋:
- 打開名為
example.txt的文件,讀取其中的內(nèi)容并逐行打印到標準輸出。 fgets在每次循環(huán)中讀取一行內(nèi)容,直到文件結(jié)束。
4.處理換行符
正如前面提到的,fgets 會將輸入中的換行符 \n 一并讀取并存儲在目標字符串中。如果在處理時不需要這個換行符,可以使用以下方法去除:
方法1:手動檢查并替換
size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n') {
buffer[len - 1] = '\0';
}
解釋:
- 首先獲取字符串的長度
len。 - 如果最后一個字符是
\n,將其替換為\0。
方法2:使用 strcspn 函數(shù)
buffer[strcspn(buffer, "\n")] = '\0';
解釋:
strcspn函數(shù)返回buffer中第一個匹配\n的位置索引,然后將該位置的字符替換為\0。
5.與其他輸入函數(shù)的比較
(1). fgets vs gets
gets: 從標準輸入讀取一行,直到遇到換行符或文件結(jié)束符。不安全,因為無法指定讀取的最大長度,容易導(dǎo)致緩沖區(qū)溢出。fgets: 可以指定最大讀取長度,安全性更高。建議始終使用fgets代替gets。
(2). fgets vs scanf
scanf: 按照指定的格式從輸入中讀取數(shù)據(jù),默認會忽略空白字符,讀取字符串時會在遇到空白字符時停止。fgets: 讀取整行輸入,包括空白字符和換行符,更適合讀取包含空格的字符串
示例:
char str1[100], str2[100];
// 使用 scanf
scanf("%s", str1);
// 輸入:Hello World
// str1 的值為:"Hello"
// 使用 fgets
fgets(str2, sizeof(str2), stdin);
// 輸入:Hello World
// str2 的值為:"Hello World\n"
(3). fgets vs fgetc
fgetc: 每次從指定流中讀取一個字符,適合逐字符處理輸入。fgets: 一次讀取一行或指定長度的字符串,效率更高。
6、常見錯誤和注意事項
(1). 忘記檢查返回值
在使用
fgets時,應(yīng)該始終檢查其返回值,以確保讀取成功。
錯誤示例:
fgets(buffer, sizeof(buffer), stdin); // 未檢查返回值,可能導(dǎo)致程序處理空指針
正確示例:
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
// 處理讀取的數(shù)據(jù)
} else {
// 錯誤處理
}
(2). 未正確處理換行符
如前所述,
fgets會保留輸入中的換行符,如果不想要這個換行符,需要手動去除。
(3). 緩沖區(qū)大小不足
確保提供給
fgets的緩沖區(qū)足夠大,以容納預(yù)期的輸入數(shù)據(jù)和結(jié)尾的空字符。
錯誤示例:
char buffer[10]; fgets(buffer, 100, stdin); // 錯誤:緩沖區(qū)只有10個字節(jié),卻試圖讀取100個字符
正確示例:
char buffer[100]; fgets(buffer, sizeof(buffer), stdin); // 正確:緩沖區(qū)大小與讀取長度匹配
(4). 多次讀取時的緩沖區(qū)殘留
在某些情況下,輸入流中可能殘留未讀取的字符,需要在下一次讀取前清空緩沖區(qū)。
char buffer1[50], buffer2[50];
printf("輸入第一行:");
fgets(buffer1, sizeof(buffer1), stdin);
printf("輸入第二行:");
fgets(buffer2, sizeof(buffer2), stdin);
如果在第一次輸入時輸入的字符超過了 buffer1 的大小,剩余的字符會留在輸入緩沖區(qū)中,影響第二次讀取。為避免這種情況,可以在每次讀取后清空緩沖區(qū)。
清空緩沖區(qū)的方法:
int c; while ((c = getchar()) != '\n' && c != EOF);
7.綜合示例
示例:讀取用戶輸入并處理
#include <stdio.h>
#include <string.h>
int main() {
char name[50];
int age;
char input[100];
// 讀取姓名
printf("請輸入您的姓名:");
if (fgets(name, sizeof(name), stdin) != NULL) {
// 去除換行符
name[strcspn(name, "\n")] = '\0';
} else {
printf("讀取姓名失敗。\n");
return 1;
}
// 讀取年齡
printf("請輸入您的年齡:");
if (fgets(input, sizeof(input), stdin) != NULL) {
// 將字符串轉(zhuǎn)換為整數(shù)
age = atoi(input);
} else {
printf("讀取年齡失敗。\n");
return 1;
}
printf("姓名:%s,年齡:%d\n", name, age);
return 0;
}
解釋:
- 首先使用
fgets讀取用戶的姓名,并去除結(jié)尾的換行符。 - 然后再次使用
fgets讀取用戶的年齡輸入,并使用atoi將其轉(zhuǎn)換為整數(shù)。 - 最后輸出用戶輸入的信息。
三.sscanf函數(shù)
sscanf是C語言中用于從字符串中讀取并解析數(shù)據(jù)的標準庫函數(shù)。它的作用類似于scanf,但sscanf從字符串中讀取數(shù)據(jù),而scanf是從標準輸入中讀取數(shù)據(jù)。sscanf非常適合從已知格式的字符串中提取數(shù)值、字符等數(shù)據(jù)。
1.函數(shù)原型
int sscanf(const char *str, const char *format, ...);
str: 要解析的源字符串。sscanf會從這個字符串中讀取數(shù)據(jù)。format: 格式字符串,指定了要解析的數(shù)據(jù)格式。它的語法和scanf的格式字符串相同,包括各種格式說明符(如%d,%s,%f等)。...: 可變參數(shù)列表,提供用于存儲從字符串中讀取的數(shù)據(jù)的指針。
返回值
- 成功: 返回成功讀取并匹配的項數(shù)。
- 失敗: 返回
EOF,如果在解析過程中遇到錯誤或在嘗試讀取時到達字符串末尾
2.工作原理
sscanf函數(shù)根據(jù)format字符串中的格式說明符,從源字符串str中逐一讀取和解析數(shù)據(jù)。每個格式說明符都對應(yīng)于一個傳入的變量地址,sscanf將解析后的數(shù)據(jù)存儲在這些變量中。格式說明符示例
%d: 讀取一個整數(shù)。%f: 讀取一個浮點數(shù)。%s: 讀取一個字符串,遇到空白字符(如空格、換行)時停止。%c: 讀取單個字符。
示例:
(1).從字符串中解析數(shù)據(jù)
#include <stdio.h>
int main() {
const char *str = "100 3.14 hello";
int num;
float pi;
char word[20];
int count = sscanf(str, "%d %f %s", &num, &pi, word);
printf("讀取到 %d 項數(shù)據(jù):\n", count);
printf("整數(shù): %d\n", num);
printf("浮點數(shù): %.2f\n", pi);
printf("字符串: %s\n", word);
return 0;
}
輸出:
讀取到 3 項數(shù)據(jù):
整數(shù): 100
浮點數(shù): 3.14
字符串: hello
解釋:
sscanf解析字符串"100 3.14 hello",并將數(shù)據(jù)分別存儲在num,pi,word中。- 返回值
count表示成功讀取了3項數(shù)據(jù)。
3.常見用法和注意事項
(1). 解析特定格式的字符串
sscanf特別適用于解析具有固定格式的字符串,比如日期、時間、IP地址等。
示例:解析日期
#include <stdio.h>
int main() {
const char *date = "2024-08-17";
int year, month, day;
sscanf(date, "%d-%d-%d", &year, &month, &day);
printf("年: %d, 月: %d, 日: %d\n", year, month, day);
return 0;
}
輸出:
年: 2024, 月: 8, 日: 17
解釋:
- 解析字符串
"2024-08-17"中的年份、月份和日期,并分別存儲在year,month,day中。
(2). 處理多余的輸入
如果源字符串中的內(nèi)容多于格式說明符指定的內(nèi)容,
sscanf只會處理指定的部分,忽略其余部分。
示例:部分解析字符串
#include <stdio.h>
int main() {
const char *str = "42 3.14 some extra text";
int num;
float pi;
int count = sscanf(str, "%d %f", &num, &pi);
printf("讀取到 %d 項數(shù)據(jù):\n", count);
printf("整數(shù): %d\n", num);
printf("浮點數(shù): %.2f\n", pi);
return 0;
}
輸出:
讀取到 2 項數(shù)據(jù):
整數(shù): 42
浮點數(shù): 3.14
解釋:
sscanf只解析了前兩個數(shù)據(jù)項(整數(shù)和浮點數(shù)),忽略了字符串末尾的額外內(nèi)容。
(3). 不匹配的格式
如果字符串中的內(nèi)容與格式說明符不匹配,
sscanf會停止解析,并返回已成功讀取的項數(shù)。
示例:格式不匹配
#include <stdio.h>
int main() {
const char *str = "hello 3.14";
int num;
float pi;
int count = sscanf(str, "%d %f", &num, &pi);
printf("讀取到 %d 項數(shù)據(jù):\n", count);
return 0;
}
輸出:
讀取到 0 項數(shù)據(jù):
(4). 忽略特定數(shù)據(jù)
sscanf還可以使用*來忽略某些輸入數(shù)據(jù),不存儲在任何變量中。
示例:忽略數(shù)據(jù)
#include <stdio.h>
int main() {
const char *str = "42 skip this 3.14";
int num;
float pi;
sscanf(str, "%d %*s %f", &num, &pi);
printf("整數(shù): %d\n", num);
printf("浮點數(shù): %.2f\n", pi);
return 0;
}
輸出:
整數(shù): 42
浮點數(shù): 3.14
解釋:
sscanf使用%*s忽略了"skip this"字符串部分,只提取了整數(shù)和浮點數(shù)。
(5). 返回值處理
sscanf的返回值用于檢查是否成功解析了預(yù)期的項數(shù)。在實際編程中,應(yīng)該根據(jù)返回值來驗證解析操作的成功與否。
示例:檢查返回值
#include <stdio.h>
int main() {
const char *str = "100 3.14";
int num;
float pi;
int result = sscanf(str, "%d %f", &num, &pi);
if (result == 2) {
printf("成功讀取兩個數(shù)值:%d 和 %.2f\n", num, pi);
} else {
printf("解析失敗,已成功讀取 %d 項數(shù)據(jù)。\n", result);
}
return 0;
}
輸出:
成功讀取兩個數(shù)值:100 和 3.14
解釋:
- 如果
sscanf成功解析了兩個值,程序輸出成功消息。否則,輸出失敗消息。
4.常見錯誤和陷阱
(1). 未匹配到預(yù)期的數(shù)據(jù)
如果輸入字符串的格式與格式說明符不匹配,
sscanf會停止解析,返回已經(jīng)成功解析的項數(shù)。確保格式字符串與輸入字符串的格式一致非常重要。
(2). 忘記檢查返回值
忽略
sscanf的返回值可能導(dǎo)致錯誤的程序行為。檢查返回值是驗證解析操作成功與否的關(guān)鍵步驟。
(3). 緩沖區(qū)溢出
當讀取字符串數(shù)據(jù)(如使用
%s)時,確保目標緩沖區(qū)有足夠的空間以避免溢出。使用長度限制格式符號(如%99s)可以防止緩沖區(qū)溢出。
(4). 處理多余輸入
如果
sscanf只讀取了部分輸入數(shù)據(jù),而程序的邏輯依賴于完整的數(shù)據(jù)解析,可能會導(dǎo)致問題。合理設(shè)計格式說明符和字符串輸入非常重要。
5.sscanf 與其他輸入函數(shù)的比較
(1). sscanf vs scanf
scanf: 從標準輸入中讀取數(shù)據(jù),適用于直接的用戶輸入操作。sscanf: 從字符串中讀取數(shù)據(jù),適用于解析已經(jīng)存在的字符串內(nèi)容。
(2). sscanf vs fscanf
fscanf: 從文件流中讀取數(shù)據(jù),適用于從文件中解析數(shù)據(jù)。sscanf: 從字符串中讀取數(shù)據(jù),適用于解析內(nèi)存中的字符串。
(3). sscanf vs strtok
strtok: 用于分割字符串,可以按指定的分隔符逐一提取子字符串。sscanf: 直接解析字符串中的數(shù)據(jù),并將其轉(zhuǎn)換為相應(yīng)的數(shù)據(jù)類型。
6.綜合示例
示例:解析復(fù)雜字符串
#include <stdio.h>
int main() {
const char *str = "Name: John Doe, Age: 30, Score: 85.5";
char name[50];
int age;
float score;
int count = sscanf(str, "Name: %[^,], Age: %d, Score: %f", name, &age, &score);
if (count == 3) {
printf("姓名: %s\n", name);
printf("年齡: %d\n", age);
printf("分數(shù): %.1f\n", score);
} else {
printf("解析字符串失敗。\n");
}
return 0;
}
輸出:
姓名: John Doe
年齡: 30
分數(shù): 85.5
解釋:
- 使用
sscanf從格式化字符串中提取姓名、年齡和分數(shù)。%[^,]格式說明符用于讀取直到遇到逗號,的所有字符,這樣可以處理包含空格的姓名。
四.fscanf()函數(shù)
fscanf是C語言中用于從文件中讀取并解析數(shù)據(jù)的標準庫函數(shù)。它的作用類似于scanf,但fscanf從文件流中讀取數(shù)據(jù),而scanf是從標準輸入中讀取數(shù)據(jù)。fscanf適合從文件中逐行或逐項讀取并解析數(shù)據(jù)。
1.函數(shù)原型
int fscanf(FILE *stream, const char *format, ...);
參數(shù)說明
stream: 文件指針,指向要讀取的文件流(通常是通過fopen打開的文件)。format: 格式字符串,指定了要解析的數(shù)據(jù)格式。它的語法和scanf的格式字符串相同,包括各種格式說明符(如%d,%s,%f等)。...: 可變參數(shù)列表,提供用于存儲從文件中讀取的數(shù)據(jù)的指針。
返回值
- 成功: 返回成功讀取并匹配的項數(shù)。
- 失敗: 如果遇到文件結(jié)束符
EOF,則返回EOF。如果遇到錯誤,返回負數(shù)。
2.工作原理
fscanf 函數(shù)根據(jù) format 字符串中的格式說明符,從文件流 stream 中逐一讀取和解析數(shù)據(jù)。每個格式說明符都對應(yīng)于一個傳入的變量地址,fscanf 將解析后的數(shù)據(jù)存儲在這些變量中。
格式說明符示例
%d: 讀取一個整數(shù)。%f: 讀取一個浮點數(shù)。%s: 讀取一個字符串,遇到空白字符(如空格、換行)時停止。%c: 讀取單個字符。
示例:從文件中解析數(shù)據(jù)
假設(shè)有一個文本文件 data.txt,內(nèi)容如下:
42 3.14 hello
#include <stdio.h>
int main() {
FILE *file = fopen("data.txt", "r"); // 打開文件進行讀取
if (file == NULL) {
perror("無法打開文件");
return 1;
}
int num;
float pi;
char word[20];
int count = fscanf(file, "%d %f %s", &num, &pi, word);
printf("讀取到 %d 項數(shù)據(jù):\n", count);
printf("整數(shù): %d\n", num);
printf("浮點數(shù): %.2f\n", pi);
printf("字符串: %s\n", word);
fclose(file); // 關(guān)閉文件
return 0;
}
輸出:
讀取到 3 項數(shù)據(jù):
整數(shù): 42
浮點數(shù): 3.14
字符串: hello
解釋:
fscanf從文件data.txt中解析數(shù)據(jù),并將數(shù)據(jù)分別存儲在num,pi,word中。- 返回值
count表示成功讀取了3項數(shù)據(jù)。
3.常用用法和注意事項
(1). 讀取一行數(shù)據(jù)
fscanf通常按格式說明符讀取數(shù)據(jù),直到匹配結(jié)束,或者遇到文件結(jié)束符EOF。它不會自動處理行結(jié)束符,因此如果要按行讀取數(shù)據(jù),可以結(jié)合fgets和sscanf使用。
示例:逐行讀取數(shù)據(jù)
假設(shè)文件 data.txt 內(nèi)容如下:
42 3.14 hello 43 2.71 world
#include <stdio.h>
int main() {
FILE *file = fopen("data.txt", "r");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
int num;
float pi;
char word[20];
while (fscanf(file, "%d %f %s", &num, &pi, word) != EOF) {
printf("整數(shù): %d, 浮點數(shù): %.2f, 字符串: %s\n", num, pi, word);
}
fclose(file);
return 0;
}
輸出:
整數(shù): 42, 浮點數(shù): 3.14, 字符串: hello
整數(shù): 43, 浮點數(shù): 2.71, 字符串: world
(2). 文件指針位置
fscanf讀取數(shù)據(jù)后,文件指針會移動到讀取結(jié)束的位置。下一次調(diào)用fscanf會從當前文件指針位置繼續(xù)讀取。
(3). 遇到EOF
當
fscanf遇到文件結(jié)束符EOF時,它會返回EOF,通常是-1。這可以用來判斷是否已經(jīng)讀取到文件末尾。
(4). 忽略特定數(shù)據(jù)
類似于
sscanf,fscanf也可以使用*來忽略某些輸入數(shù)據(jù),而不存儲在任何變量中。
示例:忽略數(shù)據(jù)
#include <stdio.h>
int main() {
FILE *file = fopen("data.txt", "r");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
int num;
float pi;
while (fscanf(file, "%d %*s %f", &num, &pi) != EOF) {
printf("整數(shù): %d, 浮點數(shù): %.2f\n", num, pi);
}
fclose(file);
return 0;
}
解釋:
fscanf使用%*s忽略了字符串部分,只提取了整數(shù)和浮點數(shù)。
(5). 返回值處理
與
sscanf類似,fscanf的返回值表示成功讀取并解析的數(shù)據(jù)項數(shù)。在實際編程中,應(yīng)該根據(jù)返回值來驗證解析操作的成功與否。
示例:檢查返回值
#include <stdio.h>
int main() {
FILE *file = fopen("data.txt", "r");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
int num;
float pi;
while (fscanf(file, "%d %f", &num, &pi) == 2) { // 期望成功讀取2項數(shù)據(jù)
printf("整數(shù): %d, 浮點數(shù): %.2f\n", num, pi);
}
fclose(file);
return 0;
}
解釋:
- 只有在成功解析了兩個值時才輸出結(jié)果。如果
fscanf未能成功讀取兩個值,將停止讀取。
(6). 處理多余輸入
如果文件中的內(nèi)容多于格式說明符指定的內(nèi)容,
fscanf只會處理指定的部分,忽略其余部分。
4.常見錯誤和陷阱
(1). 格式不匹配
如果文件中的內(nèi)容與格式說明符不匹配,
fscanf會停止解析,并返回已成功讀取的項數(shù)。確保格式字符串與文件內(nèi)容格式一致非常重要。
(2). 忘記檢查返回值
忽略
fscanf的返回值可能導(dǎo)致錯誤的程序行為。檢查返回值是驗證解析操作成功與否的關(guān)鍵步驟。
(3). 文件結(jié)束符
fscanf在讀取到文件結(jié)束符EOF時會返回EOF,這與常規(guī)的返回值檢查不同,處理文件結(jié)束符時需要特別注意。
5.fscanf 與其他輸入函數(shù)的比較
(1). fscanf vs scanf
scanf: 從標準輸入中讀取數(shù)據(jù),適用于直接的用戶輸入操作。fscanf: 從文件流中讀取數(shù)據(jù),適用于從文件中解析數(shù)據(jù)。
(2). fscanf vs sscanf
sscanf: 從字符串中讀取數(shù)據(jù),適用于解析內(nèi)存中的字符串。fscanf: 從文件流中讀取數(shù)據(jù),適用于從文件中解析數(shù)據(jù)。
(3). fscanf vs fgets
fgets: 從文件中讀取一整行字符串,適用于逐行讀取文件內(nèi)容,通常結(jié)合sscanf使用以進一步解析數(shù)據(jù)。fscanf: 按照格式說明符從文件中讀取數(shù)據(jù),適用于逐項解析數(shù)據(jù)。
6.綜合示例
示例:從文件中讀取并解析數(shù)據(jù)
假設(shè)有一個文本文件 students.txt,內(nèi)容如下:
John 20 85.5 Alice 22 90.0 Bob 21 78.5
#include <stdio.h>
int main() {
FILE *file = fopen("students.txt", "r");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
char name[50];
int age;
float score;
while (fscanf(file, "%s %d %f", name, &age, &score) == 3) {
printf("姓名: %s, 年齡: %d, 分數(shù): %.1f\n", name, age, score);
}
fclose(file);
return 0;
}
輸出:
姓名: John, 年齡: 20, 分數(shù): 85.5
姓名: Alice, 年齡: 22, 分數(shù): 90.0
姓名: Bob, 年齡: 21, 分數(shù): 78.5
解釋:
fscanf從文件students.txt中解析每一行數(shù)據(jù),并輸出到屏幕上。它通過格式說明符%s %d %f解析每行中的姓名、年齡和分數(shù)。
完!
到此這篇關(guān)于c語言中比較特殊的輸入函數(shù)的文章就介紹到這了,更多相關(guān)c語言特殊輸入函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入解讀C++ 內(nèi)聯(lián)函數(shù)inline|nullptr
內(nèi)聯(lián)函數(shù):用** inline 修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時C++編譯器會在調(diào)用的地方展開內(nèi)聯(lián)函數(shù)**,這樣調(diào)用內(nèi)聯(lián)函數(shù)就需要創(chuàng)建棧楨,就提高效率了,這篇文章給大家介紹C++ 內(nèi)聯(lián)函數(shù)inline|nullptr的相關(guān)知識,感興趣的朋友跟隨小編一起看看吧2024-07-07
C++11右值引用和轉(zhuǎn)發(fā)型引用教程詳解
這篇文章主要介紹了C++11右值引用和轉(zhuǎn)發(fā)型引用教程詳解,需要的朋友可以參考下2018-03-03
C++通過共享內(nèi)存ShellCode實現(xiàn)跨進程傳輸
在計算機安全領(lǐng)域,ShellCode是一段用于利用系統(tǒng)漏洞或執(zhí)行特定任務(wù)的機器碼,本文主要為大家介紹了C++如何通過共享內(nèi)存ShellCode實現(xiàn)跨進程傳輸,需要的可以參考下2023-12-12

