Динамически создавать char в C

Я пытаюсь создать массив, содержащий ряд символов, которые я хочу построить на лету, символы такие, как \x01, \x02 и так далее.

Например, допустим, у нас есть:

#define NUMCOLORS 3
char delim[NUMCOLORS];

И мы хотим иметь в delim значения \x01, \x02, \x03.

Я подумал о двух возможных способах сделать это, но оба вызывают segfault:

for (int i = 0; i < NUMCOLORS; i++){
  char *h = "\x01";
  sprintf(h, "\x0%d", i+1);
  strcpy(delim[i], h);
}

// Other way

for (int i = 0; i < NUMCOLORS; i++){ 
  char *h = "\x0";
  strcpy(delim[i], h+1);
}

Есть ли способ создать char, который мне нужен?


person ElBaulP    schedule 24.07.2014    source источник
comment
Вы не можете sprintf войти в h, потому что он указывает на раздел памяти, доступный только для чтения. Вы не можете strcpy в delim[i], потому что это указатель char, а не char!!!   -  person barak manos    schedule 24.07.2014
comment
Знаете ли вы о strdup(3)?   -  person Basile Starynkevitch    schedule 24.07.2014


Ответы (3)


Нет, не используйте strcpy, так как это добавит терминатор строки. Кроме того, выполнение h + 1 дает вам следующий символ в строке, на которую указывает h, который является ограничителем строки.

Вместо этого используйте тот факт, что символ на самом деле является целым числом. Это означает, что вы можете сделать, например.

char delim[4];

for (int i = 0; i < 3; ++i)
    delim[i] = i + 1;

/* Terminates as string */
delim[3] = '\0';

Теперь вы можете использовать delim как любую другую строку в C и содержать строку "\01\02\03".


Если вы хотите, чтобы строка содержала не символы '\01', '\02' и т. д., вам нужен массив большего размера и другой способ построения строки:

/* 3 sequences of 4 characters (backslash, x, two digits), plus terminator */
char delims[3 * 4 + 1] = { 0 };  /* Initialize to zero (the string terminator) */

for (int i = 0; i < 3; ++i)
{
    char temp[5];  /* Place for 4 characters plus terminator */
    sprintf(temp, "\\x%02d", i);

    strcat(delims, temp);
}

Теперь после этого строка delims будет содержать строку "\x01\x02\x03". Обратите внимание, что обратная косая черта - это настоящая обратная косая черта, а не то, что компилятор будет переводить, если вы выведете строку на консоль, вывод будет именно таким: обратная косая черта и все.

person Some programmer dude    schedule 24.07.2014
comment
Но чтобы просто заполнить разделитель 1,2,3, мне нужно было \x01 \x02 и \x03 - person ElBaulP; 24.07.2014
comment
@algui91 algui91 Вам нужен массив символов или строк? - person Some programmer dude; 24.07.2014
comment
@algui91 Кроме того, целочисленное значение 1 равно символьному литералу '\01'. - person Some programmer dude; 24.07.2014
comment
Давайте посмотрим, у меня есть строка, которую мне нужно проанализировать, например. Привет, \x01 wolrd\x02, \x01 и \x02 представляют цвета, тогда мне нужно, чтобы delim был \x01\x02, чтобы проанализировать его с помощью strtok. - person ElBaulP; 24.07.2014
comment
@ algui91 algui91 Если вы хотите использовать его как строку, см. мой обновленный ответ. - person Some programmer dude; 24.07.2014
comment
Первый подход работает как шарм. Как вы думаете, что лучше? - person ElBaulP; 24.07.2014
comment
@ algui91 Если первый работает, второй не работает. И наоборот тоже конечно. Два варианта создают разные строки, я включил их оба, потому что не был уверен, что вы хотите. - person Some programmer dude; 24.07.2014

char *h = "\x01"; ( will place \x01 in the read-only parts of the memory )
sprintf(h, "\x0%d", i+1); // not valid 

это указатель, указывающий на постоянную строку. его изменение незаконно. Прочтите этот мой ответ

person Jayesh Bhoi    schedule 24.07.2014

Обозначение "\x01" — это способ сообщить компилятору: «Когда вы создаете константу для представления этого строкового литерала, замените меня символом с числовым значением 1». Обратная косая черта (и x) даже не попадает в скомпилированный модуль. Если вам нужен символ определенного (динамического) числового значения в строке, просто добавьте это числовое значение (приведите к char) к струне. Иоахим дает вам несколько идей.

Нотация "\x01" - это просто "удобство", когда у вас есть какое-то фиксированное числовое значение, которое вы хотите вставить в строковый литерал.

person Hot Licks    schedule 24.07.2014