如何在C中使用sscanf()方法

如何在C中使用sscanf()方法,c,scanf,C,Scanf,我在这个代码中使用sscanf while(totalByte < sizeof(rdata)) { read(client_sockfd, &buffer[totalByte],1); printf("bytes[%d] : %x \n", totalByte, buffer[++totalByte]); } 有结果吗 然后使用sscanf方法 sscanf(buffer,"%d%d%c" ,&rdata.left_num, &rdat

我在这个代码中使用sscanf

while(totalByte < sizeof(rdata)) 
{   
    read(client_sockfd, &buffer[totalByte],1); 
    printf("bytes[%d] : %x \n", totalByte, buffer[++totalByte]);
}
有结果吗

然后使用sscanf方法

sscanf(buffer,"%d%d%c" ,&rdata.left_num, &rdata.right_num, rdata.op); 
printf("%d %c %d \n", ntohl(rdata.left_num),rdata.op,ntohl(rdata.right_num));
但是当打印rdata(结构)的值时,得到一个0值(初始值)

0 0

我知道sscanf方法拆分字符串并插入值

对我来说有什么误解吗

这就是我用的结构

struct cal_data 
{  
    int left_num;  
    int right_num;
    char op;  
    int result;  
    int error;  
}; 

sscanf
与许多其他C库函数一样,当字符串达到0(与“\0”相同)时,它停止迭代字符串。
字节
数组的第一个元素是0。因此,就sscanf而言,用于
sscanf
的输入字符串是
。要查看此行为的另一个示例,请在
while
循环后添加以下代码

printf("%s\n", bytes);
<>这不会打印任何东西(将打印一个空字符串),因为<代码> Prtff > <代码> sSCANF将考虑<代码>字节[0 ] < /代码>是字符串的结尾。


您可能应该使用类似的方法将数据读入结构-

根据函数描述():

第一个论点应该是:

但当您将每个字节打印为“十六进制整数”时:


第一个字节的值为0。所以如果你把它当作一个字符串,它就是一个空字符串。

我不认为这是你想要它做的:

printf("bytes[%d] : %x \n",totalByte, buffer[++totalByte]);
如果这是可行的,那么这是巧合。你不想依赖巧合,而不是逻辑,是吗?有关此处未定义行为的更多信息,请阅读。将其更改为此,并避免省略序列点,以便将来将逻辑塞入到一起:

printf("bytes[%d] : %x \n",totalByte, (unsigned int) buffer[totalByte]);
totalByte++;
然后使用sscanf方法
sscanf(缓冲区,“%d%d%c”、&rdata.left\u num、&rdata.right\u num、rdata.op)

你的错误检查在哪里?与大多数标准C函数一样,您的代码应该检查sscanf的返回值,以确保它提取了所需的信息量。如何确保sscanf成功处理两个十进制数字序列和一个字符?使用以下命令:

int n = sscanf(buffer,"%d%d%c" ,&rdata.left_num, &rdata.right_num, rdata.op);
if (n == 3) {
    /* sscanf extracted and assigned three values;
     * One for each of the format specifiers,
     * and variables you passed in. Success! */
    printf("%d %c %d \n", ntohl(rdata.left_num),rdata.op,ntohl(rdata.right_num));
}
else {
    /* sscanf failed to extract some values from the string,
     * because the string wasn't correctly formatted */
    puts("Invalid input to sscanf");
}
。。。现在你会明白问题所在了!sscanf失败了


正如其他人所指出的,字符串终止于第一个
'\0'
(或0)字节。传递给sscanf的指针指向一个空字符串。sscanf无法从空字符串中提取任何您想要的信息。

这有很多问题,甚至与
sscanf()
无关(我相信下面的答案会一目了然)。例:您认为在您选择的任何迭代中,第一个循环会打印哪个“字节”。具体来说,
printf(“字节[%d]:%x\n”,totalByte,buffer[++totalByte])
您认为这是在
缓冲区[totalByte]
转储字节吗?想打赌吗?@WhozCraig因为写了规则i chance buffer[totalByte]++总字节;缓冲区[++totalByte];这是未定义的行为。增量应该在
printf()
调用之外,除非它是参数列表中唯一出现的
totalByte
(它不是)。你第一次做对了。增量属于写入的参数列表之外。0不是“\0”。0是ASCII 48(dec.)@Koushik zero(
0x00
)或
0
打印为十进制是他所说的,他是对的。在代码中的什么地方,或者在这个答案中,您是否看到对字符
'0'
(即您所指的ASCII#48)的任何引用?@Koushik-'0'在ASCII中是48\0'是0。试试这个-
printf(“%d\n”、“\0”)@WhozCraig他正在以十进制格式打印。以文本格式输出到标准输出。因此,将0转换为ascii以在标准输出上打印。当我们读取相同的值时,我们实际上是在读取格式化为十进制值的acsii值。是吗?@Koushik在
printf()
中转换后,它作为ASCII字符转储到stdout。正是因为它不是由
sscanf()
使用的输入缓冲区中的ASCII
'0'
,所以它失败了,这就是这个答案的要点(也是它正确的原因)。缓冲区显示为
sscanf()
,好像它是一个空字符串,因为呈现给数据解析器的第一个字节是0x00(即空终止符)。我希望这是清楚的。它肯定会破坏协议。否则,你认为哪一部分是不可移植的?对齐和?没有一部分是可移植的。即使假设您解决了填充和打包问题,您仍然存在潜在的endian问题。这些都是您不通过网络发送数据结构的主要原因。您开发了一个数据协议,使其便于携带,并生成定义良好的字节流。此外,请不要使用C++网站作为C参考,特别是C++网站。考虑Google的“一个与C.@生相关的综合手册”,我认为填充细节没有标准化。尽管你的代码可能在很多平台上都能工作。答案是正确的,但如果读者想更好地理解代码不正确的原因,那么查找和链接序列指针答案的额外里程最终将对他们有所帮助。
printf("bytes[%d] : %x \n", totalByte, buffer[++totalByte]);
printf("bytes[%d] : %x \n",totalByte, buffer[++totalByte]);
printf("bytes[%d] : %x \n",totalByte, (unsigned int) buffer[totalByte]);
totalByte++;
int n = sscanf(buffer,"%d%d%c" ,&rdata.left_num, &rdata.right_num, rdata.op);
if (n == 3) {
    /* sscanf extracted and assigned three values;
     * One for each of the format specifiers,
     * and variables you passed in. Success! */
    printf("%d %c %d \n", ntohl(rdata.left_num),rdata.op,ntohl(rdata.right_num));
}
else {
    /* sscanf failed to extract some values from the string,
     * because the string wasn't correctly formatted */
    puts("Invalid input to sscanf");
}