main() 中的 fprintf 由 Grade() 函数中的子分支运行,而子级始终在函数内退出

问题描述 投票:0回答:1

我的教授希望我创建一个程序,自动为她的班级编译和评分学生作业。我知道已经有比这更充实的开源项目,但我决定编写这个代码是为了好玩。添加计时器以使学生程序不会永远继续后,.csv 文档的输出变得很奇怪。它重新打印了标题以及已经评分的学生 ID/年级

这是代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define MAX_COMMAND_LENGTH 1000
#define LOG_FILE_PATH "error_log.txt"




void logError(char* message, char* studentid, char* assignmentid, char* weekid) {
    FILE* logFile = fopen(LOG_FILE_PATH, "a");
    if (logFile) {
        fprintf(logFile, "Error: %s %s %s %s\n", message, studentid, weekid, assignmentid);
        fclose(logFile);
    }
}

void timeoutHandler(int signum) {
    //this function is called when the timeout occurs
    //logError("Execution timed out.");
    exit(1);
}

int grade(char* studentid, char* assignmentid, int questionCount, char* weekid) {
    //define paths
    char c_program_path[32];
    char input_file_path[32];
    char answer_file_path[32];
    char compile_command[MAX_COMMAND_LENGTH];
    sprintf(c_program_path, "%s/%s/%s_%s.c", weekid, studentid, studentid, assignmentid);
    sprintf(compile_command, "gcc %s -o compiled_program.out", c_program_path);

    //set up a timeout handler using the alarm function
    signal(SIGALRM, timeoutHandler);


        //Fork for grading
        pid_t child_pid = fork();

        if (child_pid == -1) {
            perror("fork");
            return 1;
        }
        if (child_pid == 0) { //this code runs in the child process
            // set a timer for the timeout duration
            //compile Program
            //printf("\n1--1\n");

            if (system(compile_command) != 0) {
                printf("Compilation successful.\n");
                exit(5);
            } 

            alarm(2);
            for (int i = 0; i < questionCount; i++){
                //define input and answer paths
                sprintf(input_file_path, "%s/input%d.txt\0", weekid, i);
                sprintf(answer_file_path, "%s/answer%d.txt\0", weekid, i);
                //open files
                FILE* input_file = fopen(input_file_path, "r");
                FILE* answer_file = fopen(answer_file_path, "r");
                if (!input_file) {
                    exit(4);
                }
                if (!answer_file) {
                    exit(4);
                }



                //execute the compiled program using input redirection

                //define variables for program execution
                char compiled_program_path[MAX_COMMAND_LENGTH];
                snprintf(compiled_program_path, sizeof(compiled_program_path), "%s", "./compiled_program.out");

                char execution_command[MAX_COMMAND_LENGTH];
                snprintf(execution_command, sizeof(execution_command), "%s < %s", compiled_program_path, input_file_path);
                //execute program
                FILE* program_output = popen(execution_command, "r");
                if (!program_output) {
                    exit(3);
                }
                //compare output to answer
                char bufferAnswer[128];
                char bufferOutput[128];
                
                while (fgets(bufferAnswer, sizeof(bufferAnswer), answer_file)) {
                
                    if (fgets(bufferOutput, sizeof(bufferOutput), program_output) == NULL) {

                        exit(2);
                    }

                    for (int j = 0; j < strlen(bufferAnswer)-2; j++){
                        if (bufferOutput[j] != bufferAnswer[j]){


                            exit(2);
                        }


                        
                    }


                }
                //printf("\ntest\n");
                // close files and cleanup
                fclose(input_file);
                fclose(answer_file);
                pclose(program_output);

            }


            // clean up by removing the compiled program
            remove("compiled_program.out");
            printf("Execution successful.\n");
            // cancel the timeout
            alarm(0);
            exit(0);
        }else{
            // wait for the child process to complete
            int status;
            waitpid(child_pid, &status, 0);

            // check grade

            int exit_status = WEXITSTATUS(status);
            if (exit_status == 5){
                logError("Compilation failed.", studentid, assignmentid, weekid);
            }else if (exit_status == 0) {
                // The child process exited successfully
                printf("Child process completed successfully.\n");
                return 0;
            } else if (exit_status == 1) {
                remove("compiled_program.out");
                logError("Child process timed out.", studentid, assignmentid, weekid);
            } else if (exit_status == 2) {
                remove("compiled_program.out");
                logError("Incorrect output.", studentid, assignmentid, weekid);
            }else if (exit_status == 3){
                remove("compiled_program.out");
                logError("Error executing the compiled program.", studentid, assignmentid, weekid);
            }else if (exit_status == 4){
                remove("compiled_program.out");
                logError("Error opening files.", studentid, assignmentid, weekid);
            }else{
                remove("compiled_program.out");
                logError("Unknown error.", studentid, assignmentid, weekid);
            }

            return 1;


        }
        

    
}

int main(){
    //define students, week, assignment, question count, grading file
    char gradesPath[32] = {"gradestest.csv"};
    char* studentid[4] = {"std1\0", "std2\0", "std3\0", "std4\0"};
    
    char* assignmentid[1] = {"test\0"};
    char* weekid = "test\0";
    int questionCount = 2;
    //open grading file
    FILE* gradesFile = fopen(gradesPath, "w");
    if (!gradesFile) {
        printf("error opening gradesFile");
        return 1;
    }
    //write header

    printf("writing header\n");
    fprintf(gradesFile, "StudentID,");

    for (int i = 0; i < 1; i++){
        fprintf(gradesFile, "%s,", assignmentid[i]);
    }
    //fprintf(gradesFile, "\n");
    printf("grading\n");
    //grade each student
    
    for (int i = 0; i < 4; i++){
        printf("grading %s\n", studentid[i]);
        fprintf(gradesFile, "\n%s,", studentid[i]);
        for (int j = 0; j < 1; j++){
            
            
            if (grade(studentid[i], assignmentid[j], questionCount, weekid)){
                fprintf(gradesFile, "0,");
            
            }else{
                fprintf(gradesFile, "1,");
            }
        }
    }        
    fprintf(gradesFile, "\n");

    //close files and cleanup
    fclose(gradesFile);
    printf("fin\n");
    return 0;
}

老实说,我不知道为什么会发生这种情况……孩子甚至不应该打印标题。我想知道 fprintf 是否有问题,但这似乎也不太可能

这是使用此程序打印的 CSV 文档。

StudentID,test,
std1,StudentID,test,
std1,1,
std2,StudentID,test,
std1,1,
std2,0,
std3,StudentID,test,
std1,1,
std2,0,
std3,0,
std4,StudentID,test,
std1,1,
std2,0,
std3,0,
std4,0,
c
1个回答
3
投票

对文件的输出进行缓冲,并在进程分叉时复制缓冲区。在调用

fflush
之前使用
fork
刷新流缓冲区,与
fflush(gradesFile);
一样。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.