如何将字符收集到 C 中的字符串中?
How do I collect chars into a string in C?
我需要将一些字符收集到我的词法分析器的缓冲区中,但我不知道如何操作。我已经阅读了一些关于 Whosebug 的答案,但这些是不同的情况。我有一个读取下一个字符的 while 循环,我想将逻辑放入其中,以便将新字符附加到内存中的缓冲区。
// init buffer with the first char 'h'
char *buffer = malloc(sizeof(char));
buffer[0] = 'h';
buffer[1] = '[=10=]';
// 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++] = '[=10=]';
// 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
,否则会导致资源泄漏。
您需要简单地覆盖空终止字符并添加新字符。
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或javascipt不同,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)
}
免责声明:
- 代码尚未经过全面测试,可能存在错误。
- 没有任何错误检查。
malloc
和 realloc
可能会失败。
- 其他有用的函数如
SetString(struct DynamicString *ds, const char *string)
需要写
- 还有优化的空间,尤其是
strcat
可以有不同的处理方式,阅读 this article 了解更多信息。我将此作为(非常简单的)练习留给 reader.
C 中没有可以将 char 附加到字符串的标准函数。您需要从头开始编写代码。
让我们从这里开始:
char *buffer = malloc(sizeof(char)); // This allocates memory for ONE char
buffer[0] = 'h'; // So this is fine
buffer[1] = '[=10=]'; // 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] = '[=11=]';
当你想在字符串中追加一个新的字符时,你也需要为它分配内存。换句话说,您需要增加 buffer
指向的内存大小。为此,您可以使用函数 realloc
.
size_t buffer_size = 2;
char *buffer = malloc(buffer_size );
buffer[0] = 'h';
buffer[1] = '[=12=]';
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] = '[=12=]'; // Add the string termination
++buffer_size; // Update buffer size
}
其他答案可以,但它们很复杂。我建议一个更简单的解决方案。字符串是 char
的数组,其中该字符串的最后一个 char
是一个 '[=13=]'
字节。它后面的数组中可以有更多 char
,但它们不是字符串的一部分。
更简单的解决方案是创建一个对 98% 的情况都足够大的数组,用它来存储字符串,当字符串太长时,您可以退出并报错。在需要时更改缓冲区大小是一个不错的功能,但如果您是 C 的新手,则不应从那里开始。
#define BUFFER_SIZE 1024
// init buffer with the first char 'h'
char buffer[BUFFER_SIZE];
buffer[0] = 'h';
buffer[1] = '[=10=]';
// 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 '[=10=]'-Byte
{
fputs("Input too long, exit\n",stderr);
exit(1);
}
//Are you sure you don't need error handling for read_next_char()?
buffer[i] = read_next_char();
buffer[i+1]='[=10=]'; //End the string with a '[=10=]'-Byte
}
我需要将一些字符收集到我的词法分析器的缓冲区中,但我不知道如何操作。我已经阅读了一些关于 Whosebug 的答案,但这些是不同的情况。我有一个读取下一个字符的 while 循环,我想将逻辑放入其中,以便将新字符附加到内存中的缓冲区。
// init buffer with the first char 'h'
char *buffer = malloc(sizeof(char));
buffer[0] = 'h';
buffer[1] = '[=10=]';
// 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++] = '[=10=]';
// 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
,否则会导致资源泄漏。
您需要简单地覆盖空终止字符并添加新字符。
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或javascipt不同,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)
}
免责声明:
- 代码尚未经过全面测试,可能存在错误。
- 没有任何错误检查。
malloc
和realloc
可能会失败。 - 其他有用的函数如
SetString(struct DynamicString *ds, const char *string)
需要写 - 还有优化的空间,尤其是
strcat
可以有不同的处理方式,阅读 this article 了解更多信息。我将此作为(非常简单的)练习留给 reader.
C 中没有可以将 char 附加到字符串的标准函数。您需要从头开始编写代码。
让我们从这里开始:
char *buffer = malloc(sizeof(char)); // This allocates memory for ONE char
buffer[0] = 'h'; // So this is fine
buffer[1] = '[=10=]'; // 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] = '[=11=]';
当你想在字符串中追加一个新的字符时,你也需要为它分配内存。换句话说,您需要增加 buffer
指向的内存大小。为此,您可以使用函数 realloc
.
size_t buffer_size = 2;
char *buffer = malloc(buffer_size );
buffer[0] = 'h';
buffer[1] = '[=12=]';
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] = '[=12=]'; // Add the string termination
++buffer_size; // Update buffer size
}
其他答案可以,但它们很复杂。我建议一个更简单的解决方案。字符串是 char
的数组,其中该字符串的最后一个 char
是一个 '[=13=]'
字节。它后面的数组中可以有更多 char
,但它们不是字符串的一部分。
更简单的解决方案是创建一个对 98% 的情况都足够大的数组,用它来存储字符串,当字符串太长时,您可以退出并报错。在需要时更改缓冲区大小是一个不错的功能,但如果您是 C 的新手,则不应从那里开始。
#define BUFFER_SIZE 1024
// init buffer with the first char 'h'
char buffer[BUFFER_SIZE];
buffer[0] = 'h';
buffer[1] = '[=10=]';
// 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 '[=10=]'-Byte
{
fputs("Input too long, exit\n",stderr);
exit(1);
}
//Are you sure you don't need error handling for read_next_char()?
buffer[i] = read_next_char();
buffer[i+1]='[=10=]'; //End the string with a '[=10=]'-Byte
}