【问题标题】:Using getchar() to read from file使用 getchar() 从文件中读取
【发布时间】:2020-12-01 22:13:54
【问题描述】:

我有一个任务,基本上我想使用getchar() 从音频文件中读取所有字节,如下所示: while(ch = getchar()) != EOF) 在某些时候,我必须读取代表 文件大小 的 4 个连续字节,但我无法理解以下内容: 例如,如果我的程序正在读取的文件大小为 150 字节,则足以存储在 4 个字节中的 1 个字节中,这意味着在这种情况下,3 个字节将为 0,最后一个字节将为 150。我知道我需要通过上述 cod 部分中的 4 次 while 重复来读取所有 4 个字节,以获得我需要的所有信息,但是 getchar() 究竟是什么将返回到我的变量,因为它返回它刚刚读取的字符的 ASCII 码? 此外,对于无法存储在单个字节中的较大数字会发生什么?

【问题讨论】:

  • 如果文件中的某个数据字段包含四个字节,则需要读取所有四个字节才能获取所有数据。即使这四个字节的组合值可以放入更小的类型,文件中的数据仍然是四个字节。此外,除非您实际读取所有四个字节并以合适的方式组合它们,否则您甚至都不知道该值。
  • 在使用基于字符的函数读取任意字节时也要小心。首先要记住getchar 返回一个int。然后记住char 类型的“字符”可以是signed unsigned,一般来说,在处理原始字节(而不是实际字符)时,您需要显式使用无符号类型(即unsigned char,或者更好的是uint8_t)。
  • 请花点时间阅读the help pages,阅读SO tour,阅读How to Ask,以及this question checklist。如前所述,请了解如何edit您的问题。
  • 您是否涵盖了诸如数组之类的内容和/或诸如charint 等变量类型的位的确切组成部分?字节序如何?因为用getchar() 读取4 个值并在所有情况下获得正确的组合值实际上很难正确完成。它还取决于数据是如何写入文件的 - 您的老师必须提供该信息以确保您获得正确的结果。
  • 同样,ASCII 是编码 文本 的标准。二进制文件不是文本。 ASCII 不相关。对于一个 1 MB 的文件,试着写出一个代表这个大小的 4 字节整数的样子。它将包含哪些字节值?你能从它的单个字节值重构整数,将其视为小整数吗?

标签: c file getchar


【解决方案1】:

由于我没有足够的声誉,因此无法发表评论,我对您的问题深感困惑,因为我不明白您的意思或您要达到什么目的 函数 getChar() 应该用于一次返回一个字节,实际上只有在阅读您的问题后,我才检查手册以了解它读取的内容不止一个,尽管从我的经验和我现在执行的测试看来用于读取多字节字符,这是我用来检查它的简单代码

    char * c;
    printf("Enter character: ");
    c = getchar();
    printf("%s",c);

我使用的字符可能会取消格式化是我在 polybar 中使用的堆栈溢出字形溜,这里显示为亚洲字符。

不仅如此,fgets 将在到达文件末尾时(或发生错误时)返回 EOF,如 linux 手册中所述 https://linux.die.net/man/3/getchar

此外,进一步阅读它取决于文件如何存储数据,如果它的大端读取的第一个字节将为 0,0,0,150,否则如果它的小端将是 150,0,0,0 但这是假设当时正在读取 1 个字符,而不是像您描述的那样一次读取 4 个字符

至于您的问题的“解决方案”,为什么不使用 fread() 一次读取 4 个字节或在它正常工作时使用它的派生词?

编辑 正如评论所要求的那样,下面的值按位“连接”我使用 scanf 的值,因为我懒得手动检查每个 ASCII 键,这假设文件是​​大端,即 0,0,0,150 否则反转顺序

#include <stdio.h>
#include <stdlib.h>
unsigned char c[4];
unsigned int dosomething(){
    unsigned int result=0;
    result= (unsigned int)c[0]<< 24 | (unsigned int)c[1]<< 16 | (unsigned int)c[2]<< 8 | (unsigned int)c[3];
    return result;
}
int main(int argc, char const *argv[]){
    
    for (size_t i = 0; i < 4; i++)
    {
        printf("Enter character: ");
        scanf ("%u", &c[i]);
        printf("%u\n", c[i]);
        //printf("%s",c);
    
    }
    printf("%u",dosomething());
    
  
    return 0;
}

现在对于 fread,它的用法如下 fread(pointertodatatoread, sizeofdata, sizeofarray, filepointer); 为了深入了解这里是手册: https://www.tutorialspoint.com/c_standard_library/c_function_fread.htm 这应该在不同的线程中问,因为我觉得我在问另一个问题

【讨论】:

  • 作业实际上是关于正确使用 getchar() 和 putchar() 函数。
  • @MantzouPitsou ive 在多次阅读您的问题后编辑了我的回复
  • 很抱歉我没有阅读您的编辑。该文件是 little-endian 并且不是 getchar() 用于一次读取一个字节还是我弄错了?
  • 是的,是的,问题是一个字符可以占用一个以上的字节,这就是为什么 getchar() 返回一个 int 字形并且某些字符占用一个以上的字节,这就是为什么 fread 可以解决这个问题问题,因为你可以告诉它一次可以读取多少字节
  • 我实际上不知道如何使用 fread() 但在这种情况下它似乎非常有用,所以我希望我可以在这个作业中使用它。但是,如果我有一个更大的文件(例如 1MB),那么它的大小将存储在一个以上的字节中。那么我怎样才能使用 getchar 阅读整个内容)?
【解决方案2】:

如果我的程序正在读取的文件大小为例如 150 个字节,则足以存储在 4 个字节中的 1 个字节中,这意味着其中 3 个字节将为 0,最后一个字节将为 150案子。我知道我需要读取所有 4 个字节才能获得我需要的所有信息,但是 getchar() 究竟会返回我的变量,因为它返回刚刚读取的字符的 ASCII 码?

getchar 对 ASCII 一无所知。如果它无法读取字节,它会返回它读取的字节的数值,或者一个特殊的代码,由EOF 表示。如果您将字节视为 ASCII 代码,那么这是解释的问题。

因此,如果您的文件大小编码为三个零字节,后跟一个值为 150 的字节,那么 getchar() 将在四个连续调用中将其返回为 0、0、0 和 150。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 2016-04-15
    相关资源
    最近更新 更多