C, равная подстроке

В C, если у меня есть:

char *reg = "[R5]";

и я хочу

char *reg_alt = "R5" (равный одному и тому же, но без скобок), как это сделать?

Я пробовал

*char reg_alt = reg[1:2];

но это не работает.

Ответ 1

Нет встроенного синтаксиса для работы с подобными подстроками, поэтому вам нужно скопировать содержимое вручную:

char res[3];
memcpy(res, &reg[1], 2);
res[2] = '\0';

Ответ 2

Я предлагаю вам прочитать основной текст на языке C, а не считать, что методы с других языков будут работать.

Во-первых, char *reg = "[R5]"; не является строкой. Это указатель, который инициализируется, чтобы указать (то есть его значение является адресом) первого символа строкового литерала ("[R5]").

Во-вторых, reg_alt также является указателем, а не строкой. Присвоение ему будет содержать адрес чего-то. Строки не являются гражданами первого класса в C, поэтому оператор присваивания не работает с ними.

В-третьих, 1:2 не указывает диапазон - это действительно более недействительный синтаксис. Да, я знаю, что другие языки. Но не C. Следовательно, мой комментарий, который вы не можете принять, C позволит вещам так, как это делают другие языки.

Если вы хотите получить подстроку из другой строки, существуют различные способы. Например:

  char substring[3];
  const char *reg = "[R5]";    /* const since the string literal should not be modified */

  strncpy(substring, &reg[1], 2);     /* copy 2 characters, starting at reg[1], to substring */
  substring[2] = '\0';     /*  terminate substring */

  printf("%s\n", substring);

strncpy() объявляется в стандартном заголовке <string.h>. Требуется прекращение подстроки, так как формат printf() %s ищет нулевой символ, чтобы отметить конец.

Ответ 3

При использовании строк с нулевым завершением (по умолчанию в C) вы действительно можете дешево создать подстроку другой строки, просто изменив указатель начального символа, но вы не можете заставить новую подстроку иметь другой нулевой ограничитель.

Опция заключается в использовании библиотеки строк Pascal. Паскальные строки имеют префикс длины вместо C-строк, которые заканчиваются на нуль, что означает, что строки Pascal могут совместно использовать содержимое большего строкового буфера, а генерация подстроки дешевая (O(1) -cheap). Строка Pascal выглядит так:

struct PString {
    size_t length;
    char*  start;
}

PString substring(const PString* source, size_t offset, size_t length) {
    // Using C99 Designated Initializer syntax:
    return PString { .length =  length, .start = source.start + offset };
}

Недостатком является то, что большинство библиотек библиотеки C и платформ используют строки с нулевым символом, и если ваша строка Pascal не заканчивается нулевым символом, вам нужно будет скопировать подстроку в новый буфер (в O(n) время).

Конечно, если вы чувствуете себя опасно (и используете изменяемые буферы символов), вы можете взломать его, чтобы временно вставить нулевой терминатор, например:

struct CStr {
    char* start;
    char* end;
    char  temp;
}

CStr getCStr(PString* source) {
    char* terminator = (source.start + source.length);
    char previous = *terminator;
    *terminator = '\0';
    return CStr { .start = source.start, .end = terminator, .temp = previous };
}

void undoGetCStr(CStr cstr) {
    *cstr.end = cstr.temp;
}

Используется так:

PString somePascalString = doSomethingWithPascalStrings();
CStr temp = getCStr( somePascalString );
printf("My Pascal string: %s", temp.start ); // using a function that expects a C-string
undoGetCStr( temp );

..., который затем дает вам производительность O(1) PString-to-CString, если вы не заботитесь о безопасности потоков.

Ответ 4

Нужно быть char?

Потому что это работает только тогда, когда это "строка", Так что, возможно, вам это нужно

char reg[] = "[R5]";

Тогда вы можете сделать другое дело или просто разделите строку следующим образом question