使用fwrite时加扰数组顺序

时间:2016-07-03 01:48:38

标签: c io

我正在尝试使用fwrite将数组写入二进制文件,因为我正在编写一个x-points流,后跟一个y-points流,顺序很重要。我希望写入输出,以便我的文件包含一对数组:

[ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4]
[ 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4]

如果我使用fprintf写出文本文件并循环遍历数组索引,我会得到预期的输出顺序,但是当我使用下面的fwrite代码时,数据是按顺序写的。由于我使用的是一个简单的数组,因此我希望fwrite调用可以简单地按顺序写出整个数组。是不是这种情况,我误解或是我的错误在其他地方?

#include<stdlib.h>
#include<stdio.h>
#include<omp.h>

#define cache_align 0x40

#define xmin -2
#define ymin -2
#define xrange 4
#define yrange 4
#define xres 5
#define yres 5
#define num_particles (xres*yres)

int main(){

  unsigned int stepnum = 0;

  double* cx = aligned_alloc(cache_align, sizeof(double)*num_particles);
  double* cy = aligned_alloc(cache_align, sizeof(double)*num_particles);

  for(int ii=0; ii<xres; ii++){
    for(int kk=0; kk<yres; kk++){
      cx[ii*yres + kk] = ii;
      cy[ii*yres + kk] = kk;
    }
  }


  FILE* outfile;
  char fname[100];
  sprintf(fname, "out.bin");
  outfile = fopen(fname,"wb");
  if(!outfile){
    printf("Unable to open output file!");
  } else {
    size_t written;
    written = fwrite(cx,sizeof(double),num_particles,outfile);
    written = fwrite(cy,sizeof(double),num_particles,outfile);
    fclose(outfile);
  }

  return 0;
}

编辑:我应该添加我正在使用python检查数据输出:

import numpy as np
data = np.fromfile('out.bin','double',-1)

1 个答案:

答案 0 :(得分:0)

目前还不清楚您是否为了简洁而省略了所有验证和错误检查,或者这只是您忽略的内容。您的索引问题由另一个答案正确解决。如果您有意省略了验证和错误检查,那么您可以在很大程度上忽略以下内容,如果没有,则考虑负责验证代码中的每个步骤,这是后续操作所依赖的。 / p>

至少,这意味着验证所有内存分配,文件打开和文件关闭(用于写入)和号码在写入时写入的对象到数据文件。验证只是简单的检查,以确保您有一个有效的内存块,一个有效的文件流,您要写入的对象的数量实际写入,并且写入后文件上没有流错误。它们可以像文件流打开一样简单:

FILE *fp = argc > 1 ? fopen (fname, "wb") : stdout;

if (!fp) {  /* validate file is open for writing */
    fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
    return 1;
}

对于内存分配:

/* validate all memory allocation */
if (!(cx = aligned_alloc (cache_align, sizeof *cx * NPART))) {
    fprintf (stderr, "error: virtual memory exhausted - cx.\n");
    return 1;
}

验证写入文件的对象数量(writtennobjnum_particlesNPART - 我讨厌打字):

    /* validate the number of objects written to file */
    if ((nobj = fwrite (cx, sizeof *cx, NPART, fp)) != NPART)
        fprintf (stderr, "warning: fwrite failure - cx.\n");
    if ((nobj = fwrite (cy, sizeof *cy, NPART, fp)) != NPART)
        fprintf (stderr, "warning: fwrite failure - cy.\n");

写入文件后关闭蒸汽:

    if (fclose (fp))  /* validate the stream closure for writes */
        fprintf (stderr, "error: fclose failed, data is suspect.\n");

最后,不要忘记释放你分配的内存。养成跟踪分配和释放每个分配的习惯,而不是依赖exit为您的分配。在以后开始在各种功能中进一步分配时,这将是常规的。还可以通过内存错误检查程序运行代码,例如Linux上的valgrind,以确保正确使用。

虽然您可以自由地检查您喜欢的数据,但只需编写验证功能就可以消除过程中的不确定性。例如,您可以简单地将现有数组传递给验证函数,并使该函数读取您编写的数据并提供每个值的比较。它只需要指出是否发生了错误。如果没有,那你就没事了。例如,一个简单的检查函数(为简单起见使用静态数组)可以是:

int chkdatafile (char *fn, double *a, double *b)
{    
    int err = 0;
    size_t nobj = 0;
    double cx[NPART] = {0.0}, cy[NPART] = {0.0};
    FILE *fp = fopen (fn, "rb");

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: fopen failed '%s'.\n", fn);
        return 1;
    }

    /* validate NPART object read into each array */
    if ((nobj = fread (cx, sizeof *cx, NPART, fp)) != NPART) {
        fprintf (stderr, "error: fread failure - cx.\n");
        return 1;
    }

    if ((nobj = fread (cy, sizeof *cx, NPART, fp)) != NPART) {
        fprintf (stderr, "error: fread failure - cy.\n");
        return 1;
    }

    fclose (fp);

    for (int i = 0; i < NPART; i++) /* validate cx read from file */
        if (cx[i] != a[i]) {
            fprintf (stderr, "error: cx[%2d] : (read) %02.0lf != %02.0lf\n",
                    i, cx[i], a[i]);
            err = 1;
        }

    for (int i = 0; i < NPART; i++) /* validate cy read from file */
        if (cy[i] != b[i]) {
            fprintf (stderr, "error: cx[%2d] : (read) %02.0lf != %02.0lf\n",
                    i, cy[i], b[i]);
            err = 1;
        }

    return err;
}

您可以通过以下类似的程序从您的程序中调用它:

    if (chkdatafile (fname, cx, cy))
        fprintf (stderr, "error: data in '%s' is invalid.\n", fname);

就像我说的那样,如果你故意省略了支票,那么我不会告诉你任何你不知道的事情,如果不是,那么请尽早养成习惯,以便随时验证以后所依赖的任何事情。在你的代码中。从长远来看,它将为您节省大量的调试时间等。

将所有部分放在一起,将输出文件名作为程序的第一个参数(如果没有给出输出文件名,只需将值写入stdout),您可以提供如下最小化检查:

#include <stdlib.h>
#include <stdio.h>

#define cache_align 0x40

#define XRES 5
#define YRES 5
#define NPART (XRES*YRES)

int chkdatafile (char *fn, double *a, double *b);

int main (int argc, char **argv) {

    size_t nobj;
    double *cx, *cy;
    char *fname = argc > 1 ? argv[1] : "stdout";
    FILE *fp = argc > 1 ? fopen (fname, "wb") : stdout;

    if (!fp) {  /* validate file is open for writing */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    /* validate all memory allocation */
    if (!(cx = aligned_alloc (cache_align, sizeof *cx * NPART))) {
        fprintf (stderr, "error: virtual memory exhausted - cx.\n");
        return 1;
    }

    if (!(cy = aligned_alloc (cache_align, sizeof *cy * NPART))) {
        fprintf (stderr, "error: virtual memory exhausted - cx.\n");
        return 1;
    }

    for (int i = 0; i < XRES; i++)
        for (int k = 0; k < YRES; k++) {
            cx[k * YRES + i] = i;
            cy[k * YRES + i] = k;
        }

    if (argc > 1) {  /* validate the number of objects written */
        if ((nobj = fwrite (cx, sizeof *cx, NPART, fp)) != NPART)
            fprintf (stderr, "warning: fwrite failure - cx.\n");
        if ((nobj = fwrite (cy, sizeof *cy, NPART, fp)) != NPART)
            fprintf (stderr, "warning: fwrite failure - cy.\n");
    }
    else {
        for (int i = 0; i < NPART; i++)
            printf (" %02.0lf", cx[i]);
        putchar ('\n');
        for (int i = 0; i < NPART; i++)
            printf (" %02.0lf", cy[i]);
        putchar ('\n');
    }

    if (fp != stdout) {
        if (fclose (fp))  /* validate the stream closure for writes */
            fprintf (stderr, "error: fclose failed, data is suspect.\n");
        if (chkdatafile (fname, cx, cy))
            fprintf (stderr, "error: data in '%s' is invalid.\n", fname);
    }

    free (cx);  /* free all allocated memory */
    free (cy);

    return 0;
}

int chkdatafile (char *fn, double *a, double *b)
{    
    int err = 0;
    size_t nobj = 0;
    double cx[NPART] = {0.0}, cy[NPART] = {0.0};
    FILE *fp = fopen (fn, "rb");

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: fopen failed '%s'.\n", fn);
        return 1;
    }

    /* validate NPART object read into each array */
    if ((nobj = fread (cx, sizeof *cx, NPART, fp)) != NPART) {
        fprintf (stderr, "error: fread failure - cx.\n");
        return 1;
    }

    if ((nobj = fread (cy, sizeof *cx, NPART, fp)) != NPART) {
        fprintf (stderr, "error: fread failure - cy.\n");
        return 1;
    }

    fclose (fp);

    for (int i = 0; i < NPART; i++) /* validate cx read from file */
        if (cx[i] != a[i]) {
            fprintf (stderr, "error: cx[%2d] : (read) %02.0lf != %02.0lf\n",
                    i, cx[i], a[i]);
            err = 1;
        }

    for (int i = 0; i < NPART; i++) /* validate cy read from file */
        if (cy[i] != b[i]) {
            fprintf (stderr, "error: cx[%2d] : (read) %02.0lf != %02.0lf\n",
                    i, cy[i], b[i]);
            err = 1;
        }

    return err;
}

如果您提供输出文件名并且没有收到任何错误,则所有内容都按预期进行。仔细看看,如果您有任何问题,请告诉我。