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

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

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

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

时间: 2024-11-02 06:48:17

scanf和fscanf读取文件的相关文章

scanf() & gets() & fgets() 读取字符串的区别

scanf()和gets()读取字符串的区别 主要的差别在于它们如何决定字符串何时结束 scanf()更基于获取单词(get word)而不是获取字符串(get string): gets()会读取所有的字符,直到遇见第一个换行符为止. scanf()使用两种方法决定输入结束. 如果使用%s格式,字符串读到(但不包括)下一个空白字符(比如空格.制表符或换行符) 如果指定了字段宽度,比如%10s,scanf()就会读入10个字符或者直到遇见第一个空白字符,由二者中最先满足的那一个终止输入 注:无论

scanf与gets读取字符串的区别

对于编程初学者很多人对gets和scanf都没做过深入的了解,本文为大家详细说明gets和scanf的区别 gets 1.函数:gets(字符指针) 2.头文件:stdio.h(c中),c++不需包含此头文件 3.原型:char*gets(char*buffer); 4.功能:从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中.注意:(换行符不作为读取串的内容,读取(接受)的换行符被转换为null值,并由此来结束字符串.) 5.返回

用结构体读取文件

#include<stdio.h>#include<stdlib.h>#include<string.h> int main(void){ struct data { char id[20]; char name[20]; char sex[10]; int old; char number[20]; char habit[10]; char b[10]; int piao; } student[10]; FILE *fp; if((fp=fopen("shi

Python读取文件数据

1题目要求: 文本文件有这些数据,需要的只有其中的5个属性,如下颜色标记 像以下的数据达到75万组: 1product/productId: B0000UIXZ4 2product/title: Timex Link USB Watch 3product/price: unknown 4review/userId: A14MVG2I9PS6NZ 5review/profileName: B. Kuiper "Wah" 6review/helpfulness: 0/0 7review/s

写出文件、读取文件、格式化写出和读取文件

1. 写出文件 #include <stdio.h> main() { FILE * f=fopen("data.txt","w"); if(f!=NULL) //quan xian { //fputc('A',f); fputs("hello world",f); fclose(f); } else { puts("File can not create"); puts("end"); } 2

PHP如何正确读取文件内容?解析

PHP 读取文件的多种方法,一起来看看吧. 处理诸如 PHP 之类的现代编程语言的乐趣之一就是有大量的选项可用.PHP 可以轻松地赢得 Perl 的座右铭“There's more than one way to do it”(并非只有一种方法可做这件事),尤其是在文件处理上.但是在这么多可用的选项中,哪一种是完成作业的最佳工具?当然,实际答案取决于解析文件的目标,因此值得花时间探究所有选项. 回页首 传统的 fopen 方法 fopen 方法可能是以前的 C 和 C++ 程序员最熟悉的,因为如

C++/Php/Python/Shell 程序按行读取文件或者控制台

写程序经常需要用到从文件或者标准输入中按行读取信息,这里汇总一下.方便使用 1. C++ 读取文件 1 #include<stdio.h> 2 #include<string.h> 3 4 int main(){ 5 const char* in_file = "input_file_name"; 6 const char* out_file = "output_file_name"; 7 8 FILE *p_in = fopen(in_fi

scanf sscanf fscanf

scanf 从控制台输入   fscanf 从文件输入   sscanf 从指定字符串输入 scanf 用法为 int scanf(const char * restrict format,...); scanf 是从标准输入读 scanf一般情况下是碰到空格,制表符以及换行作为输入的结束 支持正则表达式 格式为  %[] []内是匹配的字符,^表示求反集,当遇到非集合内的字符时立即终止输入 [a-z]  输入指定范围的小写字母,遇到非法字符立即终止 [0-9] 输入指定范围的数字,遇到非法字符

解决Python读取文件时出现UnicodeDecodeError: &#39;gbk&#39; codec can&#39;t decode byte...

用Python在读取某个html文件时会遇到下面问题: 出问题的代码: 1 if __name__ == '__main__': 2 fileHandler = open('../report.html', mode='r') 3 4 report_lines = fileHandler.readlines() 5 for line in report_lines: 6 print(line.rstrip()) 修改方式是在open方法指定参数encoding='UTF-8': if __nam