在C中,如果我有:
char *reg = "[R5]";
我想要
char *reg_alt = "R5"
(相同但没有括号),我该怎么做?
我试过
*char reg_alt = reg[1:2];
但这不起作用。
答案 0 :(得分:15)
没有内置语法来处理类似的子串,因此您需要手动复制内容:
char res[3];
memcpy(res, ®[1], 2);
res[2] = '\0';
答案 1 :(得分:13)
我建议您需要阅读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, ®[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
格式会查找零字符以标记结尾。
答案 2 :(得分:3)
当使用以null结尾的字符串(C中的默认字符串)时,您实际上可以通过简单地更改起始字符指针来廉价地创建另一个字符串的子字符串,但是您不能使新的子字符串具有不同的空终止符。
一个选项是使用Pascal字符串库。 Pascal字符串是长度前缀而不是以N结尾的C字符串,这意味着Pascal字符串可以共享更大字符串缓冲区的内容,并且子字符串生成便宜(O(1)
- 便宜)。 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库和平台库使用以null结尾的字符串,除非您的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性能。
答案 3 :(得分:1)