Как передать escape-последовательность, такую ​​как tab и символ новой строки, в качестве аргумента командной строки в C-программировании getopt_long?

Я почти достиг конца своего кода, после многих поисков я не нашел решения ни где, я хочу предоставить escape-последовательность вроде '\t', '\n' для моей программы, например как awk а также perl программа берет, и, наконец, я хочу использовать их в качестве строки формата printf или sprintf

Это то, что я пробовал до сих пор, пожалуйста, обратите внимание, что мне нужно иметь переменную delim и rs должен быть указателем.

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


 int main (int argc, char **argv)
 {
   int c;

   char *delim = ",", *rs = "\n\r";

   while (1)
     {
       static struct option long_options[] =
         {

           {"delim",  required_argument, 0, 'd'},
           {"row_sep",  required_argument, 0, 'r'},
           {0, 0, 0, 0}
         };

       int option_index = 0;

       c = getopt_long (argc, argv, "df",
                        long_options, &option_index);


       if (c == -1)
         break;

       switch (c)
         {
         case 0:

           if (long_options[option_index].flag != 0)
             break;
           printf ("option %s", long_options[option_index].name);
           if (optarg)
             printf (" with arg %s", optarg);
           printf ("\n");
           break;

         case 'd':
           delim = optarg;
           break;

         case 'r':
           rs = optarg;
           break;

         case '?':
           break;

         default:
           abort ();
         }
     }


   /* Print any remaining command line arguments (not options). */
   if (optind < argc)
     {
       printf ("non-option ARGV-elements: ");
       while (optind < argc)
         printf ("%s ", argv[optind++]);
       putchar ('\n');
     }



 /* Test input argument */


 printf("This is test%ssome text%s",delim,rs);



   exit (0);
 }

Когда я компилирую и выполняю, я получаю вывод, как это

 $ gcc argument.c

 $ ./a.out --delim="\t"
 This is test\tsome text

 $ ./a.out --delim="\t" --row_sep="\n"
 This is test\tsome text\n

Я ожидаю, что он напечатает табуляцию и символ новой строки вместо '\ t' и '\ n' как оригинальный

Пожалуйста, кто-нибудь, помогите мне.

1 ответ

Решение

Некоторый код где-то должен переводить backslash-t и backslash-n в табуляцию и перевод строки. Вы можете заставить оболочку сделать это (если это Bash или поддерживает цитирование ANSI C):

./a.out --delim=$'\t'
./a.out --delim=$'\t' --row_sep=$'\n'

Или используйте printf команда (в отличие от, хотя и относится к printf() функция); это позволяет избежать использования любых Bashisms:

./a.out --delim="$(printf '\t')"
./a.out --delim="$(printf '\t')" --row_sep="$(printf '\n')"

Или, действительно, вы можете просто ввести символы в командной строке. Для входа на вкладку необходимо ввести Control-VControl-I, чтобы избежать завершения имени файла.

$ ./a.out --delim='^V^I'
$ ./a.out --delim='^V^I' --row_sep='
> '

Это менее ясно, хотя; Я бы использовал один из предыдущих двух механизмов в предпочтении.

Или вы можете сделать это в своей программе. Это немного сложнее, но не намного. У меня довольно всеобъемлющая функция, cstrlit_chr() который выполняет большую часть этой работы (он не обрабатывает Unicode, как \u0123 или же \U00012345), но он не является стандартным и находится в файле длиной 238 строк с комментариями, тестовым кодом и т. д. (чуть более 100 непустых строк без комментариев кода C в функции, которые могут быть сжаты немного, если бы я хотел потратить время на это), так что немного сложнее добавить его сюда.


Не могли бы вы показать мне cstrlit_chr() пример для того же?

Заголовок, документирующий интерфейс, говорит:

/* Convert C String Literal in (str..end] (excluding surrounding quotes) */
/* to string, returning length of string, or -1 if conversion error, or */
/* -2 if there is not enough room for the output */
extern int cstrlit_str(const char *str, const char *end, char *buffer, size_t buflen);
/* Convert C Character Literal in (str..end] (excluding surrounding quotes) */
/* to character, returning converted char or -1 if string is invalid. */
/* If non-null, eptr is set to first non-converted (or non-convertible) character */
extern int cstrlit_chr(const char *str, const char *end, char const ** const eptr);

/* Convert character to C Character Literal. */
/* buffer[0] = '\0' if there isn't enough room in buffer */
extern void chr_cstrlit(unsigned char c, char *buffer, size_t buflen);
/* Convert string to C String Literal */
extern void str_cstrlit(const char *str, char *buffer, size_t buflen);

Так, cstrlit_chr() является одним из набора из четырех функций. Тем не менее, это довольно легко использовать:

 const char *endptr;
 int c = cstrlit_char(argv[i], argv[i]+strlen(argv[i]), &endptr);

Если argv[i] содержит обратную косую черту и t, затем c будет назначено значение '\t' (который обычно является контрольным I или 9). Если он содержит обратную косую черту и n, затем c будет назначено значение '\n' (который обычно является контрольным-J или 10).

Значение в endptr говорит вам, что будет следующим персонажем для интерпретации.

Другие вопросы по тегам