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

C语言新手如何处理SPOJ题目中的SIGSEGV(段错误)?

解决SPOJ标识符统计任务中的SIGSEGV段错误问题

任务回顾

要求编写C语言程序统计每行中符合规则的标识符数量:

  • 标识符定义:由a-z、A-Z、0-9或_组成,且必须以字母或_开头
  • 输入:多行文本,每行包含空格分隔的单词(单词为ASCII 33-126的字符序列)
  • 输出:每行对应的标识符数量

示例输入

Dato25 has 2 c-ats and 3 _dogs
op8ax _yu _yu67 great-job ax~no identifier.

示例输出

4
3

SIGSEGV段错误的常见排查方向及解决方法

代码能编译但触发段错误,通常是内存访问违规导致的,结合这个任务场景,重点检查以下几点:

1. 数组越界访问

如果用固定大小的数组存储输入行,当输入行长度超过数组容量时,会写入到数组外的内存区域,触发段错误。

  • 解决:使用动态内存分配的方式读取行,比如标准库的getline函数(自动分配/扩容缓冲区),或者手动用malloc+realloc处理长行。

2. 空指针解引用

处理字符串时未检查指针是否为NULL就直接操作,比如:

  • strtok返回NULL后仍继续访问其内容
  • malloc/calloc分配内存失败后未判断,直接使用指针
  • 解决:所有指针操作前必须做非空校验,比如strtok循环时要判断返回值是否为NULL;内存分配后检查if (ptr == NULL)并处理错误。

3. 字符串操作函数的错误使用

比如用strcpy/strcat时目标缓冲区不足,或者strtok跨多行处理时未正确重置状态:

  • 解决:优先用strncpy(注意手动添加字符串终止符'\0'),或用getline读取整行后再分割;每行处理时,strtok第一次调用传入行字符串,后续调用传入NULL,确保每行独立处理。

4. 单词处理的边界错误

比如未判断单词是否为空就直接访问word[0],或者遍历单词字符时超出字符串长度:

  • 解决:处理每个单词前先判断是否为空字符串;遍历字符时以'\0'为终止标志,或用strlen获取长度后控制遍历范围。

参考代码示例

以下是符合要求且能避免常见段错误的实现:

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

// 判断单个单词是否为合法标识符
int is_identifier(const char *word) {
    if (word == NULL || *word == '\0') {
        return 0;
    }
    // 检查首字符:必须是字母或下划线
    if (!isalpha((unsigned char)*word) && *word != '_') {
        return 0;
    }
    // 检查后续所有字符
    while (*++word != '\0') {
        if (!isalnum((unsigned char)*word) && *word != '_') {
            return 0;
        }
    }
    return 1;
}

int main() {
    char *line = NULL;
    size_t buf_size = 0;
    ssize_t read_len;

    // 逐行读取输入
    while ((read_len = getline(&line, &buf_size, stdin)) != -1) {
        // 去除换行符(如果存在)
        if (read_len > 0 && line[read_len - 1] == '\n') {
            line[read_len - 1] = '\0';
        }

        int count = 0;
        char *token = strtok(line, " ");
        // 分割每行的单词并统计
        while (token != NULL) {
            if (is_identifier(token)) {
                count++;
            }
            token = strtok(NULL, " ");
        }

        printf("%d\n", count);
    }

    // 释放getline分配的内存
    free(line);
    return 0;
}

代码关键点说明

  • 使用getline动态读取行,避免固定数组的越界问题
  • is_identifier函数先做空值校验,再严格按规则验证每个字符
  • strtok正确处理每行的单词分割,确保每行独立计算
  • 最后释放动态分配的内存,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:50:21