该程序应该获取包含学生测验成绩的文本文件,并将其写入包含学生姓名的另一个文件中,并为学生分配成绩
#include <stdio.h>
#include <stdlib.h>
void format(FILE *outputFile);
void copyNames(FILE *inputFile, FILE *outputFile);
void copyScores(FILE *inputFile, FILE *outputFile);
int main(int arc, char* argv[])
{
FILE *inputScores, *averageScores;
inputScores = fopen("quiz.txt", "r");
averageScores = fopen("average.txt", "w");
if (inputScores == NULL || averageScores == NULL)
{
printf("ERROR: The file(s) could not be opened!");
return(1);
}
copyNames(inputScores, averageScores);
copyScores(inputScores, averageScores);
fclose(inputScores);
fclose(averageScores);
return 0;
}
void copyNames(FILE *inputFile, FILE *outputFile){
char firstName[10], lastName[10], ch;
ch = fgetc(inputFile); //sets ch to a place in the file
fseek(inputFile, 0, SEEK_SET); //resets ch so it is at the beginning of the file
while (ch != EOF){
int i = 0, j = 0; //resets values in the array so you can overwrite it
for (ch = fgetc(inputFile); ch != ' ' && ch != EOF; ch = fgetc(inputFile)){ //gets the first name and puts it into an array
firstName[i] = ch;
i++;
}
for (ch = fgetc(inputFile); ch != ' ' && ch != EOF; ch = fgetc(inputFile)){ //gets last name and puts it into array
lastName[j] = ch;
j++;
}
lastName[j] = '\0'; //truncates the arrays
firstName[i] = '\0';
while (ch != '\n' && ch != EOF){ //moves the placement of ch to avoid all the grades to get the next name
ch = fgetc(inputFile);
}
fprintf(outputFile, "%s, %s \n", lastName, firstName); //prints the names to the output file
}
}
void copyScores(FILE *inputFile, FILE *outputFile){
fseek(inputFile, 0, SEEK_SET); //resets fgetc again
char lineMemory[60], sc = fgetc(inputFile);
while (sc != EOF){
int i = 0, num = 0, scores[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (sc = fgetc(inputFile); sc != '\n' && sc != EOF; sc = fgetc(inputFile)){ //writes the whole line into an array
lineMemory[i] = sc;
i++;
}
lineMemory[i] = '\0'; //truncates the array
for (int check = 0; lineMemory[check] != '\0'; check++){ //walks through the string
if (isdigit(lineMemory[check]) != 0){ //looks for the digits in the string
int j = lineMemory[check] - '0'; //turns the characters into integers
scores[num] = j; //puts the integer into the array
num++;
}
}
float avg, total = 0;
for (int indx = 0; indx < 10; indx++){
total += scores[indx];
}
avg = total / 10; //finds average of the grades
for (int x = 0; x < 10; x++){
fprintf(outputFile, "%2d", scores[x]); //prints the quiz grades
}
fprintf(outputFile, "%10g\n", avg); //prints the average
}
}
void copyAll(FILE *inputFile, FILE *outputFile){
char ch = fgetc(inputFile);
while (ch != EOF){
ch = fgetc(inputFile);
fputc(ch, outputFile);
}
printf("Data successfully written.\n");
}
结果应该是这样的:
Alex Smith 98 100 90 82 92.5
john Adams 100 90 82 90 90.5
//92.5 and 90.5 being the average.
但是我的代码只显示了名称,并在名称下方显示了等级。喜欢:
Alex Smith
john adams
98 100 90
100 90 82 etc...
答案 0 :(得分:2)
您的代码中存在多个问题:
fgetc()
返回一个int
,请勿将其分配给char
,否则您将无法可靠地检测到EOF
。您多次致电fgetc()
。您应该结合使用阅读和测试习惯用语:
void copyAll(FILE *inputFile, FILE *outputFile){
int ch ;
while ((ch = fgetc(inputFile)) != EOF) {
fputc(ch, outputFile);
}
printf("Data successfully written.\n");
}
您永远不会检查潜在的缓冲区溢出:无效的输入将导致未定义的行为。
copyScores
中将分数转换为数字的代码是错误的:它只能处理一位数的分数。"%2d"
输出分数,不会将大于9
的分数分开。请改用" %d"
。num
分,但始终输出10分及其平均值。fseek(inputFile, 0, SEEK_SET);
毫无用处。只有在更新模式下打开的流才需要使用它们,要正确使用它们非常棘手。这是一个简单得多的版本:
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *input, *output;
char firstname[50], lastname[50];
int score, n, total;
input = fopen("quiz.txt", "r");
output = fopen("average.txt", "w");
if (input == NULL || output == NULL) {
printf("ERROR: The file(s) could not be opened!");
return 1;
}
while (fscanf(input, "%49s%49s", firstname, lastname) == 2) {
fprintf(output, "%s %s", firstname, lastname);
for (n = 0, total = 0; fscanf(input, "%d", &score) == 1; n++) {
fprintf(output, " %d", score);
total += score;
}
fprintf(output, " %.2f\n", n == 0 ? 0.0 : (double)total / n);
}
fclose(input);
fclose(output);
return 0;
}