Как назначить последующие столбцы в CSV для массива с помощью strtok в C - PullRequest
0 голосов
/ 19 июня 2019

Я пытаюсь написать простую программу, которая позволит пользователю извлекать данные из файла CSV после указания, какие строки и столбцы они хотели бы извлечь. Программа принимает входные данные для начальной строки (может быть любым числом, не обязательно 1) и желаемой последней строки. Тот же принцип применяется для столбцов. Выходные данные затем присваиваются многомерному массиву, который впоследствии будет передан в функции для вычислений.

У меня проблемы с использованием strtok для извлечения столбца, который не является первым, насколько я понимаю, strtok должен читать файл последовательно?

Я использовал этот проект, чтобы научить себя Си, поэтому у меня было много итераций этого принципа для развития моих знаний. Я успешно прочитал CSV-файлы, поэтому я понимаю основные принципы strtok в CSV-файлах.

Если бы я использовал для чтения первый столбец, то я мог бы просто использовать strtok, как раньше;

var[i][0] = atof(strtok(buf, ","));
var[i][j] = atof(strtok(NULL, ","));

однако для чтения из столбца 2 и далее приведенный выше код все еще должен использоваться, поскольку strtok является последовательным, но не назначает столбец 0 переменной. Единственный грубый метод, который у меня работает, - это ввести временную переменную, поместить в нее все столбцы и извлечь столбцы, указанные в использовании, но это нежелательно.

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

void CSV_Col_read(int r, int c, int start_row, int start_col, float var[r][c])
{

char buf[1024];
float temp[r][c];

  FILE *fp = fopen("PV_Data.csv", "r");

  if(!fp)
  {
    printf("Could Not Open File\n");
  }
  int i = 0;
  int index_row = 0;

  while(fgets(buf, sizeof buf, fp))
  {  
      index_row++;
      if (index_row >= start_row){
      if(i >= r - start_row + 1){
          break;
      }

      if (c == 1){
      var[i][0] = atof(strtok(buf, ","));
  }
      else if(start_col >= 2){
          temp[i][0] = atof(strtok(buf, ","));

      for (int j = 1; j <= c-1; j++)
      {       
      temp[i][j] = atof(strtok(NULL, ","));
      }

      for (int I = -1; I <= 2; I++){

      var[i][I+1] = temp[i][start_col + I];
      }
      }
      else{

              var[i][0] = atof(strtok(buf, ","));

      for (int j = 1; j <= c-1; j++)
      {       
      var[i][j] = atof(strtok(NULL, ","));
      }
  }
  i++;
}
  }
        fclose(fp);
}

void printData(int r, int c, int start_row, int start_col, float var[r][c])
{
if ( c == 1){
for (int i = 1; i <= (r - start_row); i++)
    {
    printf("%f\n", var[i][0]);
    }
}
else{
    for(int i = 0; i <= (r - start_row); i++)
    {
        printf("%f", var[i][0]);


        for(int j = 1; j <= (c - start_col); j++)
        {
            printf("\t");
            printf("%f", var[i][j]);   
    }
    printf("\n");
    }
}
}
int main()
{
    int start_row = 705;
    int start_col = 3;
    int r = 720;
    int c = 5;
    float var[r][c];

    (void) CSV_Col_read(r, c, start_row, start_col, var);

    printData(r, c, start_row, start_col, var);
}

приведенный выше код не является «вставкой правильного слова программирования для доказательства идиота», однако, как я знаю, я только определил оператор elseif () для одного сценария. Является ли этот метод временной переменной подходом или есть более чистый способ приблизиться к этому? Я не прошу код, чтобы исправить это, и я очень доволен ответом, который направляет меня к учебному ресурсу.

Спасибо

1 Ответ

0 голосов
/ 19 июня 2019

Для чего-то простого, где я знаю, что входной файл будет правильно сформирован и без "пустых" значений, тогда я мог бы делать что-то вроде этого:

float values[rows][columns] = { 0 };  // Initialize all to zero

char line[512];  // Hopefully large enough

unsigned r;  // Row index

// Loop to get all rows, taking care to not go out of bounds
for (r = 0; r < rows && fgets(line, sizeof line, fp) != NULL; ++r)
{
    unsigned c = 0;  // Column index

    // Get the first column value
    char *current = strtok(line, ",");

    // Loop to get all columns
    while (c < columns && current != NULL)
    {
        values[r][c] = atof(current);

        ++c;  // Increase to next column
        current = strtok(NULL, ",");  // Get next (if any) column value
    }
}

// Here the whole file will have been read and parsed, and the values
// from the file will be in the array `values`.
...