从csv文件阅读并分离成变量 [英] Read from csv file and separate into variable

查看:119
本文介绍了从csv文件阅读并分离成变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我的输入值分成2不同的类别。第一个数组调用teamname就拿着球队的名称和第二个数组将举行该周的分数。我输入文件.csv格式与code的方式,它是一切都存储在一个字符串,而不是2个独立的变量。另外我不是编程悟性和我只熟悉库。

I'm trying to separate my input values into 2 different categories. The first array call teamname would hold the the team names and the second array would hold the score for that week. My input file is .csv with the code the way it is everything is stored in the as a string instead of 2 separate variables. Also I'm not to program savvy and am only familiar with the library.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

#define FILEIN "data.csv"
#define FILEOUT "matrix.csv"

int main (void)
{
    double nfl[32][32], teamscore[32];
    char teamname[30];
    int n;
    FILE *filein_ptr;
    FILE *fileout_ptr;

    filein_ptr = fopen (FILEIN, "r");
    fileout_ptr = fopen (FILEOUT, "w");

    for (n = 1; n <= 32; n++) {
        fscanf (filein_ptr, "%s  %lf\n", &teamname, &teamscore[n]);
        fprintf (fileout_ptr, "%s    %f\n", teamname, teamscore);
    }

    fclose (filein_ptr);
    fclose (fileout_ptr);

    return 0;
}

我应该说,输入文件与球队的名字第一列和团体总分第二列。任何帮助将是巨大的。谢谢!
下面是一个示例输入文件

I should say that the input file has the first column with team names and the second column with team scores. Any help would be great. Thanks! Here is a sample input file


  • 钢人队,20

  • 爱国者,25

  • 攻略,15

  • 局长,35

推荐答案

除了修改&放大器; teamname teamname ,有可能要看看一些其他的考虑。第一个是,总是初始化变量。虽然不是必需的,这有许多积极益处。对于数值数组,它初始化所有元素preventing从初始化值读取一个偶然的。对于字符数组,初始化为 0 确保了第一个副本的字符串(小于总长度)将空值终止,也prevents企图从初始化值读取。这只是良好的习惯:

In addition to changing &teamname to teamname, there are a few other considerations you may want to look at. The first being, always initialize your variables. While not required, this has a number of positive benefits. For numerical arrays, it initializes all elements preventing an accidental read from an uninitialized value. For character arrays, initializing to 0 insures that the first copy to the string (less than the total length) will be null-terminated and also prevents an attempted read from an uninitialized value. It's just good habit:

    double teamscore[MAXS] = {0.0};
    char teamname[30] = {0};
    int n = 0;

您已经为定义的默认值的 filein_ptr fileout_ptr ,你可以做你的数组的大小是一样的。这使得你的code更容易维护通过提供一个单一的数值来更新,如果你的数组的大小需求的变化。

You have defined default values for your filein_ptr and fileout_ptr, you can do the same for your array sizes. That makes your code easier to maintain by providing a single value to update if your array size needs change.

其次,这是一个相当挑剔的,但一个重要的挑剔。 接受参数,通过标准定义为 INT ARGC,字符** argv的(你也可以看到的char ** envp Unix系统上,你可能看起来他们俩写成等价形式的char * argv的[] 的char * envp [] )。这里的关键是使用它们这样你就不会只有你的硬盘codeD data.csv 矩阵坚持把论据程序的.csv 文件名。您可以使用您的硬盘codeD值,还提供了用户通过使用简单的三元经营者进入他所选择的文件名的能力(如测试,如果真code:如果为假code; ):

Next, and this is rather a nit, but an important nit. main accept arguments, defined by standard as int argc, char **argv (you may also see an char **envp on Unix systems, you may seem them both written in equivalent form char *argv[] and char *envp[]). The point here is to use them to take arguments for your program so you are not stuck with just your hardcoded data.csv and matrix.csv filenames. You can use your hardcoded values and still provided the user the ability to enter filenames of his choice by using a simple ternary operator (e.g. test ? if true code : if false code;):

    FILE *filein_ptr = argc > 1 ? fopen (argv[1], "r") : fopen (FILEIN, "r");
    FILE *fileout_ptr = argc > 2 ? fopen (argv[2], "w") : fopen (FILEOUT, "w");

在那里,的测试 ARGC&GT; 1 (意思是有用户给出至少有一个参数)的如果属实code 打开(的argv [1],R )(打开给出读取参数文件名,而如有虚假code 的fopen(FILEIN,R)打开默认如果没有文件名给。这同样适用于输出文件的事实。(你必须为他们提供正确的顺序)。

There, the test argc > 1 (meaning there is at least one argument given by the user), if true code open (argv[1], "r") (open the filename given as the argument for reading, and if false code fopen (FILEIN, "r") open your default if not filename given. The same holds true for your output file. (you must provide them in the correct order).

然后,如果你的打开的文件,您必须验证该文件实际上是开放的尝试从中读取之前。虽然你可以测试输入和输出分别告诉哪一个失败了,你也可以使用一个简单的 || 状态检查,如果任一打开失败:

Then if you open a file, you must validate that the file is actually open before you attempt to read from it. While you can test the input and output separately to tell which one failed, you can also use a simple || condition to check if either open failed:

    if (!filein_ptr || ! fileout_ptr) {
        fprintf (stderr, "error: filein of fileout open failed.\n");
        return 1;
    }

最后,如果你知道你需要为你细阅读,一个索引循环的数据行数,但你很少会知道的数线在手前的数据文件。即使使用循环,你仍然需要检查的fscanf 返回来验证你实际上有2个有效转换(并因此得到了2个值您所期望)。检查返回还提供了另一个好处。它可以让你继续读书,直到你不再获得的fscanf 2的有效转换。这提供了一种简单的方法来从文件中读取一个未知的数目的值。但是,你需要确保你不尝试多看看值到阵列比他们将举行。例如:

Lastly, if you know the number of lines of data you need to read, an indexed for loop as you have is fine, but you will rarely know the number of lines in a data file before hand. Even if using a for loop, you still need to check the return of fscanf to verify that you actually had 2 valid conversion (and therefore got 2 values you were expecting). Checking the return also provides another benefit. It allows you to continue reading until you no longer get 2 valid conversions from fscanf. This provides an easy way to read an unknown number of values from a file. However, you do need to insure you do not try and read more values into your array than they will hold. e.g.:

    while (fscanf (filein_ptr, " %29[^,],%lf", teamname, &teamscore[n]) == 2) {
        fprintf (fileout_ptr, "%s    %f\n", teamname, teamscore[n++]);
        if (n == MAXS) {  /* check data doesn't exceed MAXS */
            fprintf (stderr, "warning: data exceeds MAXS.\n");
            break;
        }
    }

注意:使用一个包含字符大小写格式说明时(如%[^,],...),要知道它会读取,包括领导,并在转换为字符串结尾的空格。所以,如果你的文件有'钢人队,.. teamname 将包括空格。您可以通过包括转换开始前一个空格修复前导空格(如%29 [^],...),并也限制数量可以通过指定的最大场宽度被读取的字符。 (在的情况下尾随空格会读取后更容易修剪)

note: when using a format specifier that contains a character case (like "%[^,], ..."), be aware it will read and include leading and trailing whitespace in the conversion to string. So if your file has ' Steelers ,..', teamname will include the whitespace. You can fix the leading whitespace by including a space before the start of the conversion (like " %29[^,], ...") and also limit the number of characters that can be read by specifying a maximum field width. (a trailing whitespace in the case would be easier trimmed after the read)

把所有的拼在一起,你可以让你的code更加灵活和可靠的通过从用户参数,并验证您的文件和读取操作:

Putting all the pieces together, you could make your code more flexible and reliable by taking arguments from the user, and validating your file and read operations:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

#define FILEIN "data.csv"
#define FILEOUT "matrix.csv"
#define MAXS 32

int main (int argc, char **argv)
{
    /* double nfl[MAXS][MAXS] = {{0}}; */
    double teamscore[MAXS] = {0.0};
    char teamname[30] = {0};
    int n = 0;
    FILE *filein_ptr = argc > 1 ? fopen (argv[1], "r") : fopen (FILEIN, "r");
    FILE *fileout_ptr = argc > 2 ? fopen (argv[2], "w") : fopen (FILEOUT, "w");

    if (!filein_ptr || ! fileout_ptr) {
        fprintf (stderr, "error: filein of fileout open failed.\n");
        return 1;
    }

    while (fscanf (filein_ptr, " %29[^,],%lf", teamname, &teamscore[n]) == 2) {
        fprintf (fileout_ptr, "%s    %f\n", teamname, teamscore[n++]);
        if (n == MAXS) {  /* check data doesn't exceed MAXS */
            fprintf (stderr, "warning: data exceeds MAXS.\n");
            break;
        }
    }

    fclose (filein_ptr);
    fclose (fileout_ptr);

    return 0;
}

测试输入

$ cat ../dat/teams.txt
Steelers,   20
Patriots,25
    Raiders,    15
    Chiefs,35

注意:的领导空白和空白值之间的差异是故意的。

note: the variations in leading whitespace and whitespace between values was intentional.

使用/输出

$ ./bin/teams ../dat/teams.txt teamsout.txt

$ cat teamsout.txt
Steelers    20.000000
Patriots    25.000000
Raiders    15.000000
Chiefs    35.000000

让我知道,如果您还有其他问题。

Let me know if you have further questions.

这篇关于从csv文件阅读并分离成变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆