【问题标题】:Create an array of values from different text files in C从 C 中的不同文本文件创建一个值数组
【发布时间】:2014-10-02 13:23:10
【问题描述】:

我在 64 位 Ubuntu 14.04 上使用 C 语言工作。

我有许多 .txt 文件,每个文件都包含多行浮点值(每行 1 个值)。这些线代表复杂样本的一部分,如果有意义的话,它们会存储为 real(a1) \n imag(a1) \n real(a2) \n imag(a2)。

在特定情况下,有 4 个文本文件,每个文件包含 32768 个样本(因此有 65536 个值),但我需要使最终版本动态以容纳多达 32 个文件(每个文件的最大样本数不会超过 32768)。不过,我只会读取前 19800 个样本(取决于其他内容),因为整个信号都包含在这 39600 个点(19800 个样本)中。

一个常见的抽象是将文件/样本表示为矩阵,其中列表示返回信号,行表示每个信号在采样时刻的值,直到最大持续时间。

我要做的是从每个返回信号中获取第一个样本并将其移动到一个双精度浮点值数组中以进行一些工作,然后转到每个信号的第二个样本(这将覆盖前一个数组)并对它们做一些工作,依此类推,直到处理完最后一行样本。

有没有一种方法可以动态打开每个信号的文件(取决于我在该特定实例中使用的脉冲数),将每个文件中的第一个样本读入缓冲区并将其发送到处理。在下一次迭代中,文件指针将全部与第二个样本对齐,然后将它们移动到一个数组中并再次发送,直到达到所需的样本数量(在我们的假设情况下为 19800)。

我可以使用 fscanf 从文件中很好地读取样本:

rx_length = 19800;
int x;
float buf;

double *range_samples = calloc(num_pulses, 2 * sizeof(range_samples));

for (i=0; i < 2 * rx_length; i++){
    x = fscanf(pulse_file, "%f", &buf);
    *(range_samples) = buf;
}

所有需要发生的事情(在我看来)是我需要循环采样 # 和脉冲 #(按此顺序),因此当完成一个脉冲后,它将继续进行下一组采样脉搏等。我不知道该怎么做是以某种方式声明所有返回信号文件的文件指针,当它们的数量在两次调用之间可能会有所不同时(例如,为 4 个脉冲做整个事情,并且在下一次调用时它可以是 16 或64)。

如果有任何想法/cmets/建议,我很想听听。

谢谢。

【问题讨论】:

  • 文件列表是在程序开始时已知的,还是在程序运行时实时处理并创建新文件?
  • 是的,文件是rx_1_out.txt,其中1代表脉冲数。

标签: c arrays file-io


【解决方案1】:

我会让您发布的代码成为一个函数,该函数将文件名数组作为参数:

void doPulse( const char **file_names, const int size )
{
  FILE *file = 0;

  // declare your other variables

  for ( int i = 0; i < size; ++i )
  {
    file = fopen( file_names[i] );

    // make sure file is open
    // do the work on that file

    fclose( file );
    file = 0;
  }
}

【讨论】:

    【解决方案2】:

    您需要的是一台发电机。在 C++ 中这将相当容易,但是当您标记 C 时,我可以想象一个函数,将自定义结构(object 的状态)作为参数。它可能类似于(伪代码):

    struct GtorState {
        char *files[];
        int filesIndex;
        FILE *currentFile;
    };
    
    void gtorInit(GtorState *state, char **files) {
        // loads the array of file into state, set index to 0, and open first file
    }
    
    int nextValue(GtorState *state, double *real, double *imag) {
        // read 2 values from currentFile and affect them to real and imag
        // if eof, close currentFile and open files[++currentIndex]
        // if real and imag were found returns 0, else 1 if eof on last file, 2 if error
    }
    

    那么你的主程序可以包含:

    GtorState state;
    // initialize the list of files to process
    gtorInit(&state, files);
    
    double real, imag);
    int cr;
    while (0 == (cr = nextValue(&state, &real, &imag)) {
        // process (real, imag)
    }
    if (cr == 2) {
        // process (at least display) error
    }
    

    或者,您的主程序可以迭代不同文件的值,并调用具有状态的 函数 与上述生成器类似,用于处理这些值,最后使用处理函数的状态得到结果。

    【讨论】:

      【解决方案3】:

      尝试了一种稍微不同的方法,效果非常好。

      不是每次我想做某事时都从不同的文件中读取,而是将每个文件的全部内容读入一个二维数组 range_phase_data[sample_number][pulse_number],然后根据哪个部分访问数组的不同部分我目前正在处理的范围箱。

      摘录如下:

      #define REAL(z,i) ((z)[2*(i)])
      #define IMAG(z,i) ((z)[2*(i)+1])
      
      for (i=0; i<rx_length; i++){
          printf("\t[%s] Range bin %i. Samples %i to %i.\n", __FUNCTION__, i, 2*i, 2*i+1);
          for (j=0; j<num_pulses; j++){
              REAL(fft_buf, j) = range_phase_data[2*i][j];
              IMAG(fft_buf, j) = range_phase_data[2*i+1][j];
          }
          printf("\t[%s] Range bin %i done, ready to FFT.\n", __FUNCTION__, i);
      
          // do stuff with the data
      }
      

      这减少了动态分配文件指针的需要,而是一次只打开一个文件并将数据写入矩阵中的相应列。

      干杯。

      【讨论】:

        猜你喜欢
        • 2017-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多