Обзор проекта: В этом проекте вы будете использовать манипуляции с файлами и строками для реализации набора функций, которые можно использовать для получения статистической информации об упражнении zyBooks. Необработанные оценки упражнения zyBooks хранятся в файле CSV (значения, разделенные запятыми). (Пожалуйста, скачайте array.csv
с Blackboard для примера. Вы можете использовать vim и Microsoft Excel для его просмотра.) Первые два столбца - это всегда фамилия и имя. Остальные столбцы разделены на три категории: участие, вызов и лаборатория. Количество столбцов в файле заранее неизвестно.
Первая строка (или строка) CSV-файла - это заголовок, то есть имена столбцов. Имена для первого и второго столбцов - «Фамилия» и «Имя». Имена для других столбцов имеют следующий формат:
• chapter.section - Participation (points)
• chapter.section - Challenge (points)
• chapter.section - Lab (points)
chapter - номер главы, section - номер раздела, а points - количество баллов (или веса), присвоенных соответствующему разделу. Ниже приведены пять примеров из имени файла array.csv
. Если количество баллов равно 0, соответствующий раздел является необязательным.
• 5.6 - Participation (8)
• 5.14 - Participation (0)
• 5.4 - Challenge (14)
• 5.10 - Challenge (0)
• 5.25 - Lab (10)
Каждая строка после строки заголовка представляет студента, содержащего фамилию, имя и количество баллов. Количество учеников в файле заранее неизвестно. Фамилия и имя не будут пустыми или содержать несколько слов. Каждый балл будет либо пустым (без балла), либо действительным числом от 0 до 100. Пустой балл считается 0 в некоторых вычислениях и игнорируется в других.
Вас просят выполнить следующеепять функций в файле functions.c
, который будет создан.
• double getMin(char csvfile[], char column[]);
Если указан файл CSV, вернуть минимальную оценку указанного столбца. Пустые ячейки исключаются из расчета.
• double getMax(char csvfile[], char column[]);
Если указан файл CSV, вернуть максимальную оценку указанного столбца. Пустые ячейки исключаются из расчета.
• double getAvg(char csvfile[], char column[]);
При наличии CSV-файла возвращать среднюю оценку указанного столбца. Пустые ячейки исключаются из расчета.
• int getCount(char csvfile[], char column[], double threshold);
Учитывая CSV-файл, вернуть количество студентов с указанным ими счетом> = порог. Пустые ячейки исключаются из расчета.
• double getGrade(char csvfile[], char first[], char last[]);
Учитывая файл CSV, вернуть средневзвешенное значение указанного учащегося. Вес каждого столбца указывается в заголовке соответствующего столбца в скобках (точках). Пустая ячейка рассматривается как 0 в расчете.
При реализации вышеуказанных функций вы можете предположить, что csvfile является допустимым CSV-файлом, и его всегда можно открыть для чтения, а параметр столбца представляет собой краткую форму заголовка столбца и начинается с буквы (Pдля участия, C для испытания и L для лабораторной работы), за которым следуют номер главы, точка и номер раздела. Например, P5.6, C5.4 и L5.25 представляют заголовки столбцов 5.6 - Участие, 5.4 - Испытание и 5.25 - Лаборатория соответственно. Вы должны вернуть -2.0 (double) или 2 (integer), если имя соответствующего столбца или имя студента не существует, и -1.0 или 1, если соответствующий столбец является необязательным. Вы также можете предположить, что в каждом столбце есть хотя бы одна непустая оценка. Кроме того, вам разрешено добавлять дополнительные вспомогательные функции в файл functions.c.
Мы рекомендуем использовать функцию fgets
для чтения строки из файла CSV и использовать функцию strsep
извлечь каждое поле из строки. Можно предположить, что каждая строка содержит менее 3000 символов, а каждое поле содержит менее 50 символов. (test_strsep.c включен в Blackboard, чтобы показать способ правильного использования функции strsep без утечки памяти; скомпилируйте ее, используя gcc -Wall -std=gnu99 test_strsep.c
). Вы должны использовать функцию strcasecmp для сравнения двух имен без учета регистра. Чтобы скомпилировать этот проект, используйте следующую команду.
gcc -Wall -std=gnu99 main.c functions.c
functions.c являетсяфайл, который нужно создать, чтобы реализовать необходимые пять функций. main.c содержит функцию main, которая будет принимать команды для пользователя и отправлять их. Вы можете скачать main.c с Blackboard и не вносить никаких изменений в main.c.
// return -2.0 if the column does not exist
double getAvg(char csvfile[], char column[]);
// Given a csv file, return the number of students with their column value >= threshold, excluding blanks
// return -1 if the column is optional
// return -2 if the column does not exist
int getCount(char csvfile[], char column[], double threshold);
// Given a csv file, return the weighted average of the specified student
// A blank cell is viewed as 0 for this function
// return -2.0 if there is no such student.
double getGrade(char csvfile[], char first[], char last[]);
int isValidColumn(char column[])
{
char type;
int chap, sec;
sscanf(column, "%c%d.%d", &type, &chap, &sec);
if (type!='P' && type!='C' && type!='L') return 0;
if (chap<=0 || sec<=0) return 0;
char column2[strlen(column)+1];
sprintf(column2, "%c%d.%d", type, chap, sec);
if (strcmp(column, column2)!=0) return 0;
return 1;
}
void printHelp()
{
printf("\nThe valid commands:\n\n");
printf("\tmin column\n");
printf("\t*** find the minimum of the specified column, excluding blanks\n");
printf("\t*** for example: min P5.6\n");
printf("\tmax column\n");
printf("\t*** find the maximum of the specified column, excluding blanks\n");
printf("\t*** for example: max C5.2\n");
printf("\tavg column\n");
printf("\t*** find the average of the specified column, excluding blanks\n");
printf("\t*** for example: avg L5.26\n");
printf("\tcount column threshold\n");
printf("\t*** find the number of rows with its column value >= threshold, excluding blanks\n");
printf("\t*** for example: count P5.12 60\n");
printf("\tgrade firstname lastname\n");
printf("\t*** find the weighted average of the specified student. A blank cell is viewed as 0\n");
printf("\t*** for example: grade John Smith\n");
printf("\tquit\n");
printf("\t*** quit this program\n");
printf("\thelp\n");
printf("\t*** print this list\n");
}
int main(int argc, char *argv[])
{
if (argc!=2) {
printf("Usage: %s csvfile\n", argv[0]);
return 1;
}
FILE *fp=fopen(argv[1], "r");
if (fp==NULL) {
printf("Unable to open %s for reading\n", argv[1]);
return 2;
}
fclose(fp);
while (1) {
char cmd[30];
char column[30];
char line[300];
printf("\nEnter a command: ");
scanf("%s", cmd);
if (strcmp(cmd, "quit")==0) break;
if (strcmp(cmd, "grade")==0) {
char first[30], last[30];
scanf("%s%s", first, last);
double grade=getGrade(argv[1], first, last);
if (grade>=0)
printf("grade(%s %s)=%g\n", first, last, grade);
else
printf("No student named %s %s\n", first, last);
}
else if (strcmp(cmd, "min")==0) {
scanf("%s", column);
if (isValidColumn(column)) {
double min=getMin(argv[1], column);
if (min>=0.0)
printf("min(%s)=%g\n",column, min);
else if (min==-1.0)
printf("%s is optional\n", column);
else if (min==-2.0)
printf("%s does not exist\n", column);
}
else {
printf("%s: invalid column name\n", column);
printf("A valid column name starts with a letter (P, C or L), followed by a chapter number, a dot, and a section number such as L5.25\n");
fgets(line, 300, stdin); // skip the rest of line
}
}
else if (strcmp(cmd, "max")==0) {
scanf("%s", column);
if (isValidColumn(column)) {
double max=getMax(argv[1], column);
if (max>=0.0)
printf("max(%s)=%g\n", column, max);
else if (max==-1.0)
printf("%s is optional\n", column);
else if (max==-2.0)
printf("%s does not exist\n", column);
}
else {
printf("%s: invalid column name\n", column);
printf("A valid column name starts with a letter (P, C or L), followed by a chapter number, a dot, and a section number such as L5.25\n");
fgets(line, 300, stdin); // skip the rest of line
}
}
else if (strcmp(cmd, "avg")==0) {
scanf("%s", column);
if (isValidColumn(column)) {
double avg=getAvg(argv[1], column);
if (avg>=0.0)
printf("avg(%s)=%g\n", column, avg);
else if (avg==-1.0)
printf("%s is optional\n", column);
else if (avg==-2.0)
printf("%s does not exist\n", column);
}
else {
printf("%s: invalid column name\n", column);
printf("A valid column name starts with a letter (P, C or L), followed by a chapter number, a dot, and a section number such as L5.25\n");
fgets(line, 300, stdin); // skip the rest of line
}
}
else if (strcmp(cmd, "count")==0) {
scanf("%s", column);
if (isValidColumn(column)) {
double threshold;
scanf("%lf", &threshold);
int count=getCount(argv[1], column, threshold);
if (count>=0)
printf("count(%s>=%g)=%d\n", column, threshold, count);
else if (count==-1)
printf("%s is optional\n", column);
else if (count==-2)
printf("%s does not exist\n", column);
}
else {
printf("%s: invalid column name\n", column);
printf("A valid column name starts with a letter (P, C or L), followed by a chapter number, a dot, and a section number such as L5.25\n");
fgets(line, 300, stdin); // skip the rest of line
}
}
else if (strcmp(cmd, "help")==0) {
printHelp();
}
else {
printf("%s: invalid commmand. Enter help for help.\n", cmd);
fgets(line, 300, stdin); // skip the rest of line
}
}
return 0;
}
Файл данных-
Фамилия, Имя, 5.1 - Участие (11),5.2 - Участие (20), 5.3 - Участие (3), 5.4 - Участие (9), 5.5 - Участие (5), 5.6 - Участие (8), 5.7 - Участие (9), 5.8 - Участие (4), 5.9- Участие (5), 5.10 - Участие (13), 5.11 - Участие (21), 5.12 - Участие (7), 5.13 - Участие (3), 5.14 - Участие (0), 5.15 - Участие (0), 5.1 -Задача (0), 5.2 - Задача (9), 5.3 - Задача (0), 5.4 - Задача (14), 5.5 - Задача (2), 5.6 - Задача (0), 5.7 - Задача (8), 5.8 - Задача(0), 5.9 - Задача (2), 5.10 - Задача (0), 5.11 - Задача (0), 5.12 - Задача (0), 5.13 - Задача (0), 5.14 - Задача (0), 5.15 - Задача (0), 5,21 - лаборатория (10), 5,23 - лаборатория (10), 5,25 - лаборатория (10), 5,26 - лаборатория (10), 5,27 - лаборатория (10)
Агилар, Мария, 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100, N/ А, N / A, N / A, 100, N/ A, 100 100, N / A, 100, N / A, 100, N / A, N / A, N / A, N / A, N / A, N / A, 100 100 100 100 100
Альварез,Абель, 100.100.100.100.100.100.100.100.100.100.100.100.100, N / A, N / A, N / A, 100, N / A, 100100, N / A, 100, N / A, 100, N / A, N / A, N / A, Н /A, N / A, N / A, 100, 100, 100, 100, 100
Андерсен, Рональд, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, N / A, N / A, N / A, 100, N / A, 100, 100, N / A, 0, N/ A, 100, N / A, N / A, N / A, N / A, N / A, N / A ,,,,, Arias, Emory, 100,100,100,100,100,100,100,100,100,100,100,100,100, N / A, N / A, N / A, 100, N / A, 100100, N / A, 100, N / A, 100, N / A, N / A, N / A, N / A, N / A, N / A, 100,100,100,100,100