我试图将我的输入值分为两个不同的类别。第一个数组调用“工作组名称”将保存团队名称,而第二个数组将保存该周的得分。我的输入文件是.csv,代码的方式是,所有内容都存储在字符串中,而不是两个单独的变量。另外,我也不懂编程,我只熟悉这个库。
#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;
}我应该说,输入文件有第一列有团队名称,第二列有团队分数。任何帮助都会很好。谢谢!下面是一个示例输入文件
发布于 2015-11-17 22:23:42
除了将&teamname更改为teamname之外,您还可能需要考虑其他几个问题。首先,始终初始化变量。虽然不是必要的,但这有一些积极的好处。对于数值数组,它初始化所有防止意外从未初始化值读取的元素。对于字符数组,初始化到0可以确保字符串的第一次复制(小于总长度)将是null-terminated,并防止尝试从未初始化的值读取。这只是个好习惯:
double teamscore[MAXS] = {0.0};
char teamname[30] = {0};
int n = 0;您已经为您的filein_ptr和fileout_ptr定义了默认值,您也可以对您的数组大小进行相同的操作。如果数组大小需要更改,则提供一个要更新的值,从而使代码更易于维护。
接下来,这是一个相当重要的nit,但是一个重要的nit。main接受参数,由标准定义为int argc, char **argv (您可能还会看到Unix系统上的char **envp,您可能认为它们都是以等效形式char *argv[]和char *envp[]编写的)。这里的重点是使用它们为您的程序获取参数,这样您就不会只使用硬编码的data.csv和matrix.csv文件名。您可以使用硬编码的值,还可以通过使用简单的ternary运算符(例如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 > 1 (意味着至少有一个由用户提供的参数),如果真代码open (argv[1], "r") (打开作为读取参数的文件名),如果假代码fopen (FILEIN, "r")打开默认的文件名,如果没有给定的文件名。输出文件也是如此。(你必须按正确的顺序提供)。
然后,如果打开文件,则必须在尝试读取文件之前验证文件是否已打开。虽然您可以分别测试输入和输出,以判断哪一个失败了,但您也可以使用一个简单的||条件来检查是否打开失败:
if (!filein_ptr || ! fileout_ptr) {
fprintf (stderr, "error: filein of fileout open failed.\n");
return 1;
}最后,如果您知道需要读取的数据行数,则可以使用索引的for循环,但是您很少知道数据文件中的行数。即使使用for循环,仍然需要检查fscanf的返回,以验证实际有2个有效的转换(因此得到了预期的2个值)。检查回报也提供了另一个好处。它允许您继续阅读,直到您不再从fscanf获得2个有效的转换。这为从文件中读取未知数量的值提供了一种简单的方法。但是,您确实需要确保不尝试将更多的值读入数组中。例如:
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;
}
}注意:当使用包含字符大小写的格式说明符(如"%[^,], ...")时,请注意,它将在字符串转换中读取并包括前导空格和尾随空格。因此,如果您的文件有' Steelers ,..',teamname将包含空格。您可以通过在开始转换之前包括一个空格(如" %29[^,], ...")来修复前导空格,还可以通过指定最大字段宽度来限制可以读取的字符数。(在这种情况下,后面的空格在读取后会更容易修剪)
将所有的代码组合在一起,您可以通过接受用户的参数并验证您的文件和读取操作,使您的代码更加灵活和可靠:
#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注意:值之间的前导空格和空格的变化是有意的。
使用/输出
$ ./bin/teams ../dat/teams.txt teamsout.txt
$ cat teamsout.txt
Steelers 20.000000
Patriots 25.000000
Raiders 15.000000
Chiefs 35.000000如果你还有其他问题,请告诉我。
发布于 2015-11-17 19:43:02
如果要将团队名称存储在数组中,则应该声明一个二维数组:
char team_names[N_OF_TEAMS][MAX_CHAR_IN_NAME];然后,为分数声明数组。你用双打来存储分数,不是只有整数吗?
double scores[N_OF_TEAMS];要读取这些值,可以使用:
int read_name_and_score( char * fname, int m, char nn[][MAX_CHAR_IN_NAME], double * ss)
{
FILE *pf;
int count = 0;
if (!fname) {
prinf("Error, no file name.\n");
return -1;
}
pf = fopen(fname,'r');
if (!pf) {
printf("An error occurred while opening file %s.\n",fname);
return -2;
}
while ( count < m && fscanf(pf, "%[^,],%d\n", nn[count], &ss[count]) == 2 ) count++;
if (!fclose(pf)) {
printf("An error occurred while closing file %s.\n",fname);
};
return count;
}如果需要^,以便在找到a时停止扫描字符串,主要内容将如下所示:
#define N_OF_TEAMS 32
#define MAX_CHAR_IN_NAME 30
int main(void) {
char team_names[N_OF_TEAMS][MAX_CHAR_IN_NAME];
double scores[N_OF_TEAMS];
int n;
n = read_name_and_score("data.csv",N_OF_TEAMS,team_names,scores);
if ( n != N_OF_TEAMS) {
printf("Error, not enough data was read.\n");
/* It's up to you to decide what to do now */
}
/* do whatever you want with data */
return 0;
}https://stackoverflow.com/questions/33761409
复制相似问题