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

C语言操作.txt文件时输入信息保存为乱码的问题求助

问题:C语言操作TXT文件时写入内容出现乱码

控制台输入信息后,文件中保存的是奇怪字符,示例:

Q(@     `$@     1       P            ÿÿÿÿÿÿÿÿ1           

附上原代码:

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

typedef struct Dados
{
    char ID[2];
    char NOME[50];
    char EMAIL[50];
    char TELEFONE[14];
    char STATUS[1]; 
} Dados;

Dados GetDados()
{
    Dados dados;
    system("cls");
    printf("\n\nDigite o ID: ");
    scanf("%s", dados.ID);
    
    printf("\n\nDigite seu primeiro nome: ");
    scanf("%s", dados.NOME);
    
    printf("\n\nDigite o Email: ");
    scanf("%s", dados.EMAIL);
    
    printf("\n\nDigite o Telefone: ");
    scanf("%s", dados.TELEFONE);
    
    rewind(stdin);
    return dados;
}


void ConsultarPorID(char ID[]) {
    FILE * arq;
    Dados dados;
    int encontrou = 0;

if ((arq = fopen("c:\\pastadados\\newdados.txt", "r")) == NULL) {
    printf("Erro ao abrir o arquivo.\n");
    return;
}
while (fscanf(arq, "%s%s%s%s", dados.ID, dados.NOME, dados.EMAIL, dados.TELEFONE) != EOF) {
    if (strcmp(dados.ID, ID) == 0) {
        printf("\n\tId: %s\n", dados.ID);
        printf("\tNome: %s\n", dados.NOME);
        printf("\tEmail: %s\n", dados.EMAIL);
        printf("\tTelefone: %s\n", dados.TELEFONE);
        encontrou = 1;
    }
}
if (!encontrou) {
    printf("Nenhum registro encontrado com o ID '%s'.\n", ID);
}
fclose(arq);
}


int main()
{
    FILE * arq;
    Dados dados;
    char ID[2];
    char NOME[50];
    char EMAIL[50];
    char TELEFONE[14];
    char STATUS[1];
    int resposta, idConsulta;
    
    printf("\n1 - Inserir dados\n\n2 - Consultar por ID\n\n3 - Consultar por nome\n\n4 - Consultar por email\n\n5 - Consultar por telefone\n\n6 - Excluir dados\n\n\nQue opcao deseja prosseguir? ");
    scanf("%d", &resposta);
    
    if(resposta == 1)
    {
        if ((arq = fopen("c:\\pastadados\\newdados.txt", "a")) == NULL)
        {
            printf("\n\nNao foi possivel criar o arquivo! :(\n\n");
            exit(1);
        }
        else 
        {
            do {
                GetDados();
                fwrite(&dados, sizeof(Dados), 1, arq);
                printf("\n\nDados salvos com sucesso!\n");
                printf("\nDeseja inserir mais dados? (s/n): ");
                resposta = getche();
            } while (resposta != 'n' && resposta != 'N');
            fclose(arq);
        }
    }

    else if (resposta == 2) {
        system("cls");
        printf("Digite o ID que deseja consultar: ");
        scanf("%d", &idConsulta);
        
        fgets(ID, 2, stdin);
        ID[strcspn(ID, "\n")]; 
        
        ConsultarPorID(ID);
    }
    
    else if (resposta == 6) {
        remove("c:\\pastadados\\newdados.txt");
        printf("\nDados excluidos com sucesso!");
    }
    return 0;
}

错误原因分析

  • 二进制写入与文本读取不兼容:使用fwrite以二进制格式写入结构体,但查询时用fscanf按文本格式读取,两种方式的存储逻辑完全不同,必然导致乱码。
  • 未接收结构体返回值:GetDados()函数返回了填充好的结构体实例,但main函数中仅调用GetDados();,没有将返回值赋值给dados变量,导致写入文件的是未初始化的垃圾内存数据。
  • ID处理逻辑错误:查询时将ID当作整数读取(scanf("%d", &idConsulta)),但结构体中ID是字符数组,后续转换和传递完全错误,导致查询用的ID是无效值。
  • STATUS数组长度不足:char STATUS[1];无法容纳C语言字符串(字符串需要末尾的\0终止符),会造成内存越界,破坏其他字段的数据。
  • getche()的问题:getche()是非标准库函数,兼容性差;且在scanf后调用会读取残留的换行符,导致循环判断异常。

修正后的代码

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

typedef struct Dados
{
    char ID[3];          // 增加长度,容纳ID和终止符
    char NOME[50];
    char EMAIL[50];
    char TELEFONE[15];   // 增加长度,容纳号码和终止符
    char STATUS[2];      // 至少2位存状态字符+终止符
} Dados;

Dados GetDados()
{
    Dados dados;
    system("cls");
    // 限制输入长度,避免数组越界
    printf("\n\nDigite o ID: ");
    scanf("%2s", dados.ID);
    
    printf("\n\nDigite seu primeiro nome: ");
    scanf("%49s", dados.NOME);
    
    printf("\n\nDigite o Email: ");
    scanf("%49s", dados.EMAIL);
    
    printf("\n\nDigite o Telefone: ");
    scanf("%14s", dados.TELEFONE);
    
    // 清理输入缓冲区的残留换行
    while(getchar() != '\n');
    return dados;
}

// 二进制方式读取查询
void ConsultarPorID(char ID[]) {
    FILE * arq;
    Dados dados;
    int encontrou = 0;

    if ((arq = fopen("c:\\pastadados\\newdados.txt", "rb")) == NULL) {
        printf("Erro ao abrir o arquivo.\n");
        return;
    }
    // 用fread读取二进制结构体
    while (fread(&dados, sizeof(Dados), 1, arq) == 1) {
        if (strcmp(dados.ID, ID) == 0) {
            printf("\n\tId: %s\n", dados.ID);
            printf("\tNome: %s\n", dados.NOME);
            printf("\tEmail: %s\n", dados.EMAIL);
            printf("\tTelefone: %s\n", dados.TELEFONE);
            encontrou = 1;
            break; // 找到后可退出循环
        }
    }
    if (!encontrou) {
        printf("Nenhum registro encontrado com o ID '%s'.\n", ID);
    }
    fclose(arq);
}

int main()
{
    FILE * arq;
    Dados dados;
    char ID[3];
    int resposta;
    char confirm;
    
    printf("\n1 - Inserir dados\n\n2 - Consultar por ID\n\n3 - Consultar por nome\n\n4 - Consultar por email\n\n5 - Consultar por telefone\n\n6 - Excluir dados\n\n\nQue opcao deseja prosseguir? ");
    scanf("%d", &resposta);
    // 清理输入缓冲区
    while(getchar() != '\n');
    
    if(resposta == 1)
    {
        // 二进制追加写入
        if ((arq = fopen("c:\\pastadados\\newdados.txt", "ab")) == NULL)
        {
            printf("\n\nNao foi possivel criar o arquivo! :(\n\n");
            exit(1);
        }
        else 
        {
            do {
                dados = GetDados(); // 接收返回的结构体
                fwrite(&dados, sizeof(Dados), 1, arq);
                printf("\n\nDados salvos com sucesso!\n");
                printf("\nDeseja inserir mais dados? (s/n): ");
                scanf("%c", &confirm);
                // 清理输入缓冲区
                while(getchar() != '\n');
            } while (confirm != 'n' && confirm != 'N');
            fclose(arq);
        }
    }

    else if (resposta == 2) {
        system("cls");
        printf("Digite o ID que deseja consultar: ");
        scanf("%2s", ID);
        ConsultarPorID(ID);
    }
    
    else if (resposta == 6) {
        if(remove("c:\\pastadados\\newdados.txt") == 0)
            printf("\nDados excluidos com sucesso!");
        else
            printf("\nErro ao excluir dados!");
    }
    return 0;
}

关键修改说明

  • 统一使用二进制读写:写入用fwrite,读取用fread,文件打开模式对应ab和rb。
  • 接收GetDados()的返回值:将填充好的结构体赋值给dados,确保写入的是用户输入的数据。
  • 修正数组长度:所有字符串数组预留足够空间存储\0终止符,避免内存越界。
  • 修复ID查询逻辑:直接按字符数组读取ID,避免类型转换错误。
  • 替换getche()为标准输入函数:用scanf读取确认字符,并清理输入缓冲区的残留换行,避免输入异常。
  • 增加错误判断:删除文件时判断remove的返回值,处理删除失败的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:48:10