• 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);
    }

    *注:这段程序,每次都要扫描整个文件,获取与序号相同的串,由于文件比较小,影响也不是太大。

    总结:对一个文本文件的搜索过程。

  • 相关阅读:
    How to use VS2012 remote debug Windows Azure Cloud Services
    vue ---05 分页和详情页功能的实现
    vue ----04课程列表的展示
    vue--03 首页和登陆注册
    luffy--03 首页和登陆注册(跨域问题的解决)
    luffy--02 ---项目配置和数据库链接
    luffy---01
    DRF---一些配置/设置
    drf-路由
    drf视图
  • 原文地址:https://www.cnblogs.com/tinaluo/p/5442176.html
Copyright © 2020-2023  润新知