C/C++程序從文本文件中讀取(保存)數據


:本文僅供初學者參閱,解惑

 

  • 在C程序中:

與程序代碼外的數據(文件)打交道,我們使用到流(stream)這個概念,實現進程的虛擬內存與文件之間的數據交換。

——文件流:C標准庫提供了FILE(之所以命名為FILE,因為linux將所有機制都視為文件) ,FILE對象是一個包含了管理流所需的所有信息的結構,包括緩沖區信息、各種標記(如文件結束標記和錯誤標記)以及用於實際I/O的文 件描述符等。

——輸入流,輸入流:數據從文件傳送到內存的叫輸入流,數據從內存傳送到文件的叫輸出流。

——打開文件:FILE對象通過調用fopen函數創建的。如: FILE *fp, fp=fopen("filename","r"), 表示以只讀的方式建立與filename相關的文件流;filename為當前目錄下的相對路徑名,r代表可讀(打開文件的模式)。 

 

一:讀取

1:對一些有規范格式文件的讀取,可使用標准庫stdio.h下的fscanf函數,

函數原型為:int fscanf(FILE * stream, const char * format, [argument...])

如讀取文件data.txt(數據格式相對規范)

代碼實現讀取:

//test.c
//文件讀取
  #include<stdio.h>
  
  int main()
  {
    //1:創建文件流,文件指針名=fopen(文件名,使用文件方式)打開失敗則返回NULL;
    FILE *fp=fopen("./data.txt","r"); //以data.txt文件為例

    //2:檢測文件是否打開成功;
    if(!fp){
       printf("打開失敗!\n");
       return -1; //返回異常
    }
    //3:
    int num; //用來儲存一個整型數據
    char name[10], place[10]; //用來儲存兩個字符串數據

    //抽象理解:
    //理解文件位置含義:其表示已打開文件當前可讀寫字符的位置,其表示為一個到文件頭的整數;
    //fscanf在讀取數據時可以這樣理解:文件被打開后,它就成了一個無序字節流(水流),其會通過一個管道,流向被讀取的一端;
    //了解fscanf后知道,其遇到空格字符(空格,制表符),換行符,就會停止,這里的停止我們可以理解為:
    //停下來為文件中兩個不相關的數據塊做一個分隔的操作,剛好適應了我們一般將空字符(包括換行符)作為兩個數據之間的分隔的行為;
    //我們只需理解管道的兩端
    //流進管道的一端的位置,就是文件的位置,表示已被讀到的位置。
    //流出管道一端,就是進程用來讀取數據的一端,其可以對管道中已經做區分的數據進行讀取。
   
   //4:讀取:
    fscanf(fp,"%d%s%s",&num, name,place); //fscanf對流的格式化讀取。
    //注1:fscanf(fp,"%da%s%s",&num,name,place); 可以實現對數據:1a小剛 河南;的准確讀取,表示兩個數據之間以a為界。
    //注2:因為流是指針的性質,所以函數是將各數據塊的首地址交給對應參數,所以num需進行&取地址操作,
    //注3:因為name,place本身已表達地址,所以不用改變;

    fscanf(fp,"\n");
    //\n為控制字符,此時文件的位置到了第二行的開始;

    //接着進行操作:fscanf(fp,"%d%s%s",&num, name,place);就可以繼續讀取第二行
    //所以我們常常只需利用一個while語句就可以將整個文件讀取到一個數據結構(進程)中
    /*
    while(!feof(fp)) //feof()檢測一個文件是否結束,即到達文件尾,若結束,則返回非0值,否則返回0
    {
       fscanf(fp,"%d%s%s\n",&num, name,place); 
    }
    */
 
    //檢測讀取結果
    printf("%d %s %s\n",num, name, place);
 
    //關閉流
    fclose(fp); 
    
    return 0;

 }

程序運行結果:

 

2:從文件中讀取整行數據(標准庫stdio.h下的fgets

函數原型:char *fgets(char *str, int n, FILE *stream); 

其從指定的流 stream 讀取一行,並把它存儲在 str 所指向的字符串內。當讀取 (n-1) 個字符時,或者讀取到換行符時,或者到達文件末尾時,它會停止,遇到空格不停止;

例從文件中讀取一行數據:

代碼實現:

//test3.c
//行讀取文件數據

#include<stdio.h>
#define maxlen 30

int main()
{
    //創建文件流
    FILE *fp=fopen("./data.txt","r");
    
    //2:檢測文件是否打開成功;
    if(!fp){
       printf("打開失敗!\n");
       return -1; //返回異常
    }
    char str[maxlen];//緩沖區,用來儲存數據

    //從文件中讀取一行數據,儲存到str開始的地址,最大長度為maxlen,然后下次讀取從下行開始
    //如果該行的數據長於maxlen-1,則只能返回一個不完整的行,並下次調用時從該處開始
    fgets(str,maxlen,fp);

    //檢測結果
    printf("%s\n",str);

    //關閉流
    fclose(fp);
    return 0;

}

運行結果:

 


 

二:保存

1:保存與讀取往往相關聯,保存格式決定了你讀取的方式,使用函數fprintf可以進行指定格式的保存:

函數原型為:int fprintf( FILE *stream, const char *format, [ argument ]...) 

假設保存一個人的個人信息到文件中:

/*test2.c */
//數據保存

#include<stdio.h>

int main()
{
    //例一個人的信息
    int num=1;
    char name[10]="小明";
    char place[10]="河南";

    //建立與文件的流
    FILE *fp=fopen("./data.txt","w");
    
    //2:檢測文件是否打開成功;
    if(!fp){
       printf("打開失敗!\n");
       return -1; //返回異常
    }

    //將數據格式化輸出到指定文件流,int fprintf( FILE *stream, const char *format, [ argument ]...) 
    //注:此函數,是將format字符串寫入到指定輸出流中,format包括空格字符,非空格字符,說明符之中的一個或多個。如:fprintf(fp," "); 就是將空格輸入到流中。
    //可理解為進程借助流將數據打印(fprintf)到了文件中;

    //將個人信息,寫入指定流中,數據間以一個空格分隔,最后還寫入換行符(控制字符)。
    fprintf(fp,"%d %s %s\n",num, name,place);

    //所以常常只要利用一個while語句就可以將講一個表(鏈表,順序表)按指定行格式寫入輸出流中
    /*
    while(!feof(fp)) //feof()檢測一個文件是否結束,即到達文件尾,若結束,則返回非0值,否則返回0
    {
       fprintf(fp,"%d %s %s\n",num, name,place); 
    }
    */
    //關閉流
    fclose(fp);

    return 0;

}

運行結果:

 

2:寫一個字符串到流中(fputs),函數原型:int fputs(const char *str, FILE *stream);

例:

//test4.c
//保存字符串

#include<stdio.h>

int main()
{
    //1:創建文件流,文件指針名=fopen(文件名,使用文件方式)打開失敗則返回NULL;
    FILE *fp=fopen("./data.txt","a"); //以data.txt文件為例,a表示追加

    //2:檢測文件是否打開成功;
    if(!fp){
       printf("打開失敗!\n");
       return -1; //返回異常
    }

    //string
    char string[20]="Facing the world";

    //write string to the fstream
    fputs(string,fp);

    //關閉流
    fclose(fp);

    return 0;

}

運行結果:

 

 

淺談c++:


 

在c++中我們可以使用操作符<<, >>來進行流的讀寫操作,更加的方便和易於理解;

具體參考下列實例:

1:讀取所示數據:

代碼實現:

//c++文件讀取
#include<iostream> //輸入輸出流
#include<fstream> //文件流

//using namespace std; //若使用該聲明,則可以不用在使用的每個標准庫的成員前加std::


int main()
{
   //序號,年齡,年;
   int num, age, year;
   //姓名,地址
   char name[20], place[20];

   //c++的文件流,ifstream為輸入文件流
   std::ifstream fp;

   //open為ifstream的成員函數,功能為打開文件,並將它與流關聯
   fp.open("./data.txt",std::ios::in); //ios::in表示讀流的方式,表示打開模式。

   //成員函數is_open檢查流是否有關聯文件,即打開成功與否,成功返回true,失敗返回false
   if(!fp.is_open()){
       std::cout<<"打開文件失敗!!\n";
       return 1;       // 返回異常;
   }

   //讀取數據
   fp>>num>>year>>age>>name>>place; //使用操作符>>,將數據傳輸到對應的變量中

   //檢測
   std::cout<<num<<":"<<name<<",age:"<<age<<",year:"<<year<<",live in:"<<place<<"\n"; //cout相當於printf

   //關閉流
   fp.close();

    return 0;
}

運行結果:

 

2:往文件保存數據:

實例:保存一個人的具體信息到文件data.txt中

代碼實現:

//c++數據保存
#include<iostream> //輸入輸出流
#include<fstream> //文件流

//using namespace std; //若使用該聲明,則可以不用在使用的每個標准庫的成員前加std::


int main()
{
   //序號,年齡,年;
   int num=3;
   int age=20;
   int year=1993;
   //姓名,地址
   char name[20]="小龍";
   char place[20]="廣元";

   //c++的文件流,ofstream為輸出文件流
   std::ofstream fp;

   //open為ofstream的成員函數,功能為打開文件,並將它與流關聯
   fp.open("./data.txt",std::ios::app); //ios::app表示每次寫入是都追加到流尾,表示打開模式。

   //成員函數is_open檢查流是否有關聯文件,即打開成功與否,成功返回true,失敗返回false
   if(!fp.is_open()){
       std::cout<<"打開文件失敗!!\n";
       return 1;       // 返回異常;
   }

   //讀取數據
   fp<<num<<" "<<year<<" "<<age<<" "<<name<<" "<<place<<"\n"; //使用操作符<<,將各數據傳輸到流所關聯的文件中

   //關閉流
   fp.close();

    return 0;
}

運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM