C Language Comprehensive Project Practice: Building a Mini IoT Management Platform with ‘Grade Module + Sensor Module + File I/O’

⭐C Language Comprehensive Project Practice: Building a Mini IoT Management Platform with ‘Grade Module + Sensor Module + File I/O’

Author: IoT Smart Academy

This article integrates everything learned previously: sequential/branching/looping, arrays, structures, pointers, file I/O, modularization into a comprehensive project that can serve as a final assignment. The article covers: Project Description + Module Division + Data Structure + Menu Design + Core Code + Experimental Tasks, all in one go.

1. Project Background: Creating a ‘Mini IoT Management Platform’

Scenario Setting:

A certain IoT training room requires a command-line management platform written in C to manage:

  • Student Grade Information (for teachers to check grades and statistics)
  • Sensor Device Information (for laboratory monitoring and debugging)

Technical Requirements (strongly tied to your classroom content):

  • Language: Pure C Language
  • Knowledge Points: Structures, Arrays, Pointers, File I/O, Modularization, Multi-file Programming
  • Interface: Command-line menu (no graphical interface, no networking)
  • Storage: Use CSV files (<span>students.csv</span>, <span>sensors.csv</span>), which can be opened with Excel

Upon completing this project, you will be able to demonstrate:

  • How to write a fully functional small system;
  • How to modularize code, maintaining clear structure;
  • How to give the program “memory” (file persistence).

2. Overall Structure: A Main Menu with Two Subsystems

After running the program, a main menu will appear:

===== IoT Comprehensive Management Platform =====
1. Student Grade Management System
2. Sensor Monitoring System
0. Exit System
===========================
Please enter your choice:
  • Select 1 → Enter the 【Student Grade System】 submenu
  • Select 2 → Enter the 【Sensor Monitoring System】 submenu

C Language Comprehensive Project Practice: Building a Mini IoT Management Platform with 'Grade Module + Sensor Module + File I/O'

1. Student Grade Management System

===== Student Grade Management System =====
1. Enter Student
2. Show All
3. Query / Modify / Delete by Student ID
4. Sort by Grade / Sort by Student ID
5. Statistics (Highest/Lowest/Average/Pass Rate)
6. Filter by Grade Range
7. Batch Add Points
8. Save to CSV
9. Read from CSV
0. Return to Previous Level
===========================
Please enter your choice:

C Language Comprehensive Project Practice: Building a Mini IoT Management Platform with 'Grade Module + Sensor Module + File I/O'

2. IoT Sensor Monitoring System (Recommended Menu)

C Language Comprehensive Project Practice: Building a Mini IoT Management Platform with 'Grade Module + Sensor Module + File I/O'

===== IoT Sensor Monitoring System =====
1. Enter Device
2. Show All
3. Query / Modify / Delete by ID
4. Filter by Type (Temp/Humi/Smoke...)
5. Filter by Threshold (value >= threshold)
6. Sort by Reading in Descending Order
7. Statistics (Min/Max/Average)
8. Batch Calibrate (Uniform + offset)
9. Save to CSV
10. Read from CSV
0. Return to Previous Level
=============================
Please enter your choice:

In actual implementation, you can first implement the “basic functions” (entering/displaying/saving/reading), and then gradually add other items.

3. Module and File Division: The Project Directory Looks Like This

The project is divided into several modules, each responsible for a specific function:

project/
│
├─ main.c          // Top-level menu + Process control
├─ student.h       // Student module: Structure + Function declarations
├─ student.c       // Student module: Function implementations
├─ sensor.h        // Sensor module: Structure + Function declarations
├─ sensor.c        // Sensor module: Function implementations
└─ util.h / util.c // Optional: Common utility functions
  • <span>student.*</span> specifically manages student data
  • <span>sensor.*</span> specifically manages sensor data
  • <span>main.c</span> is only responsible for the menu and calls
  • <span>util.*</span> contains commonly used input functions (<span>readInt</span>, <span>readFloat</span>, etc.), for easy reuse

4. Data Structure Design: Two “Small Databases”

1. Student Data Structure (<span>student.h</span>)

#ifndef STUDENT_H
#define STUDENT_H

#define MAX_STU 300

typedef struct {
    int   id;           // Student ID
    char  name[20];     // Name (suggest using pinyin without spaces)
    float score;        // Score
} Student;

typedef struct {
    Student arr[MAX_STU];
    int     count;      // Current number of students
} StudentDB;

/* —— Functions provided by the student module —— */

void initStudentDB(StudentDB *db);
void addStudents(StudentDB *db);
void showAllStudents(const StudentDB *db);

void queryUpdateDeleteStudent(StudentDB *db);
void sortStudentsByScore(StudentDB *db);
void sortStudentsById(StudentDB *db);
void statStudents(const StudentDB *db);
void filterStudentsByRange(const StudentDB *db);
void batchBonusStudents(StudentDB *db);

int  saveStudentsCSV(const char *path, const StudentDB *db);
int  loadStudentsCSV(const char *path, StudentDB *db);

#endif /* STUDENT_H */

2. Sensor Data Structure (<span>sensor.h</span>)

#ifndef SENSOR_H
#define SENSOR_H

#define MAX_SENSOR 200

typedef struct {
    int   id;              // Device ID
    char  type[16];        // Type: Temp/Humi/Smoke...
    char  location[32];    // Location: Room101/Room202...
    float value;           // Current reading
} Sensor;

typedef struct {
    Sensor arr[MAX_SENSOR];
    int    count;
} SensorDB;

/* —— Functions provided by the sensor module —— */

void initSensorDB(SensorDB *db);
void addSensors(SensorDB *db);
void showAllSensors(const SensorDB *db);

void queryUpdateDeleteSensor(SensorDB *db);
void filterSensorsByType(const SensorDB *db);
void filterSensorsByThreshold(const SensorDB *db);
void sortSensorsByValue(SensorDB *db);
void statSensors(const SensorDB *db);
void batchCalibrateSensors(SensorDB *db);

int  saveSensorsCSV(const char *path, const SensorDB *db);
int  loadSensorsCSV(const char *path, SensorDB *db);

#endif /* SENSOR_H */

3. Optional Utility Module (<span>util.h</span>)

#ifndef UTIL_H
#define UTIL_H

int   readInt(const char *tip);
float readFloat(const char *tip);

#endif

5. Key Code ①: Utility Module <span>util.c</span> (optional but highly recommended)

/* util.c */
#include <stdio.h>
#include "util.h"

int readInt(const char *tip) {
    int x;
    printf("%s", tip);
    scanf("%d", &x);
    return x;
}

float readFloat(const char *tip) {
    float x;
    printf("%s", tip);
    scanf("%f", &x);
    return x;
}

6. Key Code ②: Student Module <span>student.c</span> (Core Functionality)

Here is a set of runnable core implementations, with some remaining functionalities that you can expand upon.

/* student.c */
#include "student.h"
#include "util.h"
#include <stdio.h>
#include <string.h>

/* Initialization */
void initStudentDB(StudentDB *db) {
    db->count = 0;
}

/* Enter Student */
void addStudents(StudentDB *db) {
    int n = readInt("Please enter the number of students to be recorded:");
    if (n <= 0) {
        printf("The number must be greater than 0.\n");
        return;
    }
    if (db->count + n > MAX_STU) {
        printf("Insufficient capacity, can record %d more.\n", MAX_STU - db->count);
        return;
    }

    for (int i = 0; i < n; i++) {
        Student s;
        printf("The %d student (format: ID Name Score):\n", db->count + 1);
        scanf("%d %19s %f", &s.id, s.name, &s.score);
        db->arr[db->count++] = s;
    }
    printf("Recorded, current total number: %d\n", db->count);
}

/* Show All */
void showAllStudents(const StudentDB *db) {
    if (db->count == 0) {
        printf("No student data available.\n");
        return;
    }
    printf("\nNo.	ID	Name	Score\n");
    for (int i = 0; i < db->count; i++) {
        printf("%d	%d	%s	%.2f\n",
               i + 1,
               db->arr[i].id,
               db->arr[i].name,
               db->arr[i].score);
    }
}

/* Internal Utility: Find Index by Student ID */
static int findStudentPosById(const StudentDB *db, int id) {
    for (int i = 0; i < db->count; i++) {
        if (db->arr[i].id == id) return i;
    }
    return -1;
}

/* Query / Modify / Delete by Student ID (in one menu) */
void queryUpdateDeleteStudent(StudentDB *db) {
    if (db->count == 0) {
        printf("No student data available.\n");
        return;
    }
    printf("\n1 Query by ID\n2 Modify Score\n3 Delete Student\n0 Return\n");
    int c = readInt("Please select an operation:");
    if (c == 0) return;

    int id = readInt("Please enter the ID:");
    int pos = findStudentPosById(db, id);
    if (pos < 0) {
        printf("Student ID %d not found.\n", id);
        return;
    }

    if (c == 1) {
        Student *p = &db->arr[pos];
        printf("Found: ID=%d Name=%s Score=%.2f\n", p->id, p->name, p->score);
    } else if (c == 2) {
        float sc = readFloat("Please enter the new score:");
        db->arr[pos].score = sc;
        printf("Updated: ID=%d New Score=%.2f\n", id, sc);
    } else if (c == 3) {
        for (int i = pos; i < db->count - 1; i++)
            db->arr[i] = db->arr[i + 1];
        db->count--;
        printf("Deleted ID %d, current number=%d\n", id, db->count);
    } else {
        printf("Invalid option.\n");
    }
}

/* Sort by Score (Descending) */
void sortStudentsByScore(StudentDB *db) {
    for (int i = 0; i < db->count - 1; i++) {
        for (int j = 0; j < db->count - 1 - i; j++) {
            if (db->arr[j].score < db->arr[j + 1].score) {
                Student t = db->arr[j];
                db->arr[j] = db->arr[j + 1];
                db->arr[j + 1] = t;
            }
        }
    }
    printf("Sorted by score in descending order.\n");
}

/* Sort by Student ID (Ascending) */
void sortStudentsById(StudentDB *db) {
    for (int i = 0; i < db->count - 1; i++) {
        for (int j = 0; j < db->count - 1 - i; j++) {
            if (db->arr[j].id > db->arr[j + 1].id) {
                Student t = db->arr[j];
                db->arr[j] = db->arr[j + 1];
                db->arr[j + 1] = t;
            }
        }
    }
    printf("Sorted by ID in ascending order.\n");
}

/* Statistics (Highest/Lowest/Average/Pass Rate) */
void statStudents(const StudentDB *db) {
    if (db->count == 0) {
        printf("No student data available.\n");
        return;
    }
    float max = db->arr[0].score;
    float min = db->arr[0].score;
    float sum = 0.0f;
    int pass = 0;

    for (int i = 0; i < db->count; i++) {
        float x = db->arr[i].score;
        if (x > max) max = x;
        if (x < min) min = x;
        sum += x;
        if (x >= 60) pass++;
    }

    printf("Number: %d  Highest: %.2f  Lowest: %.2f  Average: %.2f  Pass Rate: %.2f%%\n",
           db->count,
           max,
           min,
           sum / db->count,
           100.0f * pass / db->count);
}

/* Filter by Grade Range */
void filterStudentsByRange(const StudentDB *db) {
    if (db->count == 0) {
        printf("No student data available.\n");
        return;
    }
    float L = readFloat("Please enter the lower limit:");
    float R = readFloat("Please enter the upper limit:");
    if (L > R) { float t = L; L = R; R = t; }

    int found = 0;
    printf("\n=== Students in the range [%.2f, %.2f] ===\n", L, R);
    for (int i = 0; i < db->count; i++) {
        float x = db->arr[i].score;
        if (x >= L && x <= R) {
            printf("%d	%s	%.2f\n",
                   db->arr[i].id,
                   db->arr[i].name,
                   x);
            found = 1;
        }
    }
    if (!found) printf("No matching records.\n");
}

/* Batch Add Points */
void batchBonusStudents(StudentDB *db) {
    if (db->count == 0) {
        printf("No student data available.\n");
        return;
    }
    float off = readFloat("Please enter the bonus offset (e.g., +2 / -1.5):");
    for (int i = 0; i < db->count; i++) {
        db->arr[i].score += off;
        if (db->arr[i].score < 0)   db->arr[i].score = 0;
        if (db->arr[i].score > 100) db->arr[i].score = 100;
    }
    printf("Batch bonus added (clipped to [0,100]).\n");
}

/* Save to CSV */
int saveStudentsCSV(const char *path, const StudentDB *db) {
    FILE *fp = fopen(path, "w");
    if (!fp) {
        perror("Failed to open file for writing");
        return 0;
    }
    fprintf(fp, "id,name,score\n");
    for (int i = 0; i < db->count; i++) {
        fprintf(fp, "%d,%s,%.2f\n",
                db->arr[i].id,
                db->arr[i].name,
                db->arr[i].score);
    }
    fclose(fp);
    return 1;
}

/* Read from CSV */
int loadStudentsCSV(const char *path, StudentDB *db) {
    FILE *fp = fopen(path, "r");
    if (!fp) {
        perror("Failed to open file for reading");
        return 0;
    }
    db->count = 0;
    char line[256];

    if (!fgets(line, sizeof(line), fp)) { // Skip header
        fclose(fp);
        return 0;
    }

    while (db->count < MAX_STU && fgets(line, sizeof(line), fp)) {
        Student s;
        if (sscanf(line, "%d,%19[^,],%f",
                   &s.id,
                   s.name,
                   &s.score) == 3) {
            db->arr[db->count++] = s;
        }
    }
    fclose(fp);
    return 1;
}

7. Key Code ③: Sensor Module <span>sensor.c</span> (Core Functionality)

/* sensor.c */
#include "sensor.h"
#include "util.h"
#include <stdio.h>
#include <string.h>

/* Initialization */
void initSensorDB(SensorDB *db) {
    db->count = 0;
}

/* Enter Device */
void addSensors(SensorDB *db) {
    int n = readInt("Please enter the number of devices to be recorded:");
    if (n <= 0) {
        printf("The number must be greater than 0.\n");
        return;
    }
    if (db->count + n > MAX_SENSOR) {
        printf("Insufficient capacity, can record %d more.\n", MAX_SENSOR - db->count);
        return;
    }
    for (int i = 0; i < n; i++) {
        Sensor s;
        printf("The %d device (format: id type location value):\n", db->count + 1);
        scanf("%d %15s %31s %f", &s.id, s.type, s.location, &s.value);
        db->arr[db->count++] = s;
    }
    printf("Recorded, current number of devices: %d\n", db->count);
}

/* Show All Devices */
void showAllSensors(const SensorDB *db) {
    if (db->count == 0) {
        printf("No device data available.\n");
        return;
    }
    printf("\nID	Type	Location		Value\n");
    for (int i = 0; i < db->count; i++) {
        printf("%d	%-6s	%-16s	%.2f\n",
               db->arr[i].id,
               db->arr[i].type,
               db->arr[i].location,
               db->arr[i].value);
    }
}

/* Internal Utility: Find Index by Device ID */
static int findSensorPosById(const SensorDB *db, int id) {
    for (int i = 0; i < db->count; i++) {
        if (db->arr[i].id == id) return i;
    }
    return -1;
}

/* Query / Modify / Delete by ID */
void queryUpdateDeleteSensor(SensorDB *db) {
    if (db->count == 0) {
        printf("No device data available.\n");
        return;
    }
    printf("\n1 Query by ID\n2 Modify Reading\n3 Delete Device\n0 Return\n");
    int c = readInt("Please select an operation:");
    if (c == 0) return;

    int id = readInt("Please enter the ID:");
    int pos = findSensorPosById(db, id);
    if (pos < 0) {
        printf("Device ID %d not found.\n", id);
        return;
    }

    if (c == 1) {
        Sensor *p = &db->arr[pos];
        printf("Found: ID=%d Type=%s Location=%s Value=%.2f\n",
               p->id, p->type, p->location, p->value);
    } else if (c == 2) {
        float v = readFloat("Please enter the new reading:");
        db->arr[pos].value = v;
        printf("Updated: ID=%d New Reading=%.2f\n", id, v);
    } else if (c == 3) {
        for (int i = pos; i < db->count - 1; i++)
            db->arr[i] = db->arr[i + 1];
        db->count--;
        printf("Deleted ID %d, current number of devices=%d\n", id, db->count);
    } else {
        printf("Invalid option.\n");
    }
}

/* Filter by Type */
void filterSensorsByType(const SensorDB *db) {
    if (db->count == 0) {
        printf("No device data available.\n");
        return;
    }
    char t[16];
    printf("Please enter the type (e.g., Temp/Humi/Smoke):");
    scanf("%15s", t);

    int found = 0;
    printf("\n=== Devices of type %s ===\n", t);
    for (int i = 0; i < db->count; i++) {
        if (strcmp(db->arr[i].type, t) == 0) {
            printf("%d	%s	%s	%.2f\n",
                   db->arr[i].id,
                   db->arr[i].type,
                   db->arr[i].location,
                   db->arr[i].value);
            found = 1;
        }
    }
    if (!found) printf("No devices of this type found.\n");
}

/* Filter by Threshold (>= threshold) */
void filterSensorsByThreshold(const SensorDB *db) {
    if (db->count == 0) {
        printf("No device data available.\n");
        return;
    }
    float th = readFloat("Please enter the threshold (filter devices with readings >= threshold):");
    int found = 0;
    printf("\n=== Devices with readings >= %.2f ===\n", th);
    for (int i = 0; i < db->count; i++) {
        float x = db->arr[i].value;
        if (x >= th) {
            printf("%d	%s	%s	%.2f\n",
                   db->arr[i].id,
                   db->arr[i].type,
                   db->arr[i].location,
                   x);
            found = 1;
        }
    }
    if (!found) printf("No devices exceeding the threshold.\n");
}

/* Sort by Reading in Descending Order */
void sortSensorsByValue(SensorDB *db) {
    if (db->count <= 1) {
        printf("Insufficient data, no need to sort.\n");
        return;
    }
    for (int i = 0; i < db->count - 1; i++) {
        for (int j = 0; j < db->count - 1 - i; j++) {
            if (db->arr[j].value < db->arr[j + 1].value) {
                Sensor t = db->arr[j];
                db->arr[j] = db->arr[j + 1];
                db->arr[j + 1] = t;
            }
        }
    }
    printf("Sorted by readings in descending order.\n");
}

/* Statistics (Min/Max/Average) */
void statSensors(const SensorDB *db) {
    if (db->count == 0) {
        printf("No device data available.\n");
        return;
    }
    float min = db->arr[0].value;
    float max = db->arr[0].value;
    float sum = 0.0f;

    for (int i = 0; i < db->count; i++) {
        float x = db->arr[i].value;
        if (x < min) min = x;
        if (x > max) max = x;
        sum += x;
    }
    printf("Number of devices: %d  Minimum: %.2f  Maximum: %.2f  Average: %.2f\n",
           db->count, min, max, sum / db->count);
}

/* Batch Calibrate: Uniformly add offset */
void batchCalibrateSensors(SensorDB *db) {
    if (db->count == 0) {
        printf("No device data available.\n");
        return;
    }
    float off = readFloat("Please enter the calibration offset (e.g., +0.5 / -0.5):");
    for (int i = 0; i < db->count; i++) {
        db->arr[i].value += off;
    }
    printf("Batch calibrated (offset=%.2f).\n", off);
}

/* Save to CSV */
int saveSensorsCSV(const char *path, const SensorDB *db) {
    FILE *fp = fopen(path, "w");
    if (!fp) {
        perror("Failed to open file for writing");
        return 0;
    }
    fprintf(fp, "id,type,location,value\n");
    for (int i = 0; i < db->count; i++) {
        fprintf(fp, "%d,%s,%s,%.2f\n",
                db->arr[i].id,
                db->arr[i].type,
                db->arr[i].location,
                db->arr[i].value);
    }
    fclose(fp);
    return 1;
}

/* Read from CSV */
int loadSensorsCSV(const char *path, SensorDB *db) {
    FILE *fp = fopen(path, "r");
    if (!fp) {
        perror("Failed to open file for reading");
        return 0;
    }
    db->count = 0;
    char line[256];

    if (!fgets(line, sizeof(line), fp)) { // Skip header
        fclose(fp);
        return 0;
    }

    while (db->count < MAX_SENSOR && fgets(line, sizeof(line), fp)) {
        Sensor s;
        if (sscanf(line, "%d,%15[^,],%31[^,],%f",
                   &s.id,
                   s.type,
                   s.location,
                   &s.value) == 4) {
            db->arr[db->count++] = s;
        }
    }
    fclose(fp);
    return 1;
}

8. Key Code ④: Main Program <span>main.c</span> — Main Menu + Submenus

/* main.c */
#include <stdio.h>
#include "student.h"
#include "sensor.h"
#include "util.h"

/* Top-level Menu */
int mainMenu() {
    int c;
    printf("\n===== IoT Comprehensive Management Platform =====\n");
    printf("1 Student Grade Management System\n");
    printf("2 Sensor Monitoring System\n");
    printf("0 Exit System\n");
    printf("================================\n");
    printf("Please enter your choice:");
    scanf("%d", &c);
    return c;
}

/* Student Submenu */
int studentMenu() {
    int c;
    printf("\n===== Student Grade Management System =====\n");
    printf("1 Enter Student\n");
    printf("2 Show All\n");
    printf("3 Query/Modify/Delete by ID\n");
    printf("4 Sort by Grade / Sort by ID\n");
    printf("5 Statistics (Highest/Lowest/Average/Pass Rate)\n");
    printf("6 Filter by Grade Range\n");
    printf("7 Batch Add Points\n");
    printf("8 Save to CSV\n");
    printf("9 Read from CSV\n");
    printf("0 Return to Previous Level\n");
    printf("====================================\n");
    printf("Please enter your choice:");
    scanf("%d", &c);
    return c;
}

/* Sensor Submenu */
int sensorMenu() {
    int c;
    printf("\n===== IoT Sensor Monitoring System =====\n");
    printf("1 Enter Device\n");
    printf("2 Show All\n");
    printf("3 Query/Modify/Delete by ID\n");
    printf("4 Filter by Type\n");
    printf("5 Filter by Threshold\n");
    printf("6 Sort by Reading in Descending Order\n");
    printf("7 Statistics (Min/Max/Average)\n");
    printf("8 Batch Calibrate\n");
    printf("9 Save to CSV\n");
    printf("10 Read from CSV\n");
    printf("0 Return to Previous Level\n");
    printf("====================================\n");
    printf("Please enter your choice:");
    scanf("%d", &c);
    return c;
}

/* Main Function */
int main() {
    StudentDB stuDB;
    SensorDB  senDB;

    initStudentDB(&stuDB);
    initSensorDB(&senDB);

    while (1) {
        switch (mainMenu()) {
            case 1: { // Student System
                int c;
                while ((c = studentMenu()) != 0) {
                    switch (c) {
                        case 1: addStudents(&stuDB); break;
                        case 2: showAllStudents(&stuDB); break;
                        case 3: queryUpdateDeleteStudent(&stuDB); break;
                        case 4: {
                            printf("1 Sort by Grade  2 Sort by ID:");
                            int t; scanf("%d", &t);
                            if (t == 1) sortStudentsByScore(&stuDB);
                            else        sortStudentsById(&stuDB);
                            showAllStudents(&stuDB);
                        } break;
                        case 5: statStudents(&stuDB); break;
                        case 6: filterStudentsByRange(&stuDB); break;
                        case 7: batchBonusStudents(&stuDB); break;
                        case 8:
                            if (saveStudentsCSV("students.csv", &stuDB))
                                printf("Saved to students.csv\n");
                            else
                                printf("Save failed\n");
                            break;
                        case 9:
                            if (loadStudentsCSV("students.csv", &stuDB)) {
                                printf("Read from students.csv, current number: %d\n", stuDB.count);
                                showAllStudents(&stuDB);
                            } else {
                                printf("Read failed\n");
                            }
                            break;
                        default:
                            printf("Invalid option.\n");
                    }
                }
            } break;

            case 2: { // Sensor System
                int c;
                while ((c = sensorMenu()) != 0) {
                    switch (c) {
                        case 1: addSensors(&senDB); break;
                        case 2: showAllSensors(&senDB); break;
                        case 3: queryUpdateDeleteSensor(&senDB); break;
                        case 4: filterSensorsByType(&senDB); break;
                        case 5: filterSensorsByThreshold(&senDB); break;
                        case 6: sortSensorsByValue(&senDB); showAllSensors(&senDB); break;
                        case 7: statSensors(&senDB); break;
                        case 8: batchCalibrateSensors(&senDB); break;
                        case 9:
                            if (saveSensorsCSV("sensors.csv", &senDB))
                                printf("Saved to sensors.csv\n");
                            else
                                printf("Save failed\n");
                            break;
                        case 10:
                            if (loadSensorsCSV("sensors.csv", &senDB)) {
                                printf("Read from sensors.csv, current number of devices: %d\n", senDB.count);
                                showAllSensors(&senDB);
                            } else {
                                printf("Read failed\n");
                            }
                            break;
                        default:
                            printf("Invalid option.\n");
                    }
                }
            } break;

            case 0:
                printf("System exited, goodbye!\n");
                return 0;

            default:
                printf("Invalid option, please re-enter.\n");
        }
    }
}

9. How to Compile and Run?

Assuming all files are in the same directory:

1) gcc (Linux / WSL / MinGW)

gcc main.c student.c sensor.c util.c -o iot_app
./iot_app

2) Dev-C++ / VS / Code::Blocks

  • Create a “Console Project”;
  • Add all <span>main.c / student.c / sensor.c / util.c</span> to the project;
  • Ensure <span>*.h</span> files are in the same directory;
  • Compile and run directly.

10. Grading Suggestions for the “Final Assignment”

Grading can be based on 4 dimensions:

  1. Functionality (40 points)

  • Student Grade Module: Basic Functions + Statistics (20 points)
  • Sensor Module: Basic Functions + Statistics (15 points)
  • Correct CSV File Read/Write (5 points)
  • Code Structure and Standards (30 points)

    • Multi-file modularization, clear structure (10 points)
    • Variable naming conventions, reasonable comments (10 points)
    • No obvious duplicate code, appropriate function encapsulation (10 points)
  • Robustness and User Experience (20 points)

    • Error inputs do not crash directly, provide prompts (10 points)
    • Clear menus, neat output, complete information (10 points)
  • Expansion and Innovation (10 points)

    • Add extended functions (e.g., topN, fuzzy queries, alarm statistics, etc.) (6 points)
    • Simple project report or user manual (4 points)

    11. Checklist for Students (Self-check before Submission)

    • Can enter the main menu and two submenus normally
    • Student Grade System: Can enter, display, query, modify, delete, sort, save/read
    • Sensor System: Can enter, display, query, modify, delete, filter, sort, save/read
    • Generated <span>students.csv</span> and <span>sensors.csv</span>, can be opened correctly with Excel
    • No obvious array out-of-bounds, infinite loops, random crashes
    • Code is clearly modularized, with basic comments

    Complete code: Reply to the public account IoT Comprehensive Management Platform

    Leave a Comment