所以我的代码应该读取一个文件并打印出读取的内容,同时将其组织成一个数据结构,但是代码在函数完成后就停止运行了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int StudentID;
float ProvaIngresso;
float NotaSecundario;
float NotaCandidatura;
int Escolha1, Escolha2, Escolha3, Escolha4, Escolha5;
char curso1[4], curso2[4], curso3[4], curso4[4], curso5[4];
}Candidato;
void ColocaCandidatos(Candidato *candidatos);
int main() {
Candidato candidatos[60000];
ColocaCandidatos(&candidatos[60000]);
int x = 1;
int y = 2;
int z = x +y;
printf("%d",z);
return 0;
}
void ColocaCandidatos(Candidato *candidatos){
FILE *fp;
char line[100];
char *token;
int line_count = 0;
int i= 0; //token pa controlar numero do candidato;
// Open the CSV file for reading
fp = fopen("Candidatos_N10_C20_O05.csv", "r");
if (fp == NULL) {
printf("Error: could not open file\n");
exit(1);
}
// Read each line of the file and extract the string
while (fgets(line, 100, fp) != NULL) {
if (line_count > 0) { // Skip the first line
token = strtok(line, ",");
candidatos[i].StudentID = atoi(token);
printf("\n%d",candidatos[i].StudentID);
token = strtok(NULL, ",");
candidatos[i].ProvaIngresso = atof(token);
printf("\n%f",candidatos[i].ProvaIngresso);
token = strtok(NULL, ",");
candidatos[i].NotaSecundario = atof(token);
printf("\n%f",candidatos[i].NotaSecundario);
token = strtok(NULL, ",");
candidatos[i].NotaCandidatura = atof(token);
printf("\n%f",candidatos[i].NotaCandidatura);
token = strtok(NULL, ",");
candidatos[i].Escolha1 = atoi(token);
printf("\n%d",candidatos[i].Escolha1);
token = strtok(NULL, ",");
strcpy(candidatos[i].curso1,token);
printf("\n%s",candidatos[i].curso1);
token = strtok(NULL, ",");
candidatos[i].Escolha2 = atoi(token);
printf("\n%d",candidatos[i].Escolha2);
token = strtok(NULL, ",");
strcpy(candidatos[i].curso2,token);
printf("\n%s",candidatos[i].curso2);
token = strtok(NULL, ",");
candidatos[i].Escolha3 = atoi(token);
printf("\n%d",candidatos[i].Escolha3);
token = strtok(NULL, ",");
strcpy(candidatos[i].curso3,token);
printf("\n%s",candidatos[i].curso3);
token = strtok(NULL, ",");
candidatos[i].Escolha4 = atoi(token);
printf("\n%d",candidatos[i].Escolha4);
token = strtok(NULL, ",");
strcpy(candidatos[i].curso4,token);
printf("\n%s",candidatos[i].curso4);
token = strtok(NULL, ",");
candidatos[i].Escolha5 = atoi(token);
printf("\n%d",candidatos[i].Escolha5);
token = strtok(NULL, ",");
strcpy(candidatos[i].curso5,token);
printf("\n%s",candidatos[i].curso5);
i++;
}
line_count++;
}
}
我什至尝试使用测试变量(x,y,z)来尝试找出问题所在,但我无法弄清楚,该程序根本不在函数之后运行男女同校的行,我不明白为什么。
我知道自问这个问题以来我迟到了两天,一些人已经评论了解决方案。如果有人需要,这里只是一个答案和摘要。
所以我复制了你的代码来用调试器检查。我创建了一个具有相同列标题的虚拟文件来进行测试。
问题
这是由 Weather Vane 确定的。您正试图指向数组中不存在的索引。我注意到在将令牌变量分配给列值的行中。您将名为 *restrict __s 的参数设置为 null。
token = strtok(NULL, ",");
解决方案
当它应该指向行变量时,像这样。
token = strtok(line, ",");
简而言之,代码是从 Null 值中读取 a ,并且您试图在转换这些 null 值时将它们分配给数组。因此,对于 Null 值,转换会失败,而 Null 值最终会分配给数组。
这解决了问题。我得到它来打印虚拟文件中的值并打印出最终消息。
这里是代码应该如何寻找你想做的事情。
守则
//The Header library files that the developer was using.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//* So this is a structure that the developer needs to use for his application.
typedef struct
{
int StudentID; // The Student's ID.
float ProvaIngresso; // TryIncome? Sorry I am using google translate.
float NotaSecundario; // Secondary Note.
float NotaCandidatura; // NoteCandidacy.
int Escolha1, Escolha2, Escolha3, Escolha4, Escolha5; // Pick1, Pick2, Pick3, Pick4, Pick5.
char curso1[4], curso2[4], curso3[4], curso4[4], curso5[4]; // Cursor1, Cursor2, Cursor3, Cursor4, Cursor5.
} Candidato;
//* Here he declares a function with no body.
void ColocaCandidatos(Candidato candidatos[]);
//* The main entry point of the application.
int main()
{
Candidato candidatos[100]; // Here the struct object gets declared. 60000 seems a bit excessive?
ColocaCandidatos(candidatos); // Here the method is called.
int x = 1;
int y = 2;
int z = x + y;
printf("%d", z); // I think this is a basic way of checking if the code ran to the end.
return 0; // The application ends here.
}
//* This is the method that reads the file.
void ColocaCandidatos(Candidato candidatos[])
{
// This is where the file handling is done.
FILE *fp; // The FILE variable is declared.
char line[100]; // An array with 101 available entries.
char *token; // A token. The asterisk indicates it will be for a memory cursor variable.
int line_count = 0; // How the user keeps track of what line he is on.
int i = 0; // token pa controlar numero do candidato; // Translation: token to control candidate number
// Open the CSV file for reading.
fp = fopen("Candidatos_N10_C20_O05.csv", "r");
//If the FP variable is null, Then print an error saying the file could not be opened.
if (fp == NULL)
{
printf("Error: could not open file\n"); // This prints the message.
exit(1); // This exits with code 1, Meaning it will report it as an run with error's in the system logs.
}
// Read the lines of the file and extract the string as long as there is data in the file.
while (fgets(line, 100, fp) != NULL)
{
if (line_count > 0) // Skip the first line
{
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
candidatos[i].StudentID = atoi(token); // This converts a string to an Integer and assigns it to Student ID variable of the Candidato structure.
printf("\n%d", candidatos[i].StudentID); // This prints the Student's ID, Take note that its getting the value from the structure object. So it's a way of checking the output.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
candidatos[i].ProvaIngresso = atof(token); // This converts a string to a float number and assign's it to the TryIncome variable.
printf("\n%f", candidatos[i].ProvaIngresso); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
candidatos[i].NotaSecundario = atof(token); // This converts a string to a float number and assign's it to the SecondaryNote variable.
printf("\n%f", candidatos[i].NotaSecundario); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
candidatos[i].NotaCandidatura = atof(token); // This converts a string to a float number and assign's it to the NoteCandidacy variable.
printf("\n%f", candidatos[i].NotaCandidatura); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
candidatos[i].Escolha1 = atoi(token); // This converts a string to a int number and assign's it to the Pick1 variable.
printf("\n%d", candidatos[i].Escolha1); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
strcpy(candidatos[i].curso1, token); // This copies the value and assign's it to the cursor1 variable.
printf("\n%s", candidatos[i].curso1); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
candidatos[i].Escolha2 = atoi(token); // This converts a string to a int number and assign's it to the Pick2 variable.
printf("\n%d", candidatos[i].Escolha2); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
strcpy(candidatos[i].curso2, token); // This converts a string to a float number and assign's it to the cursor2 variable.
printf("\n%s", candidatos[i].curso2); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
candidatos[i].Escolha3 = atoi(token); // This converts a string to a float number and assign's it to the Pick3 variable.
printf("\n%d", candidatos[i].Escolha3); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
strcpy(candidatos[i].curso3, token); // This converts a string to a float number and assign's it to the cursor3 variable.
printf("\n%s", candidatos[i].curso3); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
candidatos[i].Escolha4 = atoi(token); // This converts a string to a float number and assign's it to the pick4 variable.
printf("\n%d", candidatos[i].Escolha4); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
strcpy(candidatos[i].curso4, token); // This converts a string to a float number and assign's it to the cursor4 variable.
printf("\n%s", candidatos[i].curso4); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
candidatos[i].Escolha5 = atoi(token); // This converts a string to a float number and assign's it to the Pick5 variable.
printf("\n%d", candidatos[i].Escolha5); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
token = strtok(line, ","); // This apparently divides strings into tokens seperated by character's.
strcpy(candidatos[i].curso5, token); // This converts a string to a float number and assign's it to the cursor5 variable.
printf("\n%s", candidatos[i].curso5); // This print's the variable's value from the object. It's a way of checking if a value assigned to the struct.
i++; // Increment the loop integer.
}
line_count++; // Increment the line count.
}
fp = fclose(fp); // Close the reader, It's good practice ;).
}
我对代码和注释所做的其他更改
1.我更改了ColocaCandidatos的参数以使用普通对象数组。
2.我在函数结束时关闭阅读器,通常文件会在函数结束时关闭,但这是一个很好的做法。
3.用 60000 的数组大小声明候选对象似乎有点过分,每次运行时都会为数组分配至少 3.3Mb 的内存。
4.如果我有更多时间,我会尝试实现一种更好的方法来为 Candidato 对象分配值,而不是多次调用同一 3 行,但公平地说,并非所有行都是相同的。在尝试将值分配给变量之前,我还会添加一些检查空类型值的东西。