我需要为我的词法分析器收集一些字符到缓冲区中,但我不知道如何。我在stackoverflow上读过一些答案,但那是不同的情况。我有一个while循环,它读取下一个字符,我想在其中添加逻辑,这样它就可以将新字符附加到内存缓冲区中。
// init buffer with the first char 'h'
char *buffer = malloc(sizeof(char));
buffer[0] = 'h';
buffer[1] = ' ';
// go through input char by char
while(...)
{
char c = read_next_char();
buffer.append(c) // I whould do in JavaScript, but not in C :(
}
在您的情况下,您在开始分配单个字节的char *buffer = malloc(sizeof(char));
,并访问缓冲区[1]或任何其他索引是UB。
你可以在开始分配一个已知的字节数,直到你看到一个需要更多缓冲区大小的点。
像这样,
int buffersize = 100;
int index =0;
char *buffer = malloc(sizeof(char)*buffersize); //100bytes are allocated
if(!buffer)
return;
buffer[index++] = 'h';
buffer[index++] = ' ';
// go through input char by char
while(...)
{
char c = read_next_char();
if(index == buffersize ){
buffersize +=100;
buffer= realloc(buffer, buffersize );
//here buffer size is increased by 100
if(!buffer)
return;
}
buffer[index++] = c ;
}
注意:必须在使用结束后释放buffer
,否则会导致资源泄漏。
您需要简单地覆盖null终止字符并添加新字符。
char *append(char *buff, int ch)
{
size_t len = strlen(buff);
buff[len] = ch;
buff[len+1] = 0;
return buff;
}
代码假设buff
是一个有效的指针,指向足够长的内存块,可以容纳新的char和null终止char。它必须包含一个有效的C字符串。
与java或javascript不同,C中没有字符串类型,您需要自己编写。
这是一个非常简单的例子,说明如何高效地构建字符串。
这是不言自明的。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct DynamicString
{
char* string; // pointer to string
int length; // string length
int capacity; // capacity of the string buffer (= allocated size)
};
#define DS_CHUNKSIZE 100 // we increase the buffer size by DS_CHUNKSIZE
// change this as needed
// Initialize the structure
void InitDynamicString(struct DynamicString* ds)
{
ds->capacity = DS_CHUNKSIZE + 1;
ds->string = malloc(ds->capacity);
ds->string[0] = 0; // null terminator
ds->length = 0; // initial string length 0
};
// Increase the string buffer size if necessary
// (internal function)
void IncreaseSize(struct DynamicString* ds, int newsize)
{
if (ds->length + newsize + 1 > ds->capacity)
{
ds->capacity = ds->length + newsize + DS_CHUNKSIZE + 1;
ds->string = realloc(ds->string, ds->capacity); // reallocate a new larger buffer
}
}
// append a single character
void AppendChar(struct DynamicString* ds, char ch)
{
IncreaseSize(ds, sizeof(char)); // increase size by 1 if necessary
ds->string[ds->length++] = ch; // append char
ds->string[ds->length] = 0; // null terminator
}
// append a string
void AppendString(struct DynamicString* ds, const char *str)
{
IncreaseSize(ds, strlen(str)); // increase by length of string if necessary
strcat(ds->string, str); // concatenate
ds->length += strlen(str); // update string length
}
int main(int argc, char* argv[])
{
struct DynamicString ds;
InitDynamicString(&ds); // initialize ds
AppendChar(&ds, 'a'); // append chars
AppendChar(&ds, 'b');
AppendChar(&ds, 'c');
AppendString(&ds, "DE"); // append strings
AppendString(&ds, "xyz1234");
printf("string = "%s"", ds.string); // show result
}
你的代码可以这样使用:
struct DynamicString buffer;
InitDynamicString(&buffer)
dAppendChar(&buffer, 'h');
while(...)
{
char c = read_next_char();
AppendChar(&buffer, c); // quite similar to buffer.append(c)
}
免责声明:
- 代码没有经过彻底的测试,可能存在bug。
- 没有任何错误检查。
malloc
和realloc
可能失效 - 需要编写
SetString(struct DynamicString *ds, const char *string)
等其他有用的函数 - 有优化的空间,特别是
strcat
可以不同的处理,阅读这篇文章了解更多信息。我把这个(非常简单的)练习留给读者。
在C语言中没有标准函数可以在字符串后面添加字符。您需要从头开始编写代码。
我们从这里开始:
char *buffer = malloc(sizeof(char)); // This allocates memory for ONE char
buffer[0] = 'h'; // So this is fine
buffer[1] = ' '; // but this is bad. It writes outside the allocated memory
通过为两个字符分配内存来修复它
char *buffer = malloc(2); // sizeof(char) is always 1 so no need for it
buffer[0] = 'h';
buffer[1] = ' ';
当您想要在字符串中添加一个新字符时,您还需要为它分配内存。换句话说,您需要增加buffer
所指向的内存的大小。为此,可以使用realloc
函数。
size_t buffer_size = 2;
char *buffer = malloc(buffer_size );
buffer[0] = 'h';
buffer[1] = ' ';
while(...)
{
char c = read_next_char();
char* tmp = realloc(buffer, buffer_size + 1);
if (tmp == NULL)
{
// realloc failed ! Add error handling here
... error handling ...
}
buffer = tmp;
buffer[buffer_size - 1] = c; // Add the new char
buffer[buffer_size] = ' '; // Add the string termination
++buffer_size; // Update buffer size
}
其他答案也可以,但它们很复杂。我建议一个更简单的解决方案。字符串是一个char
的数组,其中该字符串的最后一个char
是' '
字节。在它之后的数组中可以有更多的char
,但它们不是字符串的一部分。
更简单的解决方案是创建一个足够大的数组,98%的情况下,使用它来存储字符串,当字符串变得太长,你可以退出一个错误。在需要的时候改变缓冲区的大小是一个很好的特性,但是当你是C语言的新手时,你不应该从这里开始。
#define BUFFER_SIZE 1024
// init buffer with the first char 'h'
char buffer[BUFFER_SIZE];
buffer[0] = 'h';
buffer[1] = ' ';
// go through input char by char Replace the ... with your condition of the while loop
for(size_t i=1;...;i++) //start at 1 so the 'h' is not overwritten
{
if(i==BUFFER_SIZE-1) //-1 for the ' '-Byte
{
fputs("Input too long, exitn",stderr);
exit(1);
}
//Are you sure you don't need error handling for read_next_char()?
buffer[i] = read_next_char();
buffer[i+1]=' '; //End the string with a ' '-Byte
}