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

write()写入文件出现乱码而非目标字符串的问题求助

问题分析与解决方案

核心问题

  1. sprintf的未定义行为
    你在循环中使用sprintf(stringnums, "%d %s", ..., stringnums),输入缓冲区和输出缓冲区是同一个字符数组。根据C标准,这种重叠的内存操作属于未定义行为,会直接导致内存读写混乱,引发乱码。

  2. 文件打开方式的潜在问题
    open(path, O_WRONLY)存在两个隐患:

    • 若目标文件不存在,open会直接报错;
    • 若文件已存在且原有内容长度大于本次写入内容,文件末尾的旧内容不会被清除,也会表现为乱码。
  3. 无效尝试的原因

  • 仅初始化stringnums为"\0":第一次循环没问题,但后续sprintf的重叠操作仍会破坏内存数据,无法解决根本问题;
  • 用sizeof替代strlen:会写入数组中未使用的内存区域(包含随机值),反而加重乱码。

修复方案

1. 解决sprintf重叠问题

避免输入输出缓冲区重叠,用以下两种方式构建字符串:

方法一:临时缓冲区拼接

// 先初始化字符串为空
stringnums[0] = '\0';
for(int i = 0; i < NUMINROW; i++){
    char temp[6]; // 足够存储数字+空格(如"29 ")
    int num = rand() % (NUMSIZE * 10);
    snprintf(temp, sizeof(temp), "%d ", num);
    
    // 临时存储拼接后的完整字符串
    char temp_full[(NUMSIZE + 1) * NUMINROW + 1];
    snprintf(temp_full, sizeof(temp_full), "%s%s", temp, stringnums);
    strcpy(stringnums, temp_full);
}

方法二:内存移动高效拼接
无需临时缓冲区,直接移动原有字符串腾出空间写入新内容:

stringnums[0] = '\0';
int current_len = 0;
const int max_len = (NUMSIZE + 1) * NUMINROW + 1;

for(int i = 0; i < NUMINROW; i++){
    int num = rand() % (NUMSIZE * 10);
    // 计算当前数字转为字符串的长度(含空格)
    int num_str_len = snprintf(NULL, 0, "%d ", num);
    
    // 确保不超出数组容量
    if(current_len + num_str_len >= max_len) break;
    
    // 将原有字符串向后移动,腾出开头空间
    memmove(stringnums + num_str_len, stringnums, current_len + 1);
    // 写入新数字到开头
    snprintf(stringnums, num_str_len + 1, "%d ", num);
    
    current_len += num_str_len;
}

2. 修正文件打开方式

添加O_CREAT(文件不存在时创建)和O_TRUNC(清空已有内容)标志,并设置合理的文件权限:

desc = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);

完整修复后的代码

#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#define NUMINROW 10
#define NUMSIZE 3

int main(){
    int desc;
    struct flock fl;
    char stringnums[(NUMSIZE + 1) * NUMINROW + 1];
    char* path = "randnums.txt";
    srand(time(NULL));

    // 修正文件打开方式
    desc = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (desc == -1)
        perror("open");

    if (fcntl(desc, F_GETLK, &fl) == -1)
        perror("fcntl_getlk");

    fl.l_type = F_WRLCK;
    if (fcntl(desc, F_SETLK, &fl) == -1)
        perror("fcntl_setlk");

    // 修正字符串构建逻辑
    stringnums[0] = '\0';
    int current_len = 0;
    const int max_len = (NUMSIZE + 1) * NUMINROW + 1;
    for(int i = 0; i < NUMINROW; i++){
        int num = rand() % (NUMSIZE * 10);
        int num_str_len = snprintf(NULL, 0, "%d ", num);
        
        if(current_len + num_str_len >= max_len) break;
        
        memmove(stringnums + num_str_len, stringnums, current_len + 1);
        snprintf(stringnums, num_str_len + 1, "%d ", num);
        current_len += num_str_len;
    }
    
    if (write(desc, stringnums, strlen(stringnums)) == -1)
        perror("write");  

    fl.l_type = F_UNLCK;
    if (fcntl(desc, F_SETLK, &fl) == -1)
        perror("fcntl_setlk");

    if (close(desc) == -1)
        perror("close");

    return 0;
}

内容的提问来源于stack exchange,提问作者Єгорій

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:45:18