scanf和fscanf讀取文件


這篇是針對推箱子游戲而寫的,某個時候在學C語言,最近轉到windows設計,不知道是否有同樣的感受,后面的東西學了,前面的就有點生疏了。其實,我的理解是,注意力轉移了,當集中於當前問題的時候就會忽略以前的某些知識。這也說明,人的注意力是隨着時間,學習內容的不同在起變化。但是,只要稍微復習一下就能很快恢復。

問題:比如一個文本文件的內容如下:

[1]
0000000000000000
0000000000000000
0000000000000000
0000011100000000
0000013100000000
0000012111100000
0001114243100000
0001324611100000
0001111410000000
0000001310000000
0000001110000000
0000000000000000
0000000000000000
0000000000000000
[2]
0000000000000000
0000000000000000
0001111100000000
0001622100000000
0001244101110000
0001242101310000
..................(截選)

[]內是序號,往下延伸,每個[]下面是14行16列的數據,我想獲取給定的某個序號下面的這個二維數組數據,比如說,序號[10]下面的14*16列的數據。

————————————————————————————————————————————————————————————

在這個問題之前,首先理解一下流的概念,簡易記錄一下:

流有很多種,包括輸入流,輸出流等,這里只說輸入流,比如stdin,在調用scanf函數讀取這個流的時候,有幾個需要注意的要點:
首先,scanf忽略前面的空格,回車等等字符
其次,在讀取的時候,流中還有一個指針在不停的移動,也就是游標。做個圖來說明:

想輸入一個數據ABCD到字符串中,在開始的時候,故意敲入空格+回車鍵,這對scanf無影響,它會忽略,一直讀取ABCD,又遇到一個回車,游標最終停留在回車這個字符上。

這個回車鍵被scanf獲取了嗎?其實是沒有的,比如接下來可以用c=getchar(),就可以捕捉到這個回車字符。

同理,將stdin換成文件fp,一樣遵循這個規則。因為不是專項整理流的問題,所以只簡單概括到這。

————————————————————————————————————————————————————————

對於上題的解法是,從fp中讀取一個字符串,然后和待匹配的序號比較,比如和字符串"[10]"比較,如果相等,則游標就定位在[10]之后的位置。

觀察上面的文本文件,每一行之后就是一個回車,所以每次從fp中讀取一個串,要么讀的是[xx],要么讀的就是二維數組的一行數據,當然,這個串的存儲長度也至少大於一行的數據,至少為16個。

具體

首先獲取要取的序號,定義一個字符串,將之寫入其中。

char str[10];
sprintf(str,"[%d]",n);

接着,按串讀取fp,與之相比較。

    FILE *fp=fopen("map.txt","rb");  //打開文本文件
    if(fp==NULL)
        return;
    char data[20];
    fscanf(fp,"%s",data);//先讀入一個串
    while(strncmp(str,data,strlen(str))!=0)//相等返回0
    {    
        if(fscanf(fp,"%s",data)==NULL)//循環讀取,游標也在移動
            break;        
    }

假如讀取到[10],符合題意了,則游標就正停留在[10]的后面,下面就是[10]序號下的14*16的數據。這個地方還有一個用處,比如說,一共有40關,假如玩家通關了,再掃描文件肯定找不到[41]的序號,就可以判定玩家通關了。

因為要讀取14*16,相當於二維數組,處理如下:

    for(int y=0;y<14;y++) //
    {
        fscanf(fp,"%s",data);//讀取一行
        for(int x=0;x<16;x++)//
        {
            map[y][x]=data[x]-'0';//字符變整型,填充map[][],map[][]是一個整型的二維數組,所以需要轉換
            ......
        }
    }

這樣,問題就解決了。

完整的示例代碼

void LoadMap(int n) //載入地圖,主要負責填充map[][]的二維數組,map[][]是操縱畫圖的關鍵
{
    char str[10];
    sprintf(str,"[%d]",n);
    FILE *fp=fopen("map.txt","rb");  //打開文件,讀取地圖數據,所謂地圖,就是用數字來(標示)操縱位圖塊
    if(fp==NULL)
        return;
    char data[20];
    fscanf(fp,"%s",data);//先讀入一個串
    while(strncmp(str,data,strlen(str))!=0)//相等返回0
    {    
        if(fscanf(fp,"%s",data)==NULL)//循環讀取,游標也在移動
            break;        
    }
    for(int y=0;y<14;y++) //行
    {
        fscanf(fp,"%s",data);//讀取14行
        for(int x=0;x<16;x++)//列
        {
            map[y][x]=data[x]-'0';//字符變整型,填充map[][]
            if(map[y][x]==MANATROAD||map[y][x]==MANATDESTINATION)
            {
                manposition.x=x;//人的位置
                manposition.y=y;
            }
        }
    }
    fclose(fp);
}

*注:這段程序,每次都要掃描整個文件,獲取與序號相同的串,由於文件比較小,影響也不是太大。

總結:對一個文本文件的搜索過程。


免責聲明!

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



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