您好,登錄后才能下訂單哦!
實(shí)現(xiàn)多個(gè)賬號(hào)
#include <stdio.h>
#include <string.h>
int main(void) {
// 定義變量,用來表示用戶名和密碼
char name[32];
char password[16];
FILE *file; //定義了一個(gè)檔指針變量,變量名是file
char line[128];
char name_tmp[32];
char password_tmp[16];
char *ret;
//打開檔
file = fopen("users.txt", "r");
if (!file) { //等效于 file == NULL
printf("檔打開失敗");
return 1;
}
//輸入用戶名和密碼
while (1) {
// 輸入用戶名和密碼
printf("請(qǐng)輸入用戶名:");
scanf("%s", name);
printf("請(qǐng)輸入密碼:");
scanf("%s", password);
/*
if (strcmp(name, "admin") == 0 &&
strcmp(password, "123456") == 0) {
break;
} else {
printf("用戶名或密碼錯(cuò)誤!\n");
system("pause");
system("cls");
}
*/
//從檔中讀取賬號(hào),并進(jìn)行判斷!
while (1) {
//讀一行
ret = fgets(line, sizeof(line), file); //line: "admin 123456\n"
if (!ret) {
break;
}
sscanf(line, "%s %s", name_tmp, password_tmp);
if (!strcmp(name, name_tmp) && !strcmp(password, password_tmp)) {
break;
}
}
if (ret) { //用戶名和密碼匹配成功
break;
} else {
printf("用戶名或密碼錯(cuò)誤!\n");
system("pause");
system("cls");
fseek(file, 0, SEEK_SET); //把檔內(nèi)部的位置指針設(shè)置到檔頭
}
}
system("cls");
// 打印功能菜單
printf("---交換機(jī)后臺(tái)管理---\n");
printf("1. 創(chuàng)建賬號(hào)\n");
printf("2. IP管理\n");
printf("3. 退出\n");
printf("請(qǐng)選擇...");
return 0;
}
1.fopen檔的打開操作
函數(shù)原型
#include <stdio.h>
FILE fopen( const char fname, const char mode );
參數(shù)1:fname 表示文件名(可以含有路徑信息)
參數(shù)2:打開方式
返回值:FILE 檔指針,
如果打開失敗,就返回NULL(就是0)
mode 打開方式
"r" 以“讀”的方式打開一個(gè)文本檔(只能讀)
"r+" 與"r" 的區(qū)別在于,增加了“寫”
"rb" 以“讀”的方式打開一個(gè)二進(jìn)制檔(只能讀)
"rb+" 與"rb"的區(qū)別在于,增加了“寫”
"w" 以“寫”的方式創(chuàng)建一個(gè)文本檔,如果這個(gè)檔已經(jīng)存在,就會(huì)覆蓋原來的檔
"w+" 與"w"的區(qū)別在于,增加了“讀”
"wb" 以“寫“的方式創(chuàng)建一個(gè)二進(jìn)制檔
"wb+" 與"wb"的區(qū)別在于,增加了“讀”
"a" 以“尾部追加”的方式打開一個(gè)文本檔, (只能寫)
"a+" 以"a"的區(qū)別在于,增加了"讀"
"ab" 以“尾部追加”的方式打開一個(gè)二進(jìn)制檔, (只能寫)
"ab+" 與"ab"的區(qū)別在于,增加了“讀”
小結(jié):
打開方式,共1到3個(gè)字符。
第一個(gè)字符是 r、w或a
r 表示“讀”,用于打開已經(jīng)存在的檔
w 表示“創(chuàng)建”, 用于創(chuàng)建一個(gè)新檔,并能夠“寫”
a 表示“尾部追加”,并能夠"寫"
b, 只能寫在第二位,表示打開的是二進(jìn)制檔
+,只能寫在最后,表示增加一個(gè)讀或?qū)懙墓δ?/p>
實(shí)例
#include <stdio.h>
int main(void) {
FILE *file;
//file = fopen("users.txt", "r");
file = fopen("users1.txt", "r");
if (file != NULL) { //NULL就是0
printf("檔users.txt打開成功!\n");
} else {
printf("檔users.txt打開失敗!\n");
}
return 0;
}
清理緩沖區(qū),并釋放檔指針。
Demo
#include <stdio.h>
int main(void) {
FILE *file;
file = fopen("users.txt", "a");
fputs("\nxiaoxiao 123456", file);
fclose(file);
return 0;
}
特別注意:
對(duì)檔執(zhí)行寫操作以后,并不會(huì)馬上寫入檔,而只是寫入到了這個(gè)檔的輸出緩沖區(qū)中!
只有當(dāng)這個(gè)輸出緩沖區(qū)滿了,或者執(zhí)行了fflush,或者執(zhí)行了fclose函數(shù)以后,或者程序結(jié)束,
才會(huì)把輸出緩沖區(qū)中的內(nèi)容正真寫入檔!
函數(shù)原型:
#include <stdio.h>
int fgetc( FILE *stream );
返回值:成功時(shí),返回讀到的字符,返回的是int類型(實(shí)際值是字符)
失敗或讀到檔尾,返回EOF (就是-1)
作用:
從檔中讀取一個(gè)字符
實(shí)例:
#include <stdio.h>
int main(void) {
FILE *file;
char c;
file = fopen("users.txt", "r");
while ((c = fgetc(file)) != EOF) { //EOF就是 -1
printf("%c", c);
}
return 0;
}
函數(shù)原型:
#include <stdio.h>
int fputc( int ch, FILE *stream );
實(shí)例:
test.c
#include <stdio.h>
int main(void) {
FILE *file1;
FILE *file2;
char c;
file1 = fopen("test.c", "r");
file2 = fopen("test2.c", "w");
while ((c = fgetc(file1)) != EOF) { //EOF就是 -1
fputc(c, file2);
}
fclose(file1);
fclose(file2);
return 0;
}
復(fù)習(xí):
在項(xiàng)目4的“字符串輸入”中學(xué)習(xí)過。
函數(shù)原型:
#include <stdio.h>
char fgets( char str, int num, FILE *stream );
參數(shù):
num: 最多讀取num-1個(gè)字符,或者遇到檔結(jié)束符EOF為止(即“檔讀完了”)
返回值; 讀取失敗時(shí), 返回NULL,
讀取成功時(shí),返回str
實(shí)例:
#include <stdio.h>
int main(void) {
FILE *file1;
char tmp[64];
char c;
file1 = fopen("test.c", "r");
while (fgets(tmp, sizeof(tmp), file1) != NULL) {
printf("%s", tmp);
}
fclose(file1);
return 0;
}
函數(shù)原型:
#include <stdio.h>
int fputs( const char str, FILE stream );
實(shí)例
#include <stdio.h>
int main(void) {
FILE *file1;
FILE *file2;
char tmp[64];
char c;
file1 = fopen("test.c", "r");
file2 = fopen("test2.c", "w");
while (fgets(tmp, sizeof(tmp), file1) != NULL) {
fputs(tmp, file2);
}
fclose(file1);
fclose(file2);
return 0;
}
函數(shù)原型:
#include <stdio.h>
int fprintf( FILE stream, const char format, ... );
Demo:
#include <stdio.h>
int main(void) {
FILE *file1;
char name[32];
int age;
char c;
file1 = fopen("info.txt", "w");
while (1) {
printf("請(qǐng)輸入學(xué)員姓名:");
scanf("%s", name);
printf("請(qǐng)輸入%s的成績(jī): ", name);
scanf("%d", &age);
fprintf(file1, "姓名:%s\t\t年齡:%d\n", name, age);
printf("還需要繼續(xù)輸入嗎? Y/N\n");
//fflush(stdin);
while((c=getchar()) != '\n'); //直到讀到回車符為止!
scanf("%c", &c);
if (c == 'Y' || c == 'y') {
continue;
} else {
break;
}
}
fclose(file1);
return 0;
}
函數(shù)原型:
#include <stdio.h>
int fscanf( FILE stream, const char format, ... );
返回值:成功時(shí),返回實(shí)際讀取的數(shù)據(jù)個(gè)數(shù)
失敗時(shí),返回 EOF (-1)
匹配失敗時(shí),返回0
Demo
#include <stdio.h>
int main(void) {
FILE *file1;
char name[32];
int age;
int ret;
file1 = fopen("info.txt", "r");
while (1) {
ret = fscanf(file1, "姓名:%s 年齡:%d\n", &name, &age);
if (ret == EOF) {
break;
}
printf("%s,%d\n", name, age);
}
fclose(file1);
return 0;
}
#include <stdio.h>
int fwrite( const void buffer, //要寫入的數(shù)據(jù)的其實(shí)地址,也就是變量的地址
size_t size, //每“塊”數(shù)據(jù)的大小
size_t count, //寫入幾塊數(shù)據(jù)
FILE stream );
Demo
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *file1;
char name[32];
int age;
int ret;
file1 = fopen("info.txt", "wb");
printf("請(qǐng)輸入您的姓名: ");
gets(name);
printf("請(qǐng)輸入您的年齡: ");
scanf("%d", &age);
fwrite(name, sizeof(name), sizeof(char), file1);
fwrite(&age, 1, sizeof(int), file1);
fclose(file1);
return 0;
}
補(bǔ)充:
w和wb的區(qū)別
wb的demo
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *file1;
char info[] = "Hello\nWorld";
int age;
int ret;
file1 = fopen("test.txt", "wb");
fwrite(info, sizeof(char), strlen(info), file1);
fclose(file1);
return 0;
}
w的demo
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *file1;
char info[] = "Hello\nWorld"; // \n 保存位 \r\n
int age;
int ret;
file1 = fopen("test.txt", "w");
fwrite(info, strlen(info), sizeof(char), file1);
fclose(file1);
return 0;
}
小結(jié):
在windows平臺(tái)下,
當(dāng)使用w方式打開檔時(shí),
如果使用fwrite寫入數(shù)據(jù)時(shí),會(huì)把’\n’寫入為 ‘\r’’\n’
即把10保存為 13 10
因?yàn)椋趙indows平臺(tái)下,文本檔中的回車符\n,會(huì)保存為 \r\n
( \n的ASCII碼為10, \r的ASCII碼為13)
當(dāng)使用wb方式打開檔時(shí),
如果使用fwrite寫入數(shù)據(jù)時(shí),遇到’\n’仍只寫入為 ‘\n’
函數(shù)原型:
#include <stdio.h>
int fread( void buffer, size_t size, size_t num, FILE stream );
Demo
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *file1;
char name[32];
int age;
int ret;
file1 = fopen("student.txt", "rb");
fread(name, sizeof(name), sizeof(char), file1);
fread(&age, 1, sizeof(int), file1);
printf("%s, %d\n", name, age);
fclose(file1);
return 0;
}
demo
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *file1;
int data[] = {1,2,3,4,5};
int i;
file1 = fopen("test.txt", "w");
for (i=0; i<5; i++) {
putw(data[i], file1);
}
fclose(file1);
return 0;
}
函數(shù)原型:
int getw(FILE *fp)
返回值:成功時(shí)返回讀取到的值
失敗時(shí)返回-1。
Demo
#include <stdio.h>
int main(void) {
FILE *file;
int value;
file = fopen("test.data", "rb");
if (!file) {
printf("檔打開失敗!\n");
return 1;
}
while (1) {
value = getw(file);
if (value == -1 && feof(file)) {
break;
}
printf("%d ", value);
}
fclose(file);
return 0;
}
函數(shù)原型:
#include <stdio.h>
int feof( FILE *stream );
返回值:如果指定的程序,已經(jīng)到達(dá)檔末尾位置,就返回非零值(真)。
#include <stdio.h>
int main(void) {
FILE *file;
char c;
file = fopen("test.c", "r");
//while ((c = fgetc(file)) != EOF) { //EOF就是 -1
while (!feof(file)) {
c = fgetc(file);
printf("%c", c);
}
return 0;
}
#include <stdio.h>
int main(void) {
FILE *file;
char c;
int ret;
file = fopen("test.c", "r");
fputc('A', file);
if (ferror(file)) {
perror("檔file發(fā)生錯(cuò)誤");
}
return 0;
}
執(zhí)行結(jié)果:
把 “r” 改為 “r+” 就不會(huì)發(fā)生錯(cuò)誤了。
函數(shù)原型:
#include <stdio.h>
void clearerr( FILE *stream );
Demo
#include <stdio.h>
int main(void) {
FILE *file;
char c;
int ret;
file = fopen("test.c", "r");
fputc('A', file);
if (ferror(file)) {
perror("檔file發(fā)生錯(cuò)誤");
}
//如果不清除檔錯(cuò)誤,以后讀寫檔時(shí), 即使沒有發(fā)生錯(cuò)誤,ferror仍將返回非零值(認(rèn)為還有錯(cuò))
clearerr(file);
c = fgetc(file);
printf("c=%c\n", c);
if (ferror(file)) {
perror("檔file發(fā)生錯(cuò)誤");
}
return 0;
}
函數(shù)原型:
#include <stdio.h>
long ftell( FILE *stream );
Demo
#include <stdio.h>
int main(void) {
FILE *file;
char c;
int ret;
long offset;
file = fopen("test.c", "r");
offset = ftell(file);
printf("當(dāng)前位置是: %ld\n", offset);
fgetc(file);
offset = ftell(file);
printf("當(dāng)前位置是: %ld\n", offset);
fclose(file);
return 0;
}
注意:檔始終只能從當(dāng)前的位置向檔尾方向讀寫!
函數(shù)原型:
#include <stdio.h>
int fseek( FILE *stream, long offset, int origin );
參數(shù)2:
偏移量,可正可負(fù)。
<0 向檔頭方向偏移 <>
<0 向檔尾方向偏移 <>
參數(shù)3:
SEEK_SET 從檔的開始位置定位, 此時(shí)參數(shù)2必須大于0
SEEK_CUR 從檔的當(dāng)前位置定位
SEEK_END 從檔的結(jié)束位置定位, 此時(shí)參數(shù)2必須小與0
Demo
#include <stdio.h>
int main(void) {
FILE *file;
char c;
char buff[256];
int i;
file = fopen("test.c", "r");
//讀取檔最后10個(gè)字符
fseek(file, -10, SEEK_END);
while (!feof(file)) {
c = fgetc(file);
printf("%c", c);
}
//讀取檔的第一行
fseek(file, 0, SEEK_SET);
fgets(buff, sizeof(buff), file);
printf("\n第一行:%s\n", buff);
//讀取當(dāng)前位置的前10個(gè)字符
fseek(file, -10, SEEK_CUR);
printf("\n這10個(gè)字符是:");
for (i=0; i<10; i++) {
c = fgetc(file);
printf("%c", c);
}
close(file);
return 0;
}
把檔的位置指針定位到開始位置。
rewind(file)
等效于:
fseek(file, 0, SEEK_SET)
1.練習(xí)1
獨(dú)立實(shí)現(xiàn)項(xiàng)目7.
編寫一個(gè)程序,統(tǒng)計(jì)該程序本身一共有多少個(gè)字符,有多少行,并列印輸出
#include <stdio.h>
// 統(tǒng)計(jì)這個(gè)程序本身,有多少個(gè)字符,有多少行代碼
int main(void) {
FILE *file ;
char c;
int count_char = 0; //字符總數(shù)
int count_line = 0; //行數(shù)
file = fopen("test.c", "r");
if (!file ) {
printf("檔打開失敗!\n");
return 1;
}
while ((c=fgetc(file)) != EOF) {
count_char++;
if (c == '\n') {
count_line++;
}
}
count_line++;
printf("一共有 %d 個(gè)字符\n", count_char);
printf("一共有 %d 行代碼\n", count_line);
return 0;
}
3.已有一個(gè)檔,用來保存通訊錄,假設(shè)已有內(nèi)容如下:
note.txt
張三豐 Tel:13507318888 Addr:武當(dāng)
劉備 Tel:13802289999 Addr:成都
馬云 Tel:13904256666 Addr:杭州
馬化騰 Tel:13107551111 Addr:深圳
編寫一個(gè)程序,執(zhí)行效果如下:
參考:
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *file;
char name_search[64];
char line[256];
char name[64];
char tel[32];
char addr[32];
int found = 0;
file = fopen("note.txt", "r");
if (!file) {
printf("檔打開失敗\n");
return 1;
}
printf("請(qǐng)輸入要查詢的用戶名:");
scanf("%s", name_search);
while (!feof(file)) {
fscanf(file, "%s Tel:%s Addr:%s\n", name, tel, addr);
if (!strcmp(name, name_search)) {
printf("%s的電話是:%s\n", name_search, tel);
found = 1;
break;
}
}
if (found == 0) {
printf("沒有%s的信息\n", name_search);
}
return 0;
}
需要特別注意fscanf的格式字符串中最后的\n,否者只能匹配第一行!
補(bǔ)充說明:
對(duì)于如下文本:
張三豐 Tel:13507318888 Addr:武當(dāng)
劉備 Tel:13802289999 Addr:成都
馬云 Tel:13904256666 Addr:杭州
馬化騰 Tel:13107551111 Addr:深圳
可以循環(huán)使用如下代碼讀?。?fscanf(file, "%s Tel:%s Addr:%s\n", name, tel, addr);
但是不加回車符,使用如下語句也能讀取:
fscanf(file, "%s Tel:%s Addr:%s", name, tel, addr);
這是是因?yàn)椋?使用fscanf(file,"%s Tel:%s Addr:%s",name_tmp,tel,addr),匹配到第一行的第2個(gè)%s時(shí),剛好把第一個(gè)行中,除了最后的回車符以外,匹配完。此時(shí)第一行還剩下一個(gè)回車符。接著進(jìn)入第2輪循環(huán),又開始使用scanf匹配,但是注意,是從檔的上一次匹配結(jié)束的位置繼續(xù)匹配,也就是第一行行尾的回車符為止,在這個(gè)格式字符串中,第一個(gè)是%s,所以會(huì)跳過第一行行尾的回車符,從而匹配成功。
如果檔的內(nèi)容是這樣的格式,就必須在格式字符串的最后加上\n了
姓名:張三豐 電話:13243879188
姓名:張四風(fēng) 電話:13243879199
總結(jié):需要特別注意fscanf的格式字符串中最后的\n的作用。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。