c - sscanf() 通过更改 for 循环的索引值导致无限循环
问题描述
功能:
void input_bytes(unsigned char bytes[], int num_bytes)
{
const int CHAR_PER_BYTE = 2; /* expects hex input */
const int STRING_SIZE = num_bytes * CHAR_PER_BYTE;
char input_string[STRING_SIZE + 1]; /* + 1 for null char */
int ind;
unsigned char byte;
fgets(input_string, STRING_SIZE + 1, stdin);
printf("after fgets\n");
for (ind = 0; ind < num_bytes; ind++)
{
printf("top of loop, ind: %d\n", ind);
sscanf(input_string, "%2x", &byte);
bytes[ind] = byte;
printf("bottom of loop, ind: %d\n", ind);
}
printf("\n\n");
}
司机:
int main()
{
unsigned char bytes[5];
input_bytes(bytes, 5);
}
输出:
after fgets
top of loop, ind: 0
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
...
用gcc driver.c -o driver
.
出于好奇,我在循环中放了一个ind++
,它在顶部是 2,在底部是 1。如果我sscanf()
取出它就会终止。
解决方案
格式对应的变量%x
必须是int
,不是char
。使用错误的类型会导致未定义的行为;在您的程序中,它正在写入0
,ind
因此循环永远不会停止。
to的size
参数fgets()
应该是缓冲区的大小,不加 1。fgets()
将减去 1 以获得它在 null 之前可以读取的字符数。您应该将 1 的大小加 1 input_string
,而不是 的参数fgets()
。
fgets()
还包括它返回的输入中的换行符,您还需要为此添加空间input_string
。
如果要转换输入中的所有字节,则需要在input_string
每次循环中从不同的索引进行扫描。
void input_bytes(unsigned char bytes[], int num_bytes)
{
const int CHAR_PER_BYTE = 2; /* expects hex input */
const int STRING_SIZE = num_bytes * CHAR_PER_BYTE + 2; // + 2 for newline and null byte
char input_string[STRING_SIZE];
int ind;
unsigned int byte;
fgets(input_string, STRING_SIZE, stdin); /* + 1 for null char */
printf("after fgets\n");
for (ind = 0; ind < num_bytes; ind++)
{
printf("top of loop, ind: %d\n", ind);
sscanf(&input_string[2*ind], "%2x", &byte);
bytes[ind] = byte;
printf("bottom of loop, ind: %d\n", ind);
}
printf("\n\n");
}
由于您实际上并未对input_string
. 您可以将其精确地num_bytes * CHAR_PER_BYTE
设置为字符长,而无需为换行符和 null 添加空间。而不是使用fgets()
,使用fread()
来准确读取您想要的字符数:
fread(input_string, CHAR_PER_BYTE, num_bytes, stdin);
推荐阅读
- asterisk - 有没有办法使用非数字用户名向 Asterisk 注册 cisco7940 硬电话?
- java - 如何使用 spring 框架检索 firestore 中的子集合?
- android - 从地方api android获取照片
- react-native - 覆盖在顶部或上方
- c# - Microsoft 服务:XmlDocument.Load 无法创建 SSL/TLS 安全通道
- emacs - emacs defun 插入不需要的文本
- c++ - 传递模板对象
- php - 捕获自定义会话处理程序引发的异常
- ionic-framework - ion-slide 和 modal 的 ionic 4/5 问题
- ecmascript-6 - 等待所有承诺在 forEach 循环中解决