首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于偏移量和逐行读取文件的问题

关于偏移量和逐行读取文件的问题
EN

Stack Overflow用户
提问于 2021-03-16 03:28:06
回答 1查看 88关注 0票数 0
代码语言:javascript
复制
#include "offsetFinder.h"

/**  Reads a GIS record file (as described in the corresponding project
 *   specification), and determines, for each GIS record contained in that
 *   file, the offset at which that record begins.  The offsets are stored
 *   into an array supplied by the caller.
 * 
 *   Pre:  gisFile is open on a GIS record file
 *         offsets[] is an array large enough to hold the offsets
 *   Post: offsets[] contains the GIS record offsets, in the order
 *            the records occur in the file
 *   Returns:  the number of offsets that were stored in offsets[]
 */
uint32_t findOffsets(FILE* gisFile, uint32_t offsets[]) {
    FILE *op;
    /***  Complete the implementation of this function  ***/
    int count = 0;
    char offsets[1000];
    char *reader;
    op = fopen(gisFile, "r");
    if (!op) {
        perror("Failed to open file!\n");
        exit(1);
    }
    else {
        reader = offsets;
        while (*reader != '\n' && fgets(offsets, sizeof(offsets), op)) {
            count++;
        }
    }
    return count;
}

大家好,我有一个关于这个作业的问题。这样的设置正确吗?对于GISData.txt,我应该读取整个文件,并且必须返回存储在offsets[]中的偏移量。

代码语言:javascript
复制
FEATURE_ID|FEATURE_NAME|FEATURE_CLASS|STATE_ALPHA|STATE_NUMERIC|COUNTY_NAME|COUNTY_NUMERIC|PRIMARY_LAT_DMS|PRIM_LONG_DMS|PRIM_LAT_DEC|PRIM_LONG_DEC|SOURCE_LAT_DMS|SOURCE_LONG_DMS|SOURCE_LAT_DEC|SOURCE_LONG_DEC|ELEV_IN_M|ELEV_IN_FT|MAP_NAME|DATE_CREATED|DATE_EDITED
885513|Siegrest Draw|Valley|NM|35|Eddy|015|323815N|1043256W|32.6376116|-104.5488549|323859N|1043732W|32.6498321|-104.6255227|1095|3592|Parish Ranch|11/13/1980|
885526|AAA Tank|Reservoir|NM|35|Eddy|015|321043N|1041456W|32.1786543|-104.2489615|||||1006|3300|Bond Draw|11/13/1980|06/23/2011
885566|Adobe Draw|Valley|NM|35|Eddy|015|322820N|1042141W|32.4723375|-104.361345|322704N|1042129W|32.4511111|-104.3580556|1007|3304|Carlsbad West|11/13/1980|
885567|Adobe Flat|Flat|NM|35|Eddy|015|322849N|1042119W|32.4803932|-104.3552339|||||1006|3300|Carlsbad West|11/13/1980|
885607|Alacran Hills|Range|NM|35|Eddy|015|322812N|1041055W|32.4701183|-104.1818931|||||1009|3310|Carlsbad East|11/13/1980|
885684|Alkali Lake|Lake|NM|35|Eddy|015|323039N|1041133W|32.5109371|-104.1924802|||||966|3169|Angel Draw|11/13/1980|06/23/2011
885697|Allen Well|Well|NM|35|Eddy|015|322309N|1042120W|32.3859489|-104.3555084|||||1038|3405|Carlsbad West|11/13/1980|

这是地理信息系统的一个片段,每个区域数据(一行)都被认为是一条GISData.txt记录。“赋值中提到的偏移量是GIS数据文件中GIS记录的开始位置。

由于每条GIS记录占用整行,因此GIS记录的偏移量仅仅是GIS记录中第一个字节的偏移量。

当然,GIS数据文件的第一行不包含GIS记录,因此在偏移量0处没有GIS记录。“

如果我完全错了,有人能检查一下我的代码并修改它吗?谢谢你!!

EN

回答 1

Stack Overflow用户

发布于 2021-03-16 20:24:08

“对于GISData.txt,我应该通读整个文件,我必须返回存储在offsets[]....Can中的偏移量,如果我完全错了,有人检查我的代码并修改它?”

首先,在这个问题中,似乎对偏移的含义有一些混淆。而且,在谷歌上搜索"gid offset“之后,我可以理解为什么。这是a GIS specific definition

_“偏移量

地图学在地图学中,地物的位移或运动,使它们在以给定比例显示时不会重叠。

例如,如果符号足够宽以至于它们重叠,则道路可以从河流偏移。

符号系统在符号系统中,符号的原点或插入点在x和/或y方向上的移位。ESRI软件在ArcGIS中,将场景中的表面或要素的z值更改为恒定量或

通过使用表达式。可以应用偏移来使要素恰好绘制在表面之上。“_

而这个“C语言的地理信息系统”definition

“文件可以被看作是一个字节序列,每个字节位于文件开头的唯一偏移量,就像数组的单元格一样。因此,每条地理信息系统记录从文件开头的唯一偏移量开始。”

这两个定义虽然都源于对gis偏移的搜索,但它们是如此不同,以至于在这个问题中没有对这两个术语的含义提供任何澄清。出于这个回答的目的,我将从您在评论中的响应中获取我的队列,并将解决如何解析文件的每个记录中的第一个字段。(不包括第1行中的标题记录。)

这里有一些建议的步骤,可以用来实现这一点。

要考虑的步骤:

原型设计如注释中所述,原型向findOffsets()函数应提供以下内容:filespec、数组大小、数组。注释中没有提到,但也可能有用的是将读取的最长记录的长度。例如:

代码语言:javascript
复制
uint32_t findOffsets(const char *fileSpec, size_t longestElement, size_t numElements, uint32_t offsets[numElements]);

调用函数产生的

  • 读取文件一次以确定记录数。例如:numRecords。看见

int count_names(const char *filename, size_t *count){...}

示例here,例如如何读取记录的数量(以及当需要时获取最长的记录)。在文件中。完成后关闭文件:

  • 使用上一步中的记录数来调整数组的大小。

示例:

代码语言:javascript
复制
uint32_t offsets[numRecords-1];  //-1 skipping header line 
memset(records, 0, sizeof records);

  • call findOffsets()

示例:

代码语言:javascript
复制
size_t numOffsets = sizeof records/sizeof *records
uint32_t count = findOffsets("c:\\gis\\data.gis", longestRecord, numOffsets, offsets);
if(count > 0)
{
   //do something with records
}   

findOffsets()中的

  • 用于第二次读取process

的打开文件

  • 读取文件的每一行(跳过标题行)
  • 从每行中分析第一个'|‘分隔标记
  • 将分析的标记从字符串转换为integer
  • close文件
  • 返回已处理的行数。

下面是一个代码示例(具有非常有限的安全性/错误检查),展示了如何做到这一点。它使用您的示例文件内容进行了测试,并借用了上面链接的代码,以适应此目的:

代码语言:javascript
复制
const char *fileSpec = "C:\\some_directory\\gisData.gis";

uint32_t findOffsets(const char *fileSpec, size_t longestElement, size_t numElements, uint32_t offsets[numElements]);
int count_lines_in_file(const char *filename, size_t *count);
size_t filesize(const char *fn);

int main(void)
{
    size_t numRecords = 0;
    
    int longestRecord = count_lines_in_file(fileSpec, &numRecords)+1;//+1 room for null terminator
    uint32_t offsets[numRecords -1];//-1 - skipping header line
    memset(offsets, 0, sizeof offsets);//initialize VLA offsets
    int recordsProcessed = findOffsets(fileSpec, longestRecord, numRecords -1, offsets);//do the work
    
    return 0;
}

uint32_t findOffsets(const char *fileSpec, size_t longestElement, size_t numElements, uint32_t offsets[numElements])
{
      char *delim = "|";
      char *tok = NULL;
      char line[longestElement+1]; //+1 - room for null terminator during read.
      memset(line, 0, sizeof line);//initialize VLA line to all zeros 
      int inx = 0;
      FILE *fp = fopen(fileSpec, "r");
      if(fp)
      {
            while(fgets(line, sizeof line, fp))//loop to read all lines in file
            {
                if(!strstr(line, "FEATURE_ID"))//skip header line, process all other lines
                {
                    tok = strtok(line, delim);//extract first field
                    if(tok)
                    {
                        offsets[inx] = atoi(tok);//convert token and store number
                        inx++;
                    }
                }
            }
            fclose(fp);
      }
      return inx;
}

//passes back count of lines in file, and return longest line
int count_lines_in_file(const char *filename, size_t *count)
{
    int len=0, lenKeep = 0;
    FILE *fp = fopen(filename, "r");
    if(fp)
    {
        char *tok = NULL;
        char *delim = "\n";
        int cnt = 0;
        size_t fSize = filesize(filename);
        char *buf = calloc(fSize, 1);
        while(fgets(buf, fSize, fp)) //goes to newline for each get
        {
            tok = strtok(buf, delim);
            while(tok)
            {
                cnt++;
                len = strlen(tok);
                if(lenKeep < len) lenKeep = len;
                tok = strtok(NULL, delim);
            }
        }
        *count = cnt;
        fclose(fp);
        free(buf);
    }
    
    return lenKeep;
}

//return file size in bytes (binary read)
size_t filesize(const char *fn)
{
    size_t size = 0;
    FILE*fp = fopen(fn, "rb");
    if(fp)
    {
        fseek(fp, 0, SEEK_END); 
        size = ftell(fp); 
        fseek(fp, 0, SEEK_SET); 
        fclose(fp);
    }
    return size;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66644467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档