Reputation: 7339
In C, If I have:
char *reg = "[R5]";
and I want
char *reg_alt = "R5"
(equal to the same thing, but without the brackets), how do I do this?
I tried
*char reg_alt = reg[1:2];
but this doesn't work.
Upvotes: 11
Views: 1715
Reputation: 155438
When using null-terminated strings (the default in C), you can indeed cheaply create a substring of another string by simply changing the starting character pointer, but you cannot make the new substring have a different null-terminator.
An option is to use a Pascal-string library. Pascal-strings are length-prefixed instead of C-strings which are null-terminated, which means Pascal-strings can share contents of a larger string buffer and substring generation is cheap (O(1)
-cheap). A Pascal string looks like this:
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 };
}
The downside is that most of the C library and platform libraries use null-terminated strings and unless your Pascal-string ends in a null character you'll need to copy the substring to a new buffer (in O(n)
time).
Of course, if you're feeling dangerous (and using mutable character buffers) then you can hack it to temporarily insert a null-terminator, like so:
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;
}
Used like so:
PString somePascalString = doSomethingWithPascalStrings();
CStr temp = getCStr( somePascalString );
printf("My Pascal string: %s", temp.start ); // using a function that expects a C-string
undoGetCStr( temp );
...which then gives you O(1)
PString-to-CString performance, provided you don't care about thread-safety.
Upvotes: 3
Reputation: 36616
I suggest you need to read a basic text on C, rather than assuming techniques from other languages will just work.
First, char *reg = "[R5]";
is not a string. It is a pointer, that is initialised to point to (i.e. its value is the address of) the first character of a string literal ("[R5]"
).
Second, reg_alt
is also a pointer, not a string. Assigning to it will contain an address of something. Strings are not first class citizens in C, so the assignment operator doesn't work with them.
Third, 1:2
does not specify a range - it is actually more invalid syntax. Yes, I know other languages do. But not C. Hence my comment that you cannot assume C will allow things it the way that other languages do.
If you want to obtain a substring from another string, there are various ways. For example;
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()
is declared in standard header <string.h>
. The termination of the substring is needed, since printf()
%s
format looks for a zero character to mark the end.
Upvotes: 13
Reputation: 726809
There is no built-in syntax for dealing with substrings like that, so you need to copy the content manually:
char res[3];
memcpy(res, ®[1], 2);
res[2] = '\0';
Upvotes: 15
Reputation: 488
Need to be a char?
Because that only work when is a "string" So maybe you need this
char reg[] = "[R5]";
Then you can do the other thing or just split the string like this question
Upvotes: 1