好的,所以我是那些经常写Java / C ++的人,而我刚刚开始编写C.我目前正在写一个词法分析器,我不能因为我不能执行字符串运算,所以我认为字符串在C中是如何工作的。所以这是我的问题:
char* buffer = "";
char* line = "hello, world";
int i;
for (i = 0; i < strlen(line); i++) {
buffer += line[i];
}
我怎样才能在C中这样做?由于上面的代码不是有效的C,我该怎么做呢?
基本上我通过字符串line
循环,我试图将每个字符附加到buffer
字符串。
答案 0 :(得分:2)
首先,缓冲区需要具有或超过复制到其中的数据的长度。
char a[length], b[] = "string";
然后将字符复制到缓冲区。
int i = 0;
while (i < length && b[i] != '\0') { a[i] = b[i]; i++; }
a[i] = '\0';
如果需要,可以反转顺序,只需在两个字符串中的最小长度值处启动i
,然后递减值而不是递增。您也可以像其他人所建议的那样使用堆,纵向指向length
的任意值或更改值。此外,您可以使用指针更改代码段(并让您更好地了解正在发生的事情):
int i = 0;
char *j = a, *k = b;
while (j - a < length && *k) { *(j++) = *(k++); }
*j = '\0';
确保查找memcpy
;并且不要忘记null终结符(oops)。
答案 1 :(得分:1)
字符串文字在C中是不可变的。修改一个会导致未定义的行为。
如果您使用足以容纳角色的char
数组(您的缓冲区),您仍然可以修改其内容:
#include <stdio.h>
int main(void) {
char * line = "hello, world";
char buffer[32]; // ok, this array is big enough for our operation
int i;
for (i = 0; i < strlen(line) + 1; i++)
{
buffer[i] = line[i];
}
printf("buffer : %s", buffer);
return 0;
}
答案 2 :(得分:0)
#include <string.h>
//...
char *line = "hello, world";
char *buffer = ( char * ) malloc( strlen( line ) + 1 );
strcpy( buffer, line );
虽然在C字符串文字中有非const数组的类型,但最好用字符串文字用限定符const声明初始化指针:
const char *line = "hello, world";
C / C ++中的字符串文字是不可变的。
如果你想附加字符,那么代码可以按以下方式查找(行的每个字符都附加到循环中的缓冲区)
#include <string.h>
//...
char *line = "hello, world";
char *buffer = ( char * ) malloc( strlen( line ) + 1 );
buffer[0] = '\0';
char *p = Buffer;
for ( size_t i = 0; i < strlen( line ); i++ )
{
*p++ = line[i];
*p = '\0';
}
一般方法是,您发现指向终止零的指针替代目标字符使指针前进,并将新的终止零作为appenf。源缓冲区应足够大,以容纳一个字符。
答案 3 :(得分:0)
如果你想将一个字符附加到堆上分配的字符串,这是一种方法:
size_t length = strlen(buffer);
char *newbuffer = realloc(buffer, length + 2);
if (newbuffer) { // realloc succeeded
buffer = newbuffer;
buffer[length] = newcharacter;
buffer[length + 1] = '\0';
}
else { // realloc failed
// TODO handle error...
free(buffer); // for example
}
但是,这在循环中重复执行效率很低,因为您将(基本上)在同一个字符串上重复调用strlen()
,并且每次重新分配缓冲区以适应另一个字符。 / p>
如果你想更聪明地重新分配,请跟踪缓冲区当前分配的容量,与其中的字符串长度分开 - 如果您了解C ++,请考虑{{1}之间的差异} object&#34; s&#34; size&#34;及其能力&#34; - 当需要重新分配时,将缓冲区的大小乘以缩放因子(例如加倍)而不是加1,这样重新分配的数量就是O(log n)而不是O( n)中。
这是一个好的字符串类在C ++中会做的事情。在C中,您可能希望将此缓冲区管理内容移动到其自己的模块中。
答案 4 :(得分:0)
缺乏任何背景的最简单的解决方案是:
char buffer[ strlen(line) + 1 ];
strcpy(buffer, line);
您可能习惯使用Java中的所有指针(因为Java中的非基本类型实际上更像是共享指针而不是其他任何东西)。但是,你不必在C中这样做,如果你这样做会很痛苦。
根据你的背景,也许一个好主意是在C中使用一个计数字符串对象,其中字符串对象拥有其数据。写struct my_string { char *data; size_t length; }
。编写用于创建,销毁,复制和所需的任何其他操作的函数,例如附加字符或检查长度。 (与实现分开的接口!)对此的一个有用的补充是使它分配比length
多1个字节,这样你就可以有一个null终止的函数,并允许它传递给一个期望的函数只读C风格的字符串。
这里唯一真正的缺陷是记住在进行复制操作时调用函数,而不是允许结构赋值发生。 (当然,您可以使用结构分配进行移动操作!)
答案 5 :(得分:0)
asprintf
函数对于构建字符串非常有用,并且可用于基于GNU的系统(Linux)或大多数基于* BSD的系统。你可以这样做:
char *buffer;
if (asprintf(&buffer, "%s: adding some stuff %d - %s", str1, number, str2) < 0) {
fprintf(stderr, "Oops -- out of memory\n");
exit(1); }
printf("created the string \"%s\"\n", buffer);
free(buffer); /* done with it */