查找不可打印字符并在C中打印出其十六进制形式

查找不可打印字符并在C中打印出其十六进制形式,c,string,state-machine,C,String,State Machine,我目前有一个有限状态机,它分析一个长字符串,用空格分隔长字符串,并将每个标记分析为八进制、十六进制、浮点、错误等 以下是我如何分析每个令牌的简要概述: enum state mystate = start_state; while (current_index <= end_index - 1) { // iterate through whole token switch (mystate) { case 0: // analyze f

我目前有一个有限状态机,它分析一个长字符串,用空格分隔长字符串,并将每个标记分析为八进制、十六进制、浮点、错误等

以下是我如何分析每个令牌的简要概述:

enum state mystate = start_state; 

while (current_index <= end_index - 1) { // iterate through whole token
    switch (mystate) {
        case 0:
            // analyze first character and move to appropriate state
            // cases 1-5 represent the valid states, if error set mystate = 6
        case 6: // this is the error state
            current_index = end_index - 1; // end loop
            break; 
    }
    current_index++;
}
现在,我应该以十六进制形式打印0x20及以下的不可打印字符,例如文本开头、标题开头等,例如[0x02]和[0x01]。我在这里找到了0x20和下面的ASCII不可打印字符的良好列表:

首先,我对如何在命令行中输入不可打印的字符感到困惑。如何键入不可打印的字符作为命令行参数供程序分析

在这个障碍之后,我知道不可打印字符将进入状态6,即我的错误状态。所以我必须稍微修改我的错误状态if语句。下面是我如何在伪代码中实现这一点的思考过程:

if (mystate == 6) {
    if (token is equal to unprintable character) {
        // print hex form, use 0x%x for formatting
    } else {
        // still error, but not unprintable so just have original error statement
        fprintf(stdout, "Error: \" %s \" is invalid\n", token); 
    }
}
我的另一个想法是:

if (mystate == 6) {
    if (the token's hex value is between 0x01 and 0x20) {
        // print hex form, use 0x%x for formatting
    } else {
        // still error, but not unprintable so just have original error statement
        fprintf(stdout, "Error: \" %s \" is invalid\n", token); 
    }
}

你的拼图中有一块是用十六进制打印的

Printf("%02x", 7);
这将打印两位十六进制值07

另一件是检测不可打印的内容

If(c<20)

这将转换为字符具有小于空格的任何值

您可以研究isprint函数,因为有些无法打印的字符大于空格


祝你好运。欢迎来到c.

,您可以使用一个理智的libc

#include <ctype.h>
...
if (!isprint((int)ch) {
    unsigned x = ch;
    printf ("[0x%02x]", 0xff&(int)ch);
}
...
在这里您可以看到STX字符。顺便说一句,有一个关于ascii的优秀手册页(
ascii(7)

因此,作为一个完整的命令行:

YOUR_Program "`printf '\x02\x03\x18\x19'`"
(xxd只是显示printf的结果,因为它是不可打印的)。xxd只是一个hextump实用程序,类似于od

注意:当您确实需要不可打印的输入时,从文件或stdin获取输入更为方便。这简化了程序调用:

printf '\x02\x03\x18\x19'|YOUR_Program

我仍然有点困惑如何使用命令行参数printf。我认为我没有正确格式化十六进制,因为当我尝试输入'\x02'| xxd'时,它打印出十六进制代码0x6a758c8d。我显然做错了什么,例如,如何正确地以0x02的形式获取它。@Bret
xxd
应该通过管道显示printf命令的结果。明白了。所以我输入了./myprogramname“
printf'\x02\x03\x18\x19'
”(并继续测试\x04到\x20)。现在,我需要一些关于错误检查中print语句格式的帮助。我一直得到很长的十六进制数,比如0x76149c8e,而不是正确的0x02到0x20格式。我目前有:fprintf(标准输出,“错误:\%s\”无效,十六进制:[0x%02x]\n],令牌,令牌)@Bret输出看起来好像令牌是指针而不是字符(或整数)<代码>%s需要
字符*
类型。我想那是你的
标记。然后通过
(int)标记[0]
获得第一个字符。所以它看起来像是
printf(“\%s\”有无效的十六进制代码[0x%02x]\n”,标记,(int)标记[0])
:1)使用带符号的
char
ch<0
,则肯定会打印出4或8个十六进制数字。2)重复使用可打印文本字符串的输出可能无法与不可打印文本字符串区分。
“0d”
“\n”
输出相同的字符。
%02x“
至少打印两个十六进制数字。如果字符的值小于0,则将打印两个以上的数字。建议
printf(“%02hhx”,7);
printf(“%02x”,无符号字符)ch);
YOUR_Program "`printf '\x02\x03\x18\x19'`"
printf '\x02\x03\x18\x19'|YOUR_Program