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

使用strlen与指针遇异常及函数返回char指针的技术求助

问题分析与解决方案

首先,咱们拆解你遇到的两个核心问题:

一、为什么strlen计算的字符数总是多2?

这是因为你用fgets读取文件内容时,会把每行末尾的换行符一起读进来——Windows系统下的文本文件换行是\r\n(两个字符),所以每个单词字符串末尾会多出这两个不可见字符,strlen自然会把它们算进去,导致结果比实际单词长度多2。

二、如何正确从函数返回char指针?

你当前把char*强制转成int返回的做法完全错误,会导致三个严重问题:

  • 64位系统下指针长度是8字节,int是4字节,强制转换会截断地址,导致后续访问非法内存;
  • 函数内malloc的二级指针word没有被释放,造成内存泄漏;
  • main里两次调用read(library),相当于每次都重新读取文件、分配内存,你打印的字符串和计算长度的字符串根本不是同一个!

修正后的完整代码

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

// 读取文件并返回随机选中的单词(动态分配,需在main中free)
char* read_words() {
    FILE *library = fopen("C:\\Users\\pc\\Desktop\\library.txt", "r");
    if (library == NULL) {
        perror("Failed to open file");
        return NULL;
    }

    // 第一步:统计单词数量
    int word_count = 0;
    char temp_buf[256];
    while (fgets(temp_buf, sizeof(temp_buf), library) != NULL) {
        word_count++;
    }
    rewind(library);

    // 第二步:分配二级指针存储所有单词
    char **words = malloc(word_count * sizeof(char*));
    if (words == NULL) {
        perror("Failed to allocate memory for words array");
        fclose(library);
        return NULL;
    }

    for (int i = 0; i < word_count; i++) {
        words[i] = malloc(256 * sizeof(char));
        if (words[i] == NULL) {
            perror("Failed to allocate memory for word");
            // 内存分配失败时,先释放已分配的内存
            for (int j = 0; j < i; j++) {
                free(words[j]);
            }
            free(words);
            fclose(library);
            return NULL;
        }
        fgets(words[i], 256, library);
        // 去掉末尾的\r\n或\n,截断字符串
        words[i][strcspn(words[i], "\r\n")] = '\0';
    }

    // 第三步:随机选中一个单词
    int random_idx = rand() % word_count;
    // 分配内存拷贝选中的单词,避免释放words数组后指针失效
    char *selected_word = malloc(strlen(words[random_idx]) + 1);
    strcpy(selected_word, words[random_idx]);

    // 释放临时内存,避免泄漏
    for (int i = 0; i < word_count; i++) {
        free(words[i]);
    }
    free(words);
    fclose(library);

    return selected_word;
}

int main() {
    // 初始化随机种子,只需要执行一次
    srand((unsigned int)time(NULL));

    char *random_word = read_words();
    if (random_word == NULL) {
        return 1;
    }

    int word_length = strlen(random_word);
    printf("选中的单词:%s\n字符数:%d\n", random_word, word_length);

    // 记得释放动态分配的内存
    free(random_word);
    return 0;
}

关键修改点说明

  1. 文件路径转义:Windows路径中的反斜杠必须写成\\,否则会被当作转义字符处理;
  2. 处理换行符:用strcspn函数定位到\r或\n的位置,直接替换为字符串结束符\0,彻底去除换行符;
  3. 正确返回指针:函数返回char*类型,并且将选中的单词拷贝到新的动态内存中,再释放临时的二级指针数组,避免内存泄漏;
  4. 内存安全:增加了内存分配失败的错误处理,避免程序崩溃;
  5. 随机种子初始化:只在main中执行一次srand,保证随机数的有效性;
  6. 避免重复读取:main中只调用一次读取函数,保证打印的单词和计算长度的是同一个。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:20:40