请问输入到文件上的内容出现乱码的问题到底如何解决

希望提供解决方案,谢谢了


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#include <locale.h>
 
void printMenu(void);
int checkPwd(int type);
int encryptFile(char *sourcefile, char *secretKey, char *targetFile, int encryptionMethod);
char redo(void);
 
int main() {
    char sourcefile[30], targetFile[30], secretKey[21], action;
    int encryptionMethod; // 加密方式
 
    while (1) {
        system("cls");  // 清屏
        printMenu();// 显示菜单
        scanf("%c", &action);// 输入要执行的操作
        fflush(stdin);// 清空stdin缓冲区
        system("cls");
 
        switch (action) {
// 退出系统
            case 'z':
                exit(0);
                break;
           // 文件加密 
            case 'a':
                while (1) {
                    printf("输入要加密的文件名(含路径):");
                    scanf("%s", sourcefile);
                    printf("输入密钥:");//密钥是用户自己定义的,可以随意给需要加密的文件添加密钥
                    scanf("%s", secretKey);
                    printf("加密后的文件名(含路径):");//给加密后的文件命名,并保存
                    scanf("%s", targetFile);
 
                    printf("选择加密方式:\n");
                    printf("1. 异或加密\n");
                    printf("2. 其他加密方式\n");
                    printf("请选择:");
                    scanf("%d", &encryptionMethod);
 
                    if (encryptFile(sourcefile, secretKey, targetFile, encryptionMethod)) {
                        printf("文件[%s]加密成功,保存在[%s]。\n", sourcefile, targetFile);
                    }
 
                    if (redo() == 'a') {// 继续加密文件
                        system("cls");
                    } else {// 回到主菜单
                        break;
                    }
                }
                break;
            case 'b':
                while (1) {
                    printf("输入要解密的文件名(含路径):");
                    scanf("%s", sourcefile);
                    printf("输入密钥:");
                    scanf("%s", secretKey);
                    printf("解密后的文件名(含路径):");//对解密的文件系统又可以提供保存路径
                    scanf("%s", targetFile);
 
                    printf("选择解密方式:\n");
                    printf("1. 异或解密\n");
                    printf("3. 其他解密方式\n");
                    printf("请选择:");
                    scanf("%d", &encryptionMethod);
 
                    if (encryptFile(sourcefile, secretKey, targetFile, encryptionMethod)) {
                        printf("文件[%s]解密成功,保存在[%s]。\n", sourcefile, targetFile);
                    }
 
                    if (redo() == 'a') {// 继续解密文件
                        system("cls");
                    } else {
                        break;// 回到主菜单
                    }
                }
                break;
            case 'c':
                               while(1){   
struct stu
{ 
    char name[10];
    int num;
    int age;
    char addr[15];
     }
boya[2],boyb[2],*pp,*qq;
{
    FILE *fp;
    char ch;
    int i;
    pp=boya;
    qq=boyb;
    if((fp=fopen("D:\ceshi.txt","wb+"))==NULL)
    {
        printf("Cannot open file strike any key exit!");
    }
    printf("\ninput data\n");
    for(i=0;i<2;i++,pp++)
    {
        scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
    }
    pp=boya;
    fwrite(pp,sizeof(struct stu),2,fp);
    //将文件指针重新指向一个流的开头
    rewind(fp);
    fread(qq,sizeof(struct stu),2,fp);
    printf("\n\nname\tnumber      age      addr\n");
    for(i=0;i<2;i++,qq++)
    {
        printf("%s\t%5d%7d     %s\n",qq->name,qq->num,qq->age,qq->addr);
    }
    fclose(fp);
}
    if(redo() == 'a'){  // 重新输入信息
                        system("cls");
                    }else{  // 回到主菜单
                        break;
                    }
                }
                break;
            default:
                printf("没有相应的菜单!按任意键回到主菜单...");
                getch();
        }
    }
 
    return EXIT_SUCCESS;
}
 /**
 * 显示程序菜单
**/
 
void printMenu() {
    printf("***************** 文本加密解密软件 *****************\n");
    printf("*                                                  *\n");
    printf("*                                                  *\n");
    printf("*      请从下面的菜单中选择你要进行的操作:        *\n");
    printf("*      a. 文件加密                                 *\n");
    printf("*      b. 文件解密                                 *\n");
    printf("*      c. 将信息存放到文件中                       *\n");
    printf("*      z. 退出系统                                 *\n");
    printf("*                                                  *\n");
    printf("*                                                  *\n");
    printf("****************************************************\n");
}
 
/**
 * 加密/解密文件
 *
 * @param   sourcefile    要加密/解密的文件名
 * @param   secretKey     密钥
 * @param   targetFile    加密/解密后要保存的文件名
 *
 * @return  加密成功或失败的数字表示
     0:加密失败
     1:加密成功
**/
int encryptFile(char *sourcefile, char *secretKey, char *targetFile, int encryptionMethod) {
    FILE *fpSource, *fpTarget;// 要打开的文件的指针
    char buffer[21];// 缓冲区,用于存放从文件读取的数据
    int readCount,// 每次从文件中读取的字节数
        keyLen = strlen(secretKey),// 密钥的长度
        i; // 循环次数
 // 以二进制方式读取/写入文件
    fpSource = fopen(sourcefile, "rb");
    if (fpSource == NULL) {
        printf("文件[%s]打开失败,请检查文件路径和名称是否输入正确!\n", sourcefile);
        return 0;
    }
 
    fpTarget = fopen(targetFile, "wb");
    if (fpTarget == NULL) {
        printf("文件[%s]创建/写入失败!请检查文件路径和名称是否输入正确!\n", fpTarget);
        return 0;
    }
 // 不断地从文件中读取 keyLen 长度的数据,保存到buffer,直到文件结束
    while ((readCount = fread(buffer, 1, keyLen, fpSource)) > 0) {
        if (encryptionMethod == 1) { // 异或加密
            for (i = 0; i < readCount; i++) {
                buffer[i] ^= secretKey[i];
            }
        } else if(encryptionMethod==2){
         // 位移加密
            for (i = 0; i < readCount; i++) {
                buffer[i] = buffer[i] + keyLen;
            }
 
        }else if(encryptionMethod==3){  // 因为位移加密和位移解密,无法共用一个处理方法,故新增一个模式来处理位移解密 
             // 位移解密 
            for (i = 0; i < readCount; i++) {
                buffer[i] = buffer[i] - keyLen;
            }
        }
 
        fwrite(buffer, 1, readCount, fpTarget);
    }
 
    fclose(fpSource);
    fclose(fpTarget);
    return 1;
}
 
char redo() {
    char action;
    printf("\n接下来你希望:\n");
    printf("a. 继续当前操作\n");
    printf("b. 回到主菜单\n");
 // 不停的等待用户输入,直到输入正确
    while (1) {
        fflush(stdin);
        scanf("%c", &action);
        fflush(stdin);
 
        if (action != 'a' && action != 'b') {
            printf("没有相应的菜单,请重新选择。\n");
        } else {
            return action;
            break;
        }
    }
}


img

如果是要解决写入文本文件打开后显示乱码,可以将fwrite()和fread()替换为fprintf()和fscanf()即可,因为fwrite()和fread()在Windows下是二进制文件读写函数,以文本文件的形式打开是会出现乱码的,而fprintf()和fscanf()应该大致是以文本模式来读写的。

修改如下:

参考链接:


【C 语言】文件操作 (fscanf、fprintf 函数)_c语言fscanf函数_韩曙亮的博客-CSDN博客 一、fscanf 函数、二、fprintf 函数_c语言fscanf函数 https://blog.csdn.net/shulianghan/article/details/117328308

C语言fread和fwrite的用法详解(以数据块的形式读写文件) fgets() 有局限性,每次最多只能从文件中读取一行内容,因为 fgets 遇到换行符就结束读取。如果希望读取多行内容,需要使用 fread 函数;相应地写入函数为 fwrite。 fread() 函数用来从指定 http://c.biancheng.net/view/2071.html

C语言-概念-fscanf函数和fprintf函数_c语言fprintf和fscanf_美腻程序员的博客-CSDN博客 fscanf函数和fprintf函数一、fscanf函数fscanf函数只能从文本文件中按格式输入。fscanf函数和scanf函数相似,只是输入的对象是磁盘上文本文件的数据。函数的调用形式如下:fscanf(文件指针,格式控制字符串,输入项表);例如,若文件指针fp已指向一个已打开的文本文件,a、b分别为整型变量,则以下语句从fp所指向的文件中读入两个整数放入变量a和b中:fscanf(fp,“%d%d”,&a,&b);注意:文件中的两个整数之间用空格(或跳个符、回车符)隔开。_c语言fprintf和fscanf https://blog.csdn.net/weixin_47423314/article/details/106200349




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

void printMenu(void);
int checkPwd(int type);
int encryptFile(char *sourcefile, char *secretKey, char *targetFile, int encryptionMethod);
char redo(void);

int main() {
    char sourcefile[30], targetFile[30], secretKey[21], action;
    int encryptionMethod; // 加密方式

    while (1) {
        system("cls");  // 清屏
        printMenu();// 显示菜单
        scanf("%c", &action);// 输入要执行的操作
        fflush(stdin);// 清空stdin缓冲区
        system("cls");

        switch (action) {
// 退出系统
            case 'z':
                exit(0);
                break;
                // 文件加密
            case 'a':
                while (1) {
                    printf("输入要加密的文件名(含路径):");
                    scanf("%s", sourcefile);
                    printf("输入密钥:");//密钥是用户自己定义的,可以随意给需要加密的文件添加密钥
                    scanf("%s", secretKey);
                    printf("加密后的文件名(含路径):");//给加密后的文件命名,并保存
                    scanf("%s", targetFile);

                    printf("选择加密方式:\n");
                    printf("1. 异或加密\n");
                    printf("2. 其他加密方式\n");
                    printf("请选择:");
                    scanf("%d", &encryptionMethod);

                    if (encryptFile(sourcefile, secretKey, targetFile, encryptionMethod)) {
                        printf("文件[%s]加密成功,保存在[%s]。\n", sourcefile, targetFile);
                    }

                    if (redo() == 'a') {// 继续加密文件
                        system("cls");
                    } else {// 回到主菜单
                        break;
                    }
                }
                break;
            case 'b':
                while (1) {
                    printf("输入要解密的文件名(含路径):");
                    scanf("%s", sourcefile);
                    printf("输入密钥:");
                    scanf("%s", secretKey);
                    printf("解密后的文件名(含路径):");//对解密的文件系统又可以提供保存路径
                    scanf("%s", targetFile);

                    printf("选择解密方式:\n");
                    printf("1. 异或解密\n");
                    printf("3. 其他解密方式\n");
                    printf("请选择:");
                    scanf("%d", &encryptionMethod);

                    if (encryptFile(sourcefile, secretKey, targetFile, encryptionMethod)) {
                        printf("文件[%s]解密成功,保存在[%s]。\n", sourcefile, targetFile);
                    }

                    if (redo() == 'a') {// 继续解密文件
                        system("cls");
                    } else {
                        break;// 回到主菜单
                    }
                }
                break;
            case 'c':
                while(1) {
                    struct stu {
                        char name[10];
                        int num;
                        int age;
                        char addr[15];
                    }
                    boya[2],boyb[2],*pp,*qq;
                    {
                        FILE *fp;
                        char ch;
                        int i;
                        pp=boya;
                        qq=boyb;
                        
                        //  这里文件模式修改下 
                        // https://blog.csdn.net/kangjianwei101/article/details/50517536
                        // https://blog.csdn.net/weixin_47423314/article/details/106200349
                        if((fp=fopen("D:\ceshi.txt","w+"))==NULL) {
                            printf("Cannot open file strike any key exit!");
                        }
                        printf("\ninput data\n");
                        for(i=0; i<2; i++,pp++) {
                            scanf("%s%d%d%s",boya[i].name,&boya[i].num,&boya[i].age,boya[i].addr);
                            // https://blog.csdn.net/shulianghan/article/details/117328308
                            // 使用fprintf()来格式化写入数据到文件 
                            fprintf(fp,"%s %d %d %s\n",boya[i].name,boya[i].num,boya[i].age,boya[i].addr);
                        }
                        pp=boya;
                        //fwrite(pp,sizeof(struct stu),2,fp);
                        //将文件指针重新指向一个流的开头
                        rewind(fp);
                    //    fread(boyb,sizeof(struct stu),2,fp);
                        printf("\n\nname\tnumber\tage\taddr\n");
                        for(i=0; i<2; i++,qq++) {
                            // 使用fscanf()从文件格式化读取数据 
                            fscanf(fp,"%s\t%d\t%d\t%s\n",boyb[i].name,&boyb[i].num,&boyb[i].age,boyb[i].addr);
                            printf("%s\t%d\t%d\t%s\n",boyb[i].name,boyb[i].num,boyb[i].age,boyb[i].addr);
                        }
                        fclose(fp);
                    }
                    if(redo() == 'a') { // 重新输入信息
                        system("cls");
                    } else { // 回到主菜单
                        break;
                    }
                }
                break;
            default:
                printf("没有相应的菜单!按任意键回到主菜单...");
                getch();
        }
    }

    return EXIT_SUCCESS;
}
/**
* 显示程序菜单
**/

void printMenu() {
    printf("***************** 文本加密解密软件 *****************\n");
    printf("*                                                  *\n");
    printf("*                                                  *\n");
    printf("*      请从下面的菜单中选择你要进行的操作:        *\n");
    printf("*      a. 文件加密                                 *\n");
    printf("*      b. 文件解密                                 *\n");
    printf("*      c. 将信息存放到文件中                       *\n");
    printf("*      z. 退出系统                                 *\n");
    printf("*                                                  *\n");
    printf("*                                                  *\n");
    printf("****************************************************\n");
}

/**
 * 加密/解密文件
 *
 * @param   sourcefile    要加密/解密的文件名
 * @param   secretKey     密钥
 * @param   targetFile    加密/解密后要保存的文件名
 *
 * @return  加密成功或失败的数字表示
     0:加密失败
     1:加密成功
**/
int encryptFile(char *sourcefile, char *secretKey, char *targetFile, int encryptionMethod) {
    FILE *fpSource, *fpTarget;// 要打开的文件的指针
    char buffer[21];// 缓冲区,用于存放从文件读取的数据
    int readCount,// 每次从文件中读取的字节数
        keyLen = strlen(secretKey),// 密钥的长度
        i; // 循环次数
// 以二进制方式读取/写入文件
    fpSource = fopen(sourcefile, "rb");
    if (fpSource == NULL) {
        printf("文件[%s]打开失败,请检查文件路径和名称是否输入正确!\n", sourcefile);
        return 0;
    }

    fpTarget = fopen(targetFile, "wb");
    if (fpTarget == NULL) {
        printf("文件[%s]创建/写入失败!请检查文件路径和名称是否输入正确!\n", fpTarget);
        return 0;
    }
// 不断地从文件中读取 keyLen 长度的数据,保存到buffer,直到文件结束
    while ((readCount = fread(buffer, 1, keyLen, fpSource)) > 0) {
        if (encryptionMethod == 1) { // 异或加密
            for (i = 0; i < readCount; i++) {
                buffer[i] ^= secretKey[i];
            }
        } else if(encryptionMethod==2) {
            // 位移加密
            for (i = 0; i < readCount; i++) {
                buffer[i] = buffer[i] + keyLen;
            }

        } else if(encryptionMethod==3) { // 因为位移加密和位移解密,无法共用一个处理方法,故新增一个模式来处理位移解密
            // 位移解密
            for (i = 0; i < readCount; i++) {
                buffer[i] = buffer[i] - keyLen;
            }
        }

        fwrite(buffer, 1, readCount, fpTarget);
    }

    fclose(fpSource);
    fclose(fpTarget);
    return 1;
}

char redo() {
    char action;
    printf("\n接下来你希望:\n");
    printf("a. 继续当前操作\n");
    printf("b. 回到主菜单\n");
// 不停的等待用户输入,直到输入正确
    while (1) {
        fflush(stdin);
        scanf("%c", &action);
        fflush(stdin);

        if (action != 'a' && action != 'b') {
            printf("没有相应的菜单,请重新选择。\n");
        } else {
            return action;
            break;
        }
    }
}




img