如何将控件或非打印字符传递给C程序?

如何将控件或非打印字符传递给C程序?,c,command-line-arguments,control-characters,C,Command Line Arguments,Control Characters,情况:我有一个C程序,它接受一个字符串参数并对其执行操作(细节不相关)。我想向它传递一个包含控制字符(如EOF、CR或LF)的字符串,并且不能在终端中将键盘切换到原始输入模式。我的问题是:C是否有任何功能允许我以某种方式指示或“键入”字符?(例如,在某些语言中生成字符串时,您可以用斜杠转义字符或指示其十六进制代码。我想知道,在从终端向C程序传递参数方面是否存在类似的情况,因此我专门询问命令行参数。)在这种情况下,您需要非常清楚功能所在。处理可能由调用程序的命令行解释器完成,也可能不由命令行解释器

情况:我有一个C程序,它接受一个字符串参数并对其执行操作(细节不相关)。我想向它传递一个包含控制字符(如EOF、CR或LF)的字符串,并且不能在终端中将键盘切换到原始输入模式。我的问题是:C是否有任何功能允许我以某种方式指示或“键入”字符?(例如,在某些语言中生成字符串时,您可以用斜杠转义字符或指示其十六进制代码。我想知道,在从终端向C程序传递参数方面是否存在类似的情况,因此我专门询问命令行参数。)

在这种情况下,您需要非常清楚功能所在。处理可能由调用程序的命令行解释器完成,也可能不由命令行解释器完成。根据您使用的是DOS命令行,还是Linux或Unix等,同一个C代码可能会得到不同的结果。

如果您对能够通过转换函数发送C字符串样式的转义序列感到满意,则以下方法可能适用于您,只要您不在输入中间使用引号。如果在输入中间需要引号,则必须确定shell通过命令行ARGs传递引号的转义序列。

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

// Unescapes 'str' in place, collapsing it back on itself, and
// returns the resulting length of the collapsed buffer.  Handles
// mid-buffer nul characters (0x00).  You can easily add your own
// special escape sequences if you wish.  Just be sure that no escape
// sequence translates into more characters than it takes to encode
// the escape sequence itself in the original string.
int unescape(char* str)
{
    char *out, *in;
    int len=0;
    in = out = str; // both start at the same place
    while(*in)
    {
        char c = *in++;
        if (c != '\\')
            *out++ = c; // regular, unescaped character
        else
        {                   // escaped character; process it...
            c = *in++;
            if      (c == '0') *out++ = '\0';
            else if (c == 'a') *out++ = '\a';
            else if (c == 'b') *out++ = '\b';
            else if (c == 'f') *out++ = '\f';
            else if (c == 'n') *out++ = '\n';
            else if (c == 'r') *out++ = '\r';
            else if (c == 't') *out++ = '\t';
            else if (c == 'v') *out++ = '\v';
            else if (c == 'x'  // arbitrary hexadecimal value
                    && isxdigit(in[0]) && isxdigit(in[1]))
            {
                char x[3];
                x[0] = *in++;
                x[1] = *in++;
                x[3] = '\0';
                *out++ = strtol(x, NULL, 16);
            }
            else if (c>='0' && c<='3' // arbitrary octal value
                    && in[0]>='0' && in[0]<='7'
                    && in[1]>='0' && in[1]<='7')
            {
                *out++ = (c-'0')*64 + (in[0]-'0')*8 + (in[1]-'0');
                in += 2;
            }
            else // any other char following '\' is just itself.
                *out++ = *in++;
        }
        ++len; // each time through the loop adds one character
    }
    *out = '\0';
    return len;
}

void print_buf(const char* buf, int len)
{
    int col;
    unsigned char* cp = (unsigned char*)buf;
    for (col=0; len>0; --len, ++col)
        printf(" %02x%s", *cp++, ((col&16==15) ? "\n" : ""));
}

int main(int argc, char*argv[])
{
    char* str;
    int len;

    if (argc<2)
    {
        fprintf(stderr, "First arg must be a string, "
                "and it probably ought to be quoted.\n");
        exit(1);
    }

    printf("\nInput string: \"%s\"\n", argv[1]);
    print_buf(argv[1], strlen(argv[1]));

    str = malloc(strlen(argv[1]));
    strcpy(str, argv[1]);
    len = unescape(str);
    printf("\nunescape() produces the following:\n");
    print_buf(str, len);
    free(str);

    printf("\n");
}
#包括
#包括
#包括
//将“str”放在适当的位置,将其折叠回自身,然后
//返回折叠缓冲区的结果长度。处理
//中间缓冲区nul字符(0x00)。您可以轻松地添加自己的
//特殊的转义序列,如果你愿意的话。只要确保没有人能逃脱
//序列转换成的字符数超过了编码所需的字符数
//原始字符串中的转义序列本身。
int unescape(字符*str)
{
字符*输出,*输入;
int len=0;
in=out=str;//两者都从同一个位置开始
while(*in)
{
字符c=*在++中;
如果(c!=“\\”)
*out++=c;//规则的、未换格的字符
其他的
{//转义字符;处理它。。。
c=*在++中;
如果(c='0')*out++='\0';
如果(c='a')*out++='\a';
如果(c='b')*out++='\b';
如果(c='f')*out++='\f';
如果(c='n')*out++='\n';
如果(c='r')*out++='\r';
如果(c='t')*out++='\t';
如果(c='v')*out++='\v';
else if(c=='x'//任意十六进制值
&&isxdigit(在[0]中)和&isxdigit(在[1]中)
{
charx[3];
x[0]=*在++中;
x[1]=*在++中;
x[3]='\0';
*out++=strtol(x,NULL,16);
}
else if(c>='0'&&c='0'&&in[0]='0'&&in[1]0;--len,++col)
printf(“%02x%s”,*cp++,((col&16==15)?”\n:“);
}
int main(int argc,char*argv[])
{
char*str;
内伦;

如果(argc您可能想了解如何在bash中将二进制数据作为参数传递。请参阅

这是一个C语言的简短演示。该程序以十六进制格式逐字符打印传递给它的每个参数

/* compile with cc -o binarg binargs.c */

#include <stdio.h>

int main(int argc, char *argv[])
{
    int i;
    char *ip;
    printf("\n");
    for(i=0; i<argc; i++)
    {
        printf("argv[%d]=%s\n",i,argv[i]);
        for(ip=(char*)argv[i]; *ip!=0; ip++)
        {
            printf("0x%02X <-\t`%c'\n",*ip,*ip);
        }
        printf("\n");
    }
    return 0;
}
结果:

(让我们跳过argv[0]部分)

这使得结果更具可读性:

argv[1]=^G^H^K^L

0x07这通常有热键(Ctrl+D=EOF等)。请检查终端应用程序中是否有合适的热键。或者,如果您的意思是在C字符串中传递实际字符,您可以使用它的文本(“\r”、“\n”等)将其键入C字符串中。)。我指的是命令行参数。热键的问题是,除非我处于原始模式,否则它们不会键入字符。例如,Ctrl+D实际上会退出我所在的任何程序。如果您需要许多控制字符,那么这些可能不是处理程序中事情的最佳方法。是的……我仍然希望得到答案但我的问题是::)不幸的是,这就是一些控制字符的工作方式,因为它们是非标准的(“\n”vs“\r\n”),正在使用的shell以及终端设置也会对其产生影响。我怀疑,对于这个问题没有“可移植”的答案。
./binargs ABC $'\x41\x42\x43' $'\t\n'
argv[0]=./binargs
0x2E <- `.'
0x2F <- `/'
0x62 <- `b'
0x69 <- `i'
0x6E <- `n'
0x61 <- `a'
0x72 <- `r'
0x67 <- `g'
0x73 <- `s'

argv[1]=ABC
0x41 <- `A'
0x42 <- `B'
0x43 <- `C'

argv[2]=ABC
0x41 <- `A'
0x42 <- `B'
0x43 <- `C'

argv[3]=

0x09 <- `       '
0x0A <- `
'
./binargs $'\a\b\v\f'  
argv[1]=


0x07 <- `'
0x08 <- '
0x0B <- `
         '
0x0C <- `
         '
./binargs $'\a\b\v\f' | cat -v
argv[1]=^G^H^K^L
0x07 <- `^G'
0x08 <- `^H'
0x0B <- `^K'
0x0C <- `^L'