情况:我有一个 C 程序,它接受一个字符串参数并对其进行处理(细节不相关。)我想向它传递一个包含控制字符的字符串,例如 EOF、CR 或 LF,并且无法切换我的键盘在终端中的原始输入模式。我的问题是:C 是否有任何功能可以让我以某种方式指示或“键入”字符?(例如,在某些语言中创建字符串时,您可以用斜杠转义字符或指示其十六进制代码。我想知道在从终端内向 C 程序传递参数方面是否存在类似的情况 - 所以我在问特别是命令行参数。)
问问题
1669 次
3 回答
1
您可能想学习如何在 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;
}
让我们按照上面提到的帖子中的说明将二进制参数传递给它。
./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 <- ` '
argv[0] 是我们程序binargs
本身 的名称
argv[1] 是一个常规字符串“ABC”
argv[2] 与 argv[1] 相同,但为十六进制
argv[3] 是两个控制字符的序列:HT LF
请注意,它使用传统的 Unix 方式来引用每个字符,因此我们可以在打印时看到不可打印字符的边界:
./binargs $'\a\b\v\f'
(让我们跳过 argv[0] 部分)
argv[1]= 0x07 <- `' 0x08 <- ' 0x0B <- ` ' 0x0C <- ` '
或者我们可以通过管道将其发送到cat -v
./binargs $'\a\b\v\f' | cat -v
这使得结果更具可读性:
argv[1]=^G^H^K^L 0x07 <- `^G' 0x08 <- `^H' 0x0B <- `^K' 0x0C <- `^L'
于 2017-02-16T14:14:07.440 回答
0
在这种情况下,您需要非常清楚功能的位置。处理可能会或可能不会由调用您的程序的命令行解释器完成。根据您使用的是 DOS 命令行、Linux 还是 Unix 等,您可能会从相同的 C 代码中得到不同的结果。
于 2013-05-01T21:08:26.917 回答
0
如果您对能够通过转换函数发送 C 字符串样式的转义序列感到满意,只要您不在输入中间使用引号,以下可能对您有用。如果您需要在输入中间使用引号,则必须弄清楚您的 shell 使用什么转义序列来通过命令行参数传递引号。
#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");
}
于 2013-05-01T22:55:43.823 回答