简体   繁体   English

使用 C 在多个 CSV 文件之间读取、转换和写入数据

[英]Reading, translating and writing data between multiple CSV files using C

I have 3 CSV files.我有 3 个 CSV 文件。 The first of them contains 4 columns:其中第一个包含 4 列:

ID,Section1,Section2,Secion3
1,23,12,7
2,11,26,9
. . . .
. . . .
19,30,22,4
20,5,6,16

The first column is the ID and the other three contain random numbers ranging from 0 to 30.第一列是 ID,其他三列包含从 0 到 30 的随机数。
The next file is a "conversion" file.下一个文件是“转换”文件。 It shows the corresponding value to each number:它显示了每个数字的对应值:

30,45,44,45
29,44,42,43
28,43,42,41
. . . .
. . . .
1,22,21,22
0,20,21,21

The first column is the number to be read and the next columns are the values that will replace those numbers in each Section.第一列是要读取的数字,接下来的列是将替换每个部分中的这些数字的值。
Like, if you read a 30 in Section1 it will be replaced by a 45, and if you find a 29 in Section 2 it will be replaced by a 42 and so on.例如,如果您在第 1 节中读到 30,它将被 45 替换,如果您在第 2 节中找到 29,它将被 42 替换,依此类推。
If I were to write the converted numbers into a third CSV file with the same 4 column format, how should I do it?如果我要将转换后的数字写入具有相同 4 列格式的第三个 CSV 文件,我应该怎么做?
So far I've had no problems with generating the files since they are randomized, except for the "conversion" file, but I don't know how to proceed with the conversion.到目前为止,由于它们是随机的,除了“转换”文件之外,我在生成文件方面没有任何问题,但我不知道如何进行转换。

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

int main (int argc,char *argv[]){
    int i, num1;
    char numbers[20][20];
    char conversions[20][20];

    //File with the initial numbers
    FILE *registry = fopen("registry.csv","w+");
    if (registry == NULL){
        fputs ("File error",stderr); 
        exit (1);
    }
    //Conversion file
    FILE *conversion = fopen("conversion.csv","r");
    if (conversion == NULL){
        fputs ("File error",stderr); 
        exit (1);
    }
    //File where the resulting values will be written
    FILE *results = fopen("results.csv","a");
    if (results == NULL){
        fputs ("File error",stderr); 
        exit (1);
    }

    //Writing the headers
    fprintf(results,"ID,Results1,Results2,Results3\n");
    fprintf(registry,"ID,Section1,Section2,Section3\n");
    srand(time(0));

    //Generating the random numbers
    for(i=1;i<21;i++){
        sprintf(numbers[i],"%d,%d,%d,%d\n",i,rand()%31,rand()%31,
            rand()%31);
        fputs(numbers[i], registry);
    }

    //This is where I don't know how to proceed

    for(i=1;i<21;i++){
        sprintf(conversions[i],"%d,%d,%d,%d\n",i,
            fscanf(registry,"%d,%*s,%*s,%*s\n",num1)...);


    }

I was trying to do something like what I did to generate the random numbers by saving everything into a buffer and then writing it into the file and I found that the fscanf function can be of great use to skip the parts I don't need to read, but I couldn't figure out how to use it to skip the headers and the ID column and I'm still missing the conversion part.我试图通过将所有内容保存到缓冲区然后将其写入文件来执行类似于生成随机数的操作,我发现 fscanf function 可以很好地跳过我不需要的部分阅读,但我不知道如何使用它来跳过标题和 ID 列,我仍然缺少转换部分。
Conversion file:转换文件:

30,45,44,45
29,44,43,43
28,43,42,42
27,43,41,40
26,41,40,40
25,40,39,39
24,39,37,39
23,38,37,38
22,38,36,37
21,36,36,37
20,35,35,36
19,34,34,35
18,33,34,35
17,33,33,34
16,32,32,33
15,32,31,32
14,31,30,31
13,30,30,31
12,29,29,30
11,29,28,29
10,28,28,29
9,28,27,27
8,27,26,26
7,27,26,25
6,26,25,25
5,25,24,24
4,25,23,24
3,24,23,23
2,23,22,21
1,21,21,20
0,20,21,20

This answer is scoped to address:这个答案的范围是解决:
//This is where I don't know how to proceed . //This is where I don't know how to proceed

To do what you have described, if it is not necessary to include the first columns in registry, results or conversion for storing, then do not.要执行您所描述的操作,如果不需要在注册表、结果或转换中包含第一列以进行存储,则不要。 Although nice for human readability, they complicate the task of reading in, and using arrays.尽管对人类可读性很好,但它们使读取和使用 arrays 的任务复杂化。 The unused column data and header row requires array indexing gymnastics to get the data to line up correctly into the arrays.未使用的列数据和 header 行需要数组索引体操才能使数据正确排列到 arrays 中。 Without the header row and numbering column, array indexes alone are sufficient to track all that is needed to make the conversion.如果没有 header 行和编号列,仅数组索引就足以跟踪进行转换所需的所有内容。
However , if you feel the first column/row is needed for your purposes, then adjust the array indexing of the routines shown below to accommodate.但是,如果您觉得需要第一列/行来满足您的目的,则调整下面显示的例程的数组索引以适应。

The following steps (some of which you already do) are what I identified as essential toward making the conversion step as simple as possible...以下步骤(其中一些您已经完成)是我认为对使转换步骤尽可能简单至关重要的步骤......

Steps:脚步:

  • Create registry - 60 - random numbers (0-30) arranged in 20 rows, 3 data columns创建注册表 - 60 - 随机数 (0-30) 排列成 20 行,3 个数据列

  • Create int reg[20][3] = {{0}};创建int reg[20][3] = {{0}};

  • Read registry into reg array using a combination fgets sscanf routine.使用组合fgets sscanf例程将注册表读入 reg 数组。

Example:(assuming registry has already been created in your code)示例:(假设您的代码中已经创建了注册表)

registry = fopen(".\\registry.csv","r");
if (registry)
{
    while(fgets(buf, sizeof(buf), registry))
    {
        sscanf(buf, "%d,%d,%d", &reg[index][0],&reg[index][1],&reg[index][2] );
        index++;
    }
    fclose(registry);
}

conversion table - pre-existing file转换表 - 预先存在的文件

  • Create int conv[31][3] = {{0}};创建int conv[31][3] = {{0}};

  • Read conversion table into conv array using a combination fgets sscanf routine (see above example)使用组合fgets sscanf例程将转换表读入 conv 数组(参见上面的示例)

Once you have these arrays created properly,正确创建这些 arrays 后,
Perform conversion:执行转换:

  • Create int res[20][3] = {{0}};创建int res[20][3] = {{0}};

  • Create char buf[80] = {0};创建char buf[80] = {0};

  • Open 'results' file: FILE *results = fopen(".\\results.csv","w");打开“结果”文件: FILE *results = fopen(".\\results.csv","w");
  • populate results:填充结果:

Example:例子:

//File where the resulting values will be written
FILE *results = fopen(".\\results.csv","w");
if (results)
{
    for(i=0;i<sizeof(reg)/sizeof(reg[0]);i++)
    {
        for(j=0;j<sizeof(reg[0])/sizeof(reg[0][0]);j++)
        {
            res[i][j] = conv[reg[i][j]][j];
        //      |                         |  |___reg col   == conv col
        //      |                         |______value reg == conv row
        //      |________________________________row and column of conv
        }
        sprintf(buf, "%d,%d,%d\n", res[i][0],res[i][1],res[i][2]);
        fputs(buf, results);

    }
    fclose(results);    
}

At this point, you can print the results file in a format that suits your needs.此时,您可以以适合您需要的格式打印结果文件。

Following is an image showing actual results using suggested approaches above for a randomly generated registry , the values you provided for conversion and resulting results .下图显示了使用上述建议方法对随机生成的registry的实际结果、您为conversion提供的值和results (each created without column 1 shown in your original code, as I suggested in my comments.) Image is showing indexing from 0 - n for each set of array data: (正如我在评论中所建议的那样,每个创建都没有在原始代码中显示第 1 列。)图像显示每组数组数据的索引从 0 到 n:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM