实验代码框架讲解

项目结构

.
├── exercises //所有习题都在此文件夹下
├── LICENSE
├── Makefile 
├── README.en.md
├── README.md
└── test //所有测例都在此文件夹下
  • exercises:这个文件夹包含了所有的习题代码。每个习题可以作为一个子文件夹,其中包含习题的源代码、数据文件和任何相关的资源。
  • LICENSE:项目的许可证文件,定义了项目的使用、修改和分发的法律条款。
  • Makefile:一个自动化构建脚本,用于编译、测试和清理项目。通过运行 make 命令,可以执行 Makefile 中定义的任务。
  • test:这个文件夹包含了所有的测试用例。每个测试用例可以作为一个子文件夹或文件,用于验证习题代码的正确性。

Makefile 内容

实验框架的 Makefile:

# Makefile for C language exercise project

# Define the directory where the exercise files are stored
EXERCISE_DIR = ./exercises

# Define the test directory
TEST_DIR = ./test

# Define the build directory
BUILD_DIR = ./build

# Ensure the test and build directories exist
$(shell mkdir -p $(TEST_DIR) $(BUILD_DIR))

# Define the list of exercises
EXERCISES = $(wildcard $(EXERCISE_DIR)/*.c)

# Define the list of executables
EXECUTABLES = $(patsubst $(EXERCISE_DIR)/%.c, $(BUILD_DIR)/%, $(EXERCISES))

# Define compiler and linker flags
CC = gcc
CFLAGS = -Wall -Wextra -std=c99
LDFLAGS = -lm

# Default target: build all executables
all: $(EXECUTABLES) clean

# Build rule for each executable
$(BUILD_DIR)/%: $(EXERCISE_DIR)/%.c
	$(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)

# Clean rule to remove all executables and object files
clean:
	rm -f $(EXECUTABLES) $(BUILD_DIR)/*.o

# Generate test cases rule
generate-test-cases: $(EXECUTABLES)
	@for exe in $(EXECUTABLES); do \
    	./$$exe > $(TEST_DIR)/$$(basename $$exe).out; \
	done
	@$(MAKE) clean

# Test rule to compare output with expected results
test-output: $(EXECUTABLES)
	@for exe in $(EXECUTABLES); do \
    	exercise_name=$$(basename $$exe); \
    	expected=$$(cat $(TEST_DIR)/$${exercise_name}.out); \
    	actual=$$($$exe); \
    	if [ "$$expected" = "$$actual" ]; then \
        	echo "Test for $${exercise_name} passed."; \
    	else \
        	echo "Test for $${exercise_name} failed."; \
        	echo "Expected:"; echo "$$expected"; \
        	echo "Actual:"; echo "$$actual"; \
    	fi; \
	done
	@$(MAKE) clean

# New target to save test results and count pass rate in JSON format
save-test-results: $(EXECUTABLES)
	@total=0; \
	passed=0; \
	> $(BUILD_DIR)/test_results.json; \
	for exe in $(EXECUTABLES); do \
    	exercise_name=$$(basename $$exe); \
    	expected=$$(cat $(TEST_DIR)/$${exercise_name}.out); \
    	actual=$$($$exe); \
    	total=$$((total+1)); \
    	if [ "$$expected" = "$$actual" ]; then \
        	passed=$$((passed+1)); \
    	fi; \
	done; \
	echo "{\"channel\": \"gitee\",\"courseId\": 1558,\"ext\": \"aaa\",\"name\": \"\",\"score\": $$passed,\"totalScore\": 5}" > $(BUILD_DIR)/test_results.json
	@$(MAKE) clean

.PHONY: all clean generate-test-cases test-output save-test-results

  • 目录定义
    • EXERCISE_DIR:存放练习文件的目录。
    • TEST_DIR:存放测试文件的目录。
    • BUILD_DIR:存放构建产物的目录。
  • 文件和目录操作
    • mkdir -p $(TEST_DIR) $(BUILD_DIR):确保测试和构建目录存在。
  • 编译和链接
    • CC = gcc:定义编译器为gcc。
    • CFLAGS = -Wall -Wextra -std=c99:编译选项,包括警告和C99标准。
    • LDFLAGS = -lm:链接选项,链接数学库。
  • 构建规则
    • $(BUILD_DIR)/%: $(EXERCISE_DIR)/%.c:为每个练习文件生成对应的执行文件。
  • 清理规则
    • clean:删除所有执行文件和构建目录下的对象文件。
  • 测试规则
    • generate-test-cases:生成测试用例。
    • test-output:运行测试并比较输出结果。
    • save-test-results:保存测试结果和通过率到JSON文件。

使用 makefile 进行实验

在实验过程中,Makefile提供了自动化构建和测试的便利。以下是如何使用这个Makefile进行实验的步骤:

  1. 编译所有练习

    make
    

    这个命令会编译所有练习文件,并在BUILD_DIR目录下生成对应的执行文件。

  2. 生成测试用例

    make generate-test-cases
    

    这个命令会运行所有执行文件,并将输出保存为测试用例。

  3. 运行测试

    make test-output
    

    这个命令会比较每个执行文件的输出与预期结果,并显示测试结果。

  4. 保存测试结果

    make save-test-results
    

    这个命令会计算测试的通过率,并将结果保存到test_results.json文件中。

  5. 清理

    make clean
    

    这个命令会删除所有构建产物和对象文件,保持环境整洁。