【问题标题】:C couldn't read a fileC 无法读取文件
【发布时间】:2020-07-05 02:01:48
【问题描述】:

我有一个关于从文件中解密秘密消息的作业。我需要读取文件并转换字符以进行解密,但我什至无法启动 decrypt_and_print(char*) 函数。为了测试它,我放置了控制线,但是当我运行代码时,它没有写任何东西,也没有完成过程。我不知道为什么会发生这种情况我在 c 有点新。这是我的代码:

#include <stdio.h>
void decrypt_and_print(char*);
int main(){
        char* file_name = "/home/baran/hw4/encrypted_p1.img";
        decrypt_and_print(file_name);
        return 0;
}
void decrypt_and_print(char* file_name){
        FILE *f = fopen(file_name,"r");
        if(f == NULL){
                printf("Couldn't open file!");
        }else{
                printf("File opened sucesfully!");
        }
        char a;
        fscanf(f,"%ch",&a);
        while(fscanf(f,"%ch",&a) == 1){
                switch(a){
                        case '0':{printf(" ");break;}
                        case '1':{printf("-");break;}
                        case '2':{printf("_");break;}
                        case '3':{printf("|");break;}
                        case '4':{printf("/");break;}
                        case '5':{printf("\\");break;}
                        case '6':{printf("O");break;}
                        default:printf("\n");
                }
        }
}

【问题讨论】:

  • 在这些调试字符串的末尾添加换行符以刷新输出。超级骗子:(
  • while(1) 很好地表明您陷入了循环。 fscanf 可能没有读取任何数据(它已经到达文件末尾),并且 a 中剩余的值大于 6,因此没有一个案例被命中。检查 fscanf 返回的值。
  • 很有可能名为*.img 的文件不是文本数据,因此将%d 与scanf 一起使用是错误的读取方式。
  • 您需要在您的案例中使用break 语句以避免失败。
  • 啊。如果您的输入看起来像“111324”,那么带有 %d 的 scanf 将读取非常大的整数。你应该停止使用 scanf 而只使用fgetc 这样你一次只能读取一个字符。

标签: c string file pointers io


【解决方案1】:

以下建议的代码:

  1. 干净编译
  2. 使用有效格式字符串调用fscanf()
  3. 执行所需的功能
  4. 在无法打开文件时通过stderr 通知用户
  5. 在 `printf() 中使用 '\n' 跟踪格式字符串,因此每个字符都在一个新行上
  6. 打印switch() 语句中尚未处理的任何字符的数值。
  7. 遵循公理:每行只有一个语句,并且(最多)每个语句有一个变量声明。
  8. 记录为什么要包含 stdlib.h 头文件
  9. 如果对fopen() 的调用失败,则正确退出,而不是尝试从(未打开的)文件中读取

现在,建议的代码:

#include <stdio.h>
#include <stdlib.h>   // exit(), EXIT_FAILURE

void decrypt_and_print(char*);

int main( void )
{
        char* file_name = "/home/baran/hw4/encrypted_p1.img";
        decrypt_and_print( file_name );
        return 0;
}


void decrypt_and_print( char* file_name )
{
    FILE *fp = fopen( file_name, "rb" );
    if( !fp )
    {
         perror( "fopen faiied" );
         exit( EXIT_FAILURE );
    }

    printf("File opened successfully!");

    char a;

    while( fscanf(fp, "%c", &a ) == 1 )
    {
        switch( a )
        {
            case '0': 
                printf( " \n" );
                break;

            case '1':
                printf( "-\n" );
                break;

            case '2':
                printf( "_\n" );
                break;

            case '3':
                printf( "|\n" );
                break;

            case '4':
                printf( "/\n" );
                break;

            case '5':
                printf( "\\\n" );
                break;

            case '6':
                printf( "O\n" );
                break;

            default:
                printf( "char: %d ignored\n", (int)a );
                break;
        }
    }
}

建议修改,以便它需要一个带有文件路径/名称的命令行参数,而不是依赖于硬编码的路径/名称

建议更换

int main( void )
{
    char* file_name = "/home/baran/hw4/encrypted_p1.img";

int main( int argc, char* argv[] )
{
    char *file_name;
    if( argc < 2 )
    {
        file_name = "/home/baran/hw4/encrypted_p1.img";
    }
    else
    {
        file_name = argv[1];
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-30
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 2020-07-24
    • 2013-04-01
    • 2019-10-23
    相关资源
    最近更新 更多