You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解析类Excel格式CSV文件时触发Segmentation Fault(C语言)

Fixing Segmentation Fault & Fgets Issues in Your CSV Column Calculation Code

Hey there! I can tell you’ve been stuck on this for a while—let’s unpack the problems in your code and get you past that segmentation fault and the fgets reading issue. You’ve already narrowed down the trouble spot to the header parsing loop, so let’s start there.

Key Issues in Your Current Code

  • Uninitialized token variable: In your first loop, you check while(token != NULL) before ever assigning a value to token. This means the loop won’t run at all, so you never parse the header row to find your target column.
  • Incorrect feof() usage: Using feof(inFile) as the loop condition leads to off-by-one errors. feof() only triggers after you’ve tried to read past the end of the file, so you might end up processing invalid data (or trying to read from a failed fgets call).
  • Broken strsep logic: You’re modifying the stack-allocated Toprow array directly with strsep(&Toprow, ","), which shifts the pointer to the array’s start. After the first call, Toprow no longer points to the original beginning of the buffer, leading to memory chaos. Also, your loop order is reversed—you need to call strsep first, then check if the token is NULL.
  • Type mismatches & invalid conversions: Your min is an int but the function returns double. Worse, atoi(*token) is wrong—*token is a single char, so you’re converting the ASCII value of the first character instead of the entire string. It should be atoi(token).
  • Missing file open error check: If fopen("array.csv","r") fails (e.g., file not found), inFile stays NULL, and any subsequent operations on it will cause a segmentation fault.

Fixed Code with Explanations

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <float.h>

double getMin(char csvfile[], char column[]) {
    int target_col = -1; // Track the index of our target column
    char type;
    int chap, sec;
    char activity[50]; // Increased size to avoid overflow
    char header[100]; // Larger buffer for the header string
    char row[3000];
    FILE* inFile = NULL;

    // Parse the column specifier (e.g., "C1.2")
    if (sscanf(column, "%c%d.%d", &type, &chap, &sec) != 3) {
        return -2.0; // Invalid format
    }
    type = toupper(type); // Normalize to uppercase to simplify checks
    if (type != 'P' && type != 'C' && type != 'L') return -2.0;
    if (chap <= 0 || sec <= 0) return 0.0;

    // Build the header string we're looking for
    if (type == 'C') {
        snprintf(activity, sizeof(activity), "challenge"); // Fixed typo: "challange" → "challenge"
    } else if (type == 'P') {
        snprintf(activity, sizeof(activity), "participation");
    } else { // 'L'
        snprintf(activity, sizeof(activity), "lab"); // Fixed: "%cab" → "lab" (assumed typo)
    }
    snprintf(header, sizeof(header), "%d.%d - %s", chap, sec, activity);

    // Open the file with error checking
    inFile = fopen(csvfile, "r"); // Use the passed csvfile parameter instead of hardcoding!
    if (inFile == NULL) {
        perror("Failed to open file");
        return -3.0; // Indicate file open failure
    }

    // Read and parse the header row to find our target column
    if (fgets(row, sizeof(row), inFile) == NULL) {
        fclose(inFile);
        return -4.0; // Empty file or read error
    }

    char* row_ptr = row; // Use a separate pointer to avoid modifying the original array
    char* token;
    int col_index = 0;
    while ((token = strsep(&row_ptr, ",")) != NULL) {
        // Trim any leading/trailing whitespace/newlines from the token
        token[strcspn(token, "\n\r")] = '\0';
        if (strcmp(token, header) == 0) {
            target_col = col_index;
            break;
        }
        col_index++;
    }

    if (target_col == -1) {
        fclose(inFile);
        return -5.0; // Column not found
    }

    // Now read data rows to find the minimum value
    double min_val = DBL_MAX; // Use a large initial value for double
    while (fgets(row, sizeof(row), inFile) != NULL) {
        char* data_ptr = row;
        col_index = 0;
        while ((token = strsep(&data_ptr, ",")) != NULL) {
            token[strcspn(token, "\n\r")] = '\0'; // Trim newlines
            if (col_index == target_col) {
                // Convert token to double (supports decimals too)
                double curr_val = strtod(token, NULL);
                if (curr_val < min_val) {
                    min_val = curr_val;
                }
                break; // Move to next row once we get the target column
            }
            col_index++;
        }
    }

    fclose(inFile);

    // If no valid values were found, return an error
    if (min_val == DBL_MAX) {
        return -6.0;
    }

    return min_val;
}

Key Improvements Made

  1. Proper header parsing: We use a separate pointer (row_ptr) with strsep so we don’t modify the original stack array. We also trim newlines from tokens to avoid mismatches.
  2. Fixed file handling: We use the passed csvfile parameter instead of hardcoding "array.csv", add error checks for fopen and fgets, and always close the file before returning.
  3. Type consistency: Switched to double for min_val to match the function’s return type, and use strtod instead of atoi to support decimal values.
  4. Cleaner loop logic: Replaced feof() with checking the return value of fgets directly—this is the correct way to loop through a file line by line.
  5. Normalized input: Converted the type character to uppercase so "c1.2" and "C1.2" both work.
  6. Fixed typos: Corrected "challange" to "challenge" and fixed the "L" case to use "lab" instead of "%cab" (which was producing invalid strings like "Lab").

Additional Tips for Beginners

  • Always initialize variables before using them—uninitialized variables lead to unpredictable behavior (like segmentation faults).
  • Avoid modifying stack-allocated arrays directly with functions like strsep that alter the pointer. Use a temporary pointer instead.
  • When working with files, always check if fopen succeeds, and remember to close the file when you’re done to avoid resource leaks.

内容的提问来源于stack exchange,提问作者Stephen Carson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:14:05