2013-05-01 6 views
1

Ситуация: У меня есть программа на C, которая принимает строковый аргумент и делает что-то полезное (подробности не актуальны.) Я хочу передать ему строку, содержащую контрольный символ, такой как EOF, CR или LF, и не может переключите мою клавиатуру в режим сырого ввода в терминале. Мой вопрос: имеет ли C функциональность, которая позволит мне указать или «набрать» символ каким-то образом? (Например, вы можете избегать символов с косой чертой или указывать свои шестнадцатеричные коды при создании строк на некоторых языках. Мне интересно, существует ли что-то подобное в отношении передачи аргументов программе C из терминала, поэтому я спрашиваю о аргументы командной строки.)Как передать управляющий или непечатаемый символ программе C?

+3

Есть, как правило, горячие клавиши для этого (Ctrl + D = EOF, и т.д ...) проверить приложение терминала для соответствующего из них. Или если вы имеете в виду передачу фактического символа в C-строке, вы можете просто ввести его в c-строку, используя его литерал («\ r», «\ n» и т. Д.). –

+0

Я имею в виду аргумент командной строки. И проблема с горячими клавишами заключается в том, что, если я не в сыром режиме, они не набирают символ. Например, Ctrl + D фактически выходит из любой программы, в которой я находится. – mage

+0

Возможно, это не лучшие способы обработки вещей в вашей программе, если вам требуются многие из этих управляющих символов. –

ответ

0

В этой ситуации вам необходимо быть в курсе, где функциональность. Обработка может или не может быть выполнена интерпретатором командной строки, который вызывает вашу программу. Вы можете получать разные результаты от одного и того же кода C в зависимости от того, используете ли вы команду DOS или Linux или Unix и т. Д.

+0

Какая оболочка используется, также может воздействовать на нее, а также параметры терминала. Подозреваю, нет «портативного» ответа на этот вопрос. –

0

Если вас устраивает возможность отправки escape-последовательностей в стиле строки C функция преобразования может работать для вас, если вы не используете кавычки в середине ввода. Если вам нужны кавычки в середине ввода, вам нужно выяснить, какую escape-последовательность использует ваша оболочка для передачи кавычек в командной строке 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"); 
} 
0

Возможно, вам захочется узнать, как передавать двоичные данные в качестве аргумента в bash. См. this question.

Вот короткая демонстрация на 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] является sequense из двух управляющих символов: 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' 
Смежные вопросы