我目前正在阅读21世纪C,并且玩弄了一些人为的示例代码。在C99中收集没有浪费malloc的字符串
我试图解决这个问题不重复malloc()
和realloc()
荷兰国际集团,缓冲区中的问题,完整的代码here,但我下面联的重要组成部分:
功能_sgr_color(int modes[])
应该叫一样,既是等价的,第二个是宏包装复合文字:
_sgr_color((int[]){31,45,0}); // literal function
sgv_color(31, 45); // va macro wrapper
这些都应该返回类似\x1b[;31;45m
。
然而神奇的号码被定义为在原代码(typedef enum SGR_COLOR { SGR_COLOUR_BLACK = 31}
等)
功能_sgr_color(int modes[])
内部常量,我知道我需要分配一个缓冲区,并返回它,没有问题,但我不知道过了多久,使缓冲区,直到我走了modes[]
:
我已经诠释了联代码:
/* Static, to make callers use the macro */
static char *_sgr_color(int modes[]) {
/* We increment the writeOffset to move the "start" pointer for the memcpy */
int writeOffset = 0;
/* Initial length, CSI_START and CSI_END are `\x1b[' and `m' respectively */
int len = strlen(CSI_START CSI_END);
/* Loop over modes[] looking for a 0, then break, count the number of entries
* this is +1 to account for the ; that we inject.
*/
for (int i = 0; modes[i] > 0; i++) {
len += sizeof(enum SGR_COLOR) + 1;
}
/* Local buffer, unsafe for return but the length at least is right (no +1 for
* \0
* because we are in control of reading it, and we'll allocate the +1 for the
* buffer which we return
*/
char buffer[len];
/* Copy CSI_START into our buffer at position 0 */
memcpy(buffer, CSI_START, strlen(CSI_START));
/* Increment writeOffset by strlen(CSI_START) */
writeOffset += strlen(CSI_START);
/* Loop again over modes[], inefficient to walk it twice,
* but preferable to extending a buffer in the first loop with
* realloc().
*/
for (int i = 0; modes[i] > 0; i++) {
/* Copy the ; separator into the buffer and increment writeOffset by
* sizeof(char) */
memcpy(buffer + writeOffset, ";", sizeof(char));
writeOffset += sizeof(char);
/* Write the mode number (int) to the buffer, and increment the writeOffset
* by the appropriate amount
*/
char *modeistr;
if (asprintf(&modeistr, "%d", modes[i]) < 0) {
return "\0";
}
memcpy(buffer + writeOffset, modeistr, sizeof(enum SGR_COLOR));
writeOffset += strlen(modeistr);
free(modeistr);
}
/* Copy the CSI_END into the buffer, no need to touch writeOffset */
memcpy(buffer + writeOffset, CSI_END, strlen(CSI_END));
char *dest = malloc(len + 1);
/* Copy the buffer into the return buffer, strncopy will fill the +1 with \0
* as per the documentation:
*
* > The stpncpy() and strncpy() functions copy at most n characters
* > from src into dst. If src is less than n characters long, the
* > remainder of dst is filled with `\0' characters.
* > Otherwise, dst is not terminated.
*
*/
strncpy(dest, buffer, len);
return dest;
}
这里的代码工作,一个示例程序输出正确的b ytes按照正确的顺序和颜色代码工作,如标注但是存在的问题:
- 采用
asprintf()
破坏我的理由为希望不要重复调用malloc()
。
我很努力地看到如何简化这段代码,如果有的话,以及如何可能会危及我不想重复分配内存的愿望。
避免重复分配内存的唯一方法是为整个作业前面分配足够的。如果你不能这样做,那么这是一个如何组织这些分配的问题。 – 2014-12-10 22:19:08
你可以用你的专业知识,以组成一个答案,我可以接受,也许是分配在堆上合理大小的缓冲,迭代的事情,不知何故检测(用'strncpy'?)字符串的结束,mallocing和复制只是那点?另外我怎样才能将整数转换为char *而不用'asprintf'调用? – 2014-12-10 22:32:50
注意:'sizeof(enum color)'不是估计所需缓冲区大小的正确方法。它给出了'enum color'的内部表示的大小,而不是* formatted *表示的大小。你是 – 2014-12-10 22:52:10