You need to enable JavaScript to run this app. C语言字符串拼接程序调试:safeReadString输入无返回问题排查
优惠活动
大模型
产品
解决方案
定价
更多

C语言字符串拼接程序调试:safeReadString输入无返回问题排查

C语言字符串读取拼接程序调试方案

核心问题定位

程序无法正常返回/崩溃的根源主要分为两部分:safeReadString函数存在多处逻辑硬错误,main函数存在内存操作隐患与输入输出逻辑疏漏。

一、safeReadString 函数的错误(直接导致程序崩溃的核心原因)

原函数实现存在4处致命逻辑错误:

  • 循环终止条件完全错误
    原循环逻辑:
    while((c!='\0') || (count<size))
    
    • getchar()读取的输入字符不会出现'\0',用户输入回车产生的是'\n'(ASCII 10)
    • 逻辑或||的判定规则是只要任意条件成立就持续循环,会导致循环永久运行、超出内存边界

    正确逻辑应为:只要未遇到输入终止符(换行/EOF),且仍有剩余存储空间时才继续读取,使用逻辑与&&做判定,同时预留1个字符的位置存储字符串结尾'\0'

  • 字符存储逻辑完全错误
    原代码的存储逻辑:
    s+=c;
    s++;
    
    该代码是将指针s的地址直接加上字符的ASCII值(比如输入字符a对应ASCII 97,就会把指针向后跳转97个字节),完全没有把字符存入目标内存,属于直接的野指针访问。

    正确存储逻辑:直接将字符赋值到当前指针指向的地址,再移动指针,即 *s = c; s++; 或简写为 *s++ = c;

  • 未处理输入残留的换行符
    用户输入结束按下的回车符会被存入输入缓冲区,若不主动排除或作为循环终止标记,会被错误写入字符串内容。
  • 未预留字符串结尾的存储空间
    原循环最多读取size个字符,后续还要执行*s='\0'写入结尾标记,会直接超出申请的内存边界。

二、main.c 中的隐藏错误

即使修正了safeReadString的逻辑,以下问题仍会导致程序异常:

  • 输出缓冲区未刷新
    原代码printf("Got here");末尾未加换行符,由于stdout默认是行缓冲模式,没有换行触发缓冲区刷新时,输出会滞留在内存中,程序后续崩溃时缓冲区会被直接丢弃,无法正常打印。
  • insStr为野指针
    原代码仅定义了char * insStr;未给指针分配任何有效内存,直接传入函数做写入操作会直接触发段错误。
  • 字符串拼接的索引逻辑错误
    原拼接代码:
    for(i=0;i<=strlen(mainStr);i++)
      newStr[i]=mainStr[i];
    for(int j=0;j<=strlen(insStr);j++)
      newStr[i+j]=insStr[j];
    
    第一个循环结束后,i的值已经等于strlen(mainStr)+1(循环条件为i<=strlen(mainStr)),第二个循环使用i+j作为偏移量会直接覆盖mainStr的结尾'\0',导致拼接后的字符串无法识别边界,出现越界访问。
  • 打印格式符语法错误
    原代码中with:\%s\n多了冗余的反斜杠,会将格式符转义为普通文本,无法正常打印第二个字符串内容。
  • 头文件缺少重复包含保护
    safeStr.h未添加头文件守卫,多文件编译时可能出现符号重复定义的问题。

修正后的完整代码

safeStr.h

#ifndef SAFE_STR_H
#define SAFE_STR_H

#include <stdio.h>
#define MAXSTR 80

void safeReadString(char *str, int size);

#endif

safeStr.c

#include "safeStr.h"

void safeReadString(char *str, int size)
{
    char c;
    char *s = str;
    int count = 0;
    printf("Please type a string of at most %d characters.\n", size);

    // 正确循环判定:遇到换行/EOF、或读满size-1个字符时终止
    while ((c = getchar()) != '\n' && c != EOF && count < size - 1)
    {
        *s++ = c; // 正确存储字符并移动指针
        count++;
    }
    *s = '\0'; // 手动写入字符串结尾标记
    // 清空输入缓冲区残留字符,避免影响下一次读取
    while (c != '\n' && c != EOF) {
        c = getchar();
    }
}

main.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "safeStr.h"

int main(void){
    char mainStr[MAXSTR] = "Initial string";
    safeReadString(mainStr, MAXSTR);
    int remChars = MAXSTR - strlen(mainStr) - 1;
    printf("Got here\n");
    if (remChars > 0)
    {
        // 给insStr分配有效堆内存
        char *insStr = (char*)malloc(remChars);
        if (insStr == NULL) {
            printf("Memory allocation failed\n");
            return 1;
        }
        safeReadString(insStr, remChars);

        int mainLen = strlen(mainStr);
        int insLen = strlen(insStr);
        // 给拼接结果分配有效内存
        char *newStr = (char*)malloc(mainLen + insLen + 1);
        if (newStr == NULL) {
            printf("Memory allocation failed\n");
            free(insStr);
            return 1;
        }

        // 直接用标准库函数完成拼接,避免手写索引错误
        strcpy(newStr, mainStr);
        strcat(newStr, insStr);

        printf("The result of concatenating:\n%s\nwith: %s\nis:\n%s\n", mainStr, insStr, newStr);

        // 释放堆内存,避免泄漏
        free(newStr);
        free(insStr);
    }
    else {
        printf("No room for inserting a string\n");
    }
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 14:54:01