- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个函数读取 unsigned long long 中的每一位并将值存储在数组中,现在我想将此函数转换为返回数字中的下一位并将数据处理留给调用者的函数.
理想情况下,它的工作方式与 getc() 类似,我可以在其中执行以下操作:
int n;
while((n = getbit()) != NULL)
...
我知道静态索引变量是一个选项,但这不是很优雅。有没有更实用的方法来做到这一点?
最佳答案
很像 FILE
结构包裹了输入的各种状态,例如缓冲、错误状态等,您可以用一个简单的包裹提取位所需的状态结构:
// Struct used to manage reading bits from a file
struct bitstream
{
FILE *fp;
unsigned char ch; // current char
unsigned char mask; // next bit mask
unsigned char mask0; // first bit mask
};
这会维护正在读取的 FILE
,跟踪从该文件读取的最后一个字符,并管理一次将选择一位的位掩码。因为不同的应用程序可能需要特定的 bit order (LSB->MSB 或 MSB->LSB),为此使用了一个额外的成员 mask0
。您稍后会看到它是如何使用的。
首先,您需要一个函数来设置此结构,准备好执行操作。让我们有两个函数,它们明确选择所需的位顺序:
// Initialize a bitstream where bit ordering is LSB -> MSB
void bitstream_init_lsb(struct bitstream* bs, FILE *fp)
{
struct bitstream bs_init = { fp };
bs_init.mask0 = 1u;
*bs = bs_init;
}
// Initialize a bitstream where bit ordering is MSB -> LSB
void bitstream_init_msb(struct bitstream* bs, FILE *fp)
{
struct bitstream bs_init = { fp };
bs_init.mask0 = 1u << (CHAR_BIT - 1);
*bs = bs_init;
}
注意这两个函数中mask0
的区别。对于 LSB 优先级,mask0
是最低位。对于 MSB 优先级,mask0
是最高位。在这两种情况下,ch
和 mask
都是零初始化的。我们可以依靠 mask
的零值来指示已从 ch
中读取所有位,并且我们必须从文件中读取下一个字节。
这将起作用的方式是,每次您阅读一点时,您都会在适当的方向(向左或向右,取决于选择的顺序)移动掩码。在任何一种情况下,当位被移位超出其存储能力时,掩码将再次变为零。然后您知道是时候读取下一个字节了。
请注意,上述逻辑明确依赖于 mask
是 unsigned char
类型。这很重要。
// Get next bit (0 or 1) from bitstream, or EOF
int bitstream_get(struct bitstream *bs)
{
// Get next character when next bit is zero
if (bs->mask == 0) {
int ch = fgetc(bs->fp);
if (ch == EOF) {
return EOF;
}
bs->ch = (unsigned char) ch;
bs->mask = bs->mask0;
}
// Get next bit
int result = (bs->ch & bs->mask) ? 1 : 0;
if (bs->mask0 == 1u) {
bs->mask <<= 1;
} else {
bs->mask >>= 1;
}
return result;
}
感谢chux - Reinstate Monica对于他们的建议improvements到我原来的答案。以上是一个修订版,合并了这些更改并明确实现了位排序。
要使用它,您只需使用有效的 FILE*
进行初始化,然后像使用 fgetc
一样执行读取循环:
int bit;
struct bitstream bs;
bitstream_init_msb(&bs, stdin);
while (EOF != (bit = bitstream_get(&bs)))
{
// ...
}
这是一个现场演示:https://godbolt.org/z/KdEMoTavh
关于c - 我如何编写像 getc() 这样的函数来一次读取一位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72877694/
根据“未定义行为”的现代解释,编译器有权假设不会发生导致未定义行为“不可避免”的事件链,并且可以消除仅适用于以下情况的代码:将执行未定义的行为;这可能会导致未定义行为的影响及时倒退,并使原本可以观察到
在阅读 getc 手册页时,我遇到了: may be implemented as a macro which evaluates stream more than once. 那么,getc 也可以
程序有什么问题? #include #include #include main( ) { char * buf="robot.c"; char c;int i=0; FILE*f
在下面的代码中,我尝试存储文件中的所有字符(包括换行符)。如果读取换行符,变量“i”应该递增,“j”重置为 0,但这种情况不会发生。通过从我的数组打印到控制台,我已经确认换行符实际上正在被读取和存储。
它只是一个程序,我试图读取文件中作为参数传递的单词的出现次数,该文件也作为下一个参数传递。 代码如下所示: #include extern void exit(int); void main(int
我正在用 C 开发一个链表。我正在从一个 txt 文件中获取数据。但是当我尝试运行该程序时,它给我一个 getc() 的段错误这是代码, #include #include struct node{
程序: #include #include char *f_gets(char *s, int n, FILE *iop) { int c=0; char *cs; cs =
我试图找到 getc 和 fgetc 之间的区别。当时我看到这样的说法: The difference between getc and fgetc is that getc can be imple
我正在使用 Perl 6 模块 Term::termios . #!/usr/bin/env perl6 use v6; use Term::termios; my $saved_termios :=
我有一个函数读取 unsigned long long 中的每一位并将值存储在数组中,现在我想将此函数转换为返回数字中的下一位并将数据处理留给调用者的函数. 理想情况下,它的工作方式与 getc()
我有一个函数读取 unsigned long long 中的每一位并将值存储在数组中,现在我想将此函数转换为返回数字中的下一位并将数据处理留给调用者的函数. 理想情况下,它的工作方式与 getc()
我有一个函数 getNum(),它从文件中获取一个数字并返回它。当我回到 getNum() 时,我丢失了指针,它再次从文件的开始处开始。我想知道如何获取 getc 所在的位置,然后返回到那个地方。我在
所以我开始实现霍夫曼树,为此,我尝试从标准输入或输入文件获取字符值。输入文件(只是一个字符串“cheese”)被添加到数组 freqcounts 中,其中添加的 freqcounts 索引是它读取的字
我遇到的问题是在这一行: int tok = getc(fp); getc 返回 -1。为什么?提前致谢。 #include #include #include "file_reader.h" /
printf("hello2"); int i = 0; int done = 0; while (!done) { char c; printf("hello3"); c =
我正在阅读 Jim Trevor 等人所著的Cyclone:C 的安全方言。一切都是为了编程语言类(class)。作者表示,如果调用 getc(null) 可能会导致段错误,因为 C 标准没有指定如何
当我尝试从名为“file1”的文件中读取输入时,我的程序正确显示文件中的字符数,但采用无法识别的字符格式。下面是代码 #include #include void db_sp(FILE*); in
// Program to remove the comments and the spaces from the given input file #include #include using
这是我的代码。 #include #include int main(int argc,char** argv) { char a; a=9; FILE * fp; f
我正在尝试用 C 编写一个简单的“猫”克隆。我正在运行 Windows 7 并使用 MinGW 编译器。但是,每当我运行该程序时,它都会返回文本文件,但每个字符都替换为“☺”字符。提前谢谢你。 #in
我是一名优秀的程序员,十分优秀!