C - 将数据读入结构数组,memcpy?

标签 c arrays struct

为清楚起见编辑:

fscanf 正在按照此处编写的方式工作...它将数据获取到损坏的数组中。

为清楚起见,再次进行编辑:

唯一的失败点是通过循环的第二次迭代中的 memcpy 行,其中 fileindex 为 0 且 i 为 1。当 i 为 0 时,memcpy 行工作正常。


我正在使用 fread 将用于从二进制文件直接读取数据的程序转换为从 ascii 文本读取的数组。这是设置:

#define MAX_FLIGHT_ENTRIES    27000
#define MAX_PLANES_IN_A_FLIGHT 10

typedef struct {
    double local_x;
    double local_y;
    double local_z;
    float pitch;
    float roll;
    float heading;
    float gearpos;
    float flappos;
    float speedbrakepos;
    float canopypos;
    float afterburnerOn;
    float kias;
    float time;     // record timestamp
} FLIGHT_ENTRY_TYPE;
static FLIGHT_ENTRY_TYPE FlightEntries [MAX_PLANES_IN_A_FLIGHT][MAX_FLIGHT_ENTRIES];

过去的工作方式是,在一个循环中,数组将通过以下方式填充:

fread (&FlightEntries[fileIndex][i], sizeof (FLIGHT_ENTRY_TYPE), 1, pFile);

而且我相信这实际上会通过将数据直接放入内存来实例化数组中的每个条目。现在我正在从一个文本文件中读取,并且我已经尽我所能将值放入数组中,但它只会写入第一个条目 FlightEntries[0][0]。任何读取或写入 FlightEntries[0][1] 的尝试都会崩溃。这是我目前的最佳尝试。

for ( i = 0; i < MAX_FLIGHT_ENTRIES; i++)
{               
        // If the file end is found before it should be, set values to defaults
        // and save the file
        if (feof(pFile))
        {
            FlightInfo[fileIndex].endFrameIndex = i - 1;
            break;
        }
        else
        {
            float plocalx, plocaly, plocalz;
            float ppitch, proll, pheading, pgearpos, pflappos, pbrakepos, pcanopypos, pafterburnon, pkias, ptime;
            
            int fresult;
            fresult = fscanf(pFile, "%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
                &plocalx,
                &plocaly,
                &plocalz,
                &ppitch,
                &proll,
                &pheading,
                &pgearpos,
                &pflappos,
                &pbrakepos,
                &pcanopypos,
                &pafterburnon,
                &pkias,
                &ptime);

                FLIGHT_ENTRY_TYPE newEntry;

            newEntry.local_x = (double)plocalx;
            newEntry.local_y = (double)plocaly;
            newEntry.local_z = (double)plocalz;
            newEntry.pitch = ppitch;
            newEntry.roll = proll;
            newEntry.heading = pheading;
            newEntry.gearpos = pgearpos;
            newEntry.flappos = pflappos;
            newEntry.speedbrakepos = pbrakepos;
            newEntry.canopypos = pcanopypos;
            newEntry.afterburnerOn = pafterburnon;
            newEntry.kias = pkias;
            newEntry.time = ptime;

            memcpy (&FlightEntries[fileIndex][i], &newEntry, sizeof FLIGHT_ENTRY_TYPE);
        }
}

我认为数组条目没有正确分配。我试过直接通过 FlightEntries[fileIndex][i].local_x = (double)plocalx; 访问各个结构成员,我也试过使用 memcpy 来做每个成员都做同样的事情……我的指示有误吗?我不知道该去哪里。每当我越过一个绊脚石时,就会出现其他问题,我认为这都与数组有关,而不是从文件中读取。我必须做些什么来分配空间吗?

最大的问题是:

fread 对 FlightEntries[0][1] 中的二进制数据做了什么而 memcpy 没有做?我的 memcpy 行是否正确?我需要做某种malloc吗?

最佳答案

...用于使用 fread 将二进制文件中的数据直接读取到数组中。...
编辑
现在我正在读取一个文本文件,并且我已尽我所能将值放入数组中。

除非您的文件内容与 FLIGHT_ENTRY_TYPE 结构的当前定义相匹配,也许这些定义:

#define MAX_FLIGHT_ENTRIES    27000
#define MAX_PLANES_IN_A_FLIGHT 10

无论您尝试什么,您的读取尝试都会出现问题。 (文件内容和结构定义必须对齐以执行您要执行的操作。因为您使用的是文本文件,所以这应该很容易验证。)

还有 feof(pFile) 很少是读取文件的好选择

考虑把它改成这样:(伪代码)

FLIGHT_ENTRY_TYPE newEntry;
int len = sizeof(FLIGHT_ENTRY_TYPE)*2;// *2 to account for comma delimiters, etc.  Change as needed
char **stringArray = {0};
//see edits in answer below for defintion of allocArray()
stringArray = allocMemory(stringArray, MAX_PLANES_IN_A_FLIGHT, len);        
FILE *fp = fopen(".\\filename.bin", "rb");
if(fp && stringArray)
{   
    while(fgets(stringArray[i], len, fp)
    {
         fresult = sscanf(stringArray[i], "%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
                    &plocalx,
                    &plocaly,
                    &plocalz,
                    &ppitch,
                    &proll,
                    &pheading,
                    &pgearpos,
                    &pflappos,
                    &pbrakepos,
                    &pcanopypos,
                    &pafterburnon,
                    &pkias,
                    &ptime);  
          if(fresult > 0)
          { ...assign values to newEntry struct...  }

    }
    fclose(fp);
    freeMemory(stringArray,MAX_PLANES_IN_A_FLIGHT);   
}

结构的前三个成员是 double 值,因此应该读入 double 值。如果您决定进行更改:

float plocalx, plocaly, plocalz; 

收件人:

double plocalx, plocaly, plocalz;

一定要改变:

fresult = fscanf(pFile, "%f %f %f %f %f %f %f %f %f %f %f %f %f\n", 

:

fresult = fscanf(pFile, "%lf %lf %lf %f %f %f %f %f %f %f %f %f %f\n",  

您还应该检查 sscanf()
的返回值 返回值: 根据formatString 中的说明符将指定源字符串的输入转换为一系列值。如果输入失败发生在 第一个 转换之前,函数返回EOF(-1);否则,该函数返回分配的输入项数。如果复制发生在重叠的对象之间,则行为未定义。

编辑 2
如果您确实需要创建一个字符串数组(针对文件的每一行),这些函数将有所帮助:

char ** allocMemory(char ** a, int numStrings, int maxStrLen)
{
    int i;
    a = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
    for(i=0;i<numStrings; i++)
    {
      a[i] = calloc(sizeof(char)*maxStrLen + 1, sizeof(char));
    }
    return a;
}

void freeMemory(char ** a, int numStrings)
{
    int i;
    for(i=0;i<numStrings; i++)
        if(a[i]) free(a[i]);
    free(a);
}

//usage:
#define MAX_FLIGHT_ENTRIES    27000
#define MAX_PLANES_IN_A_FLIGHT 10
int main(void)
{
    char **stringArray = {0};
    stringArray = allocMemory(stringArray, MAX_PLANES_IN_A_FLIGHT, sizeof FLIGHT_ENTRY_TYPE);
    ...//read data into string array as shown in code above
    return 0;
}   

这里的概念是假设文件的每一行代表填充 FLIGHT_ENTRY_TYPE 结构的一个结构实例的数据。换句话说,为结构数组中的每个结构读取文件中的一行。

关于C - 将数据读入结构数组,memcpy?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28857447/

相关文章:

c - 安全调整结构大小

c - 将数组发送到函数仅发送数组的第一个元素

c - 如何将#define 常量从.h 文件导入Ada?

c++ - 设置两个结构彼此相等后指针为 NULL

c - 从accept()获取目的地/IP地址?

arrays - 我无法快速获取循环的 json 值

java - 如何检查 JsonElement 中的项目是否存在于单独的 JsonArray 中?

java - 将 RGB byte[][] 图像转换为 byte[] 的最佳方法

c - 计算 int 最大值的函数未返回所需结果

c - C 中的循环优化