如何多次附加到字符串?

时间:2015-03-27 08:31:24

标签: c string loops char

所以我有一个循环,每次都会产生一个sting,我想把这个字符串附加到一个现有变量。

char fullString[] = "start: ";

while(x < 200){

    char someVar[] = "test "

    //append someVar to fullString

    x++;

}

所以我想最终得到一个像这样的字符串:

start: test test test test test ...

我可以轻松地使用任何其他语言,只是不确定如何在c中做任何想法?

7 个答案:

答案 0 :(得分:5)

你应该有一个足够大的缓冲区来容纳整个连接字符串。

使用字符串函数strcat(),如下所示

char fullString[2000] = "start: ";

while(x<200)
{
    char someVar[] = "test "; // What ever valid string you want to append to the existing string
    strcat(fullString,someVar);
    x++;
}

答案 1 :(得分:2)

你可以这样使用,

char *full =malloc(10);// allocating the memory
 if ( full == NULL ){ 
         printf("allocation failed\n");
         return;
 }
strcpy(full,"Start: ");
char someVar[] ="test ";
char *temp;
while(x < 200 ) {
     temp=realloc(full,(strlen(full)+1)+(strlen(someVar)+1));//reallocating for store repeatedly
     if ( temp == NULL )
              printf("allocation failed\n");
         break;
     }
     full=temp;
     strcat(full,someVar);
     x++;
}

答案 2 :(得分:1)

今天早上我写了这个答案但是停电了。无论如何,无论如何都要引导提问者理解他。

在C中这并不容易,因为你必须自己管理字符串空间(其他语言也适合你)。

本质上,每次要追加到现有字符串时,都必须计算其当前长度,要追加的字符串的长度,分配新空间来保存两者,将现有部分复制到新的字符串内存,追加新字符串,并释放旧字符串。

有多种方法可以加快速度,例如使用realloc,正如其他人建议的那样,预先分配更大的缓冲区,跟踪当前的长度等等;但是,如果要附加可变长度字符串,则该方法不会更改。

答案 3 :(得分:1)

strcat(),malloc()和realloc()的成本经常被忽视。

我已经对这个案子玩了一些并得到了一些数字:

% ./catter "Start: " "test " 1000                                                                                                             
    realloc_catter:        379
   prealloc_catter:        154
  realloc_mycatter:        152
 prealloc_mycatter:          8
% ./catter "Start: " "test " 100000  
    realloc_catter:    1453494
   prealloc_catter:     741639
  realloc_mycatter:     733160
 prealloc_mycatter:        365
% ./catter "Start: " "test " 1000000
    realloc_catter:  265374117
   prealloc_catter:  128139699
  realloc_mycatter:  127484834
 prealloc_mycatter:       3397

这里我们清楚地看到O(n ^ 2)成本。适当优化的连接方法仅花费O(n)。

测试代码是:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

void measure(char *name, void (*func)(char**,char *,char*,int), char **target, char *initial, char *repeat, int times)
{
    clock_t start, finish;
    start = clock();
    func(target, initial, repeat, times);
    free(*target);
    finish = clock();
    printf("%20s: %10lld\n", name, (long long)(finish - start));
}

void realloc_catter(char **target, char *initial, char *repeat, int times)
{
    *target = malloc(strlen(initial)+1);
    strcpy(*target, initial);
    for (int i = 0; i < times; i++) {
        *target = realloc(*target, strlen(*target) + strlen(repeat) + 1);
        strcat(*target, repeat);
    }
}

void prealloc_catter(char **target, char *initial, char *repeat, int times)
{
    *target = malloc(strlen(initial) + strlen(repeat) * times + 1);
    strcpy(*target, initial);
    for (int i = 0; i < times; i++) {
        strcat(*target, repeat);
    }
}

char *mystrcat(char *target, char *repeat)
{
    for(;;) {
        *target = *repeat;
        if (!*repeat) break;
        target++;
        repeat++;
    }
    return target;
}

void realloc_mycatter(char **target, char *initial, char *repeat, int times)
{
    char *catptr = *target = malloc(strlen(initial)+1);
    strcpy(*target, initial);
    for (int i = 0; i < times; i++) {
        *target = realloc(*target, strlen(*target) + strlen(repeat) + 1);
        catptr = mystrcat(catptr, repeat);
    }
}

void prealloc_mycatter(char **target, char *initial, char *repeat, int times)
{
    char *catptr = *target = malloc(strlen(initial) + strlen(repeat) * times + 1);
    strcpy(*target, initial);
    for (int i = 0; i < times; i++) {
        catptr = mystrcat(catptr, repeat);
    }
}

int main(int argc, char **argv)
{
    if (argc < 4) exit(1);
    char *initial = argv[1];
    char *repeat = argv[2];
    int times = atoi(argv[3]);

    char *target;

    measure("realloc_catter", realloc_catter, &target, initial, repeat, times);

    measure("prealloc_catter", prealloc_catter, &target, initial, repeat, times);

    measure("realloc_mycatter", realloc_mycatter, &target, initial, repeat, times);

    measure("prealloc_mycatter", prealloc_mycatter, &target, initial, repeat, times);

    return 0;
}

mystrcat()函数返回指向最后一个字符串位置的指针,保存下一次调用,必须再次遍历该字符串。此测试代码也可以gist

的形式提供

答案 4 :(得分:0)

正如DrKoch所提出的,多次调用realloc可能会对执行时间产生影响,具体取决于realloc的实现。

如果你已经有多少时间追加someVar,你可以一次分配所有必需的动态内存:

char *full;
char someVar[] ="test ";
int  nb_append = 200;
int  x = 0;

if ((full = malloc(sizeof (*full) * 8) == NULL)// allocating the memory
   // Handle malloc error;
strcpy(full,"Start: ");
if (realloc(full,sizeof(*full) * 8 + sizeof(someVar) * nb_append) == NULL) //reallocating for store only once
   // Handle realloc error;
while (x < nb_append ) {
     strcat(full, someVar);
     x++;
}

答案 5 :(得分:0)

如果迭代地重复追加字符串会导致O(n ^ 2)运行时间。相反,应该预先分配全部内存,并逐步构建字符串。

这是一些代码。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// append_extra returns a string consisting of init
// with count copies of extra appended.
// Or NULL on failure.
char *append_extra(char *init, char *extra, int count) {
    size_t len_init = strlen(init);
    size_t len_extra = strlen(extra);
    char *result = malloc(len_init + len_extra * count + 1);
    if (!result) {
       return 0;
    }
    char *p = result;
    strcpy(p, init);
    p += len_init;
    for (int i = 0; i < count; i++) {
        strcpy(p, extra);
        p += len_extra;
    }
    return result;
}

int main(void) {
    char *result = append_extra("hello", " world", 10);
    if (!result) exit(1);
    printf("'%s'\n", result);
    return 0;
}

答案 6 :(得分:0)

strcat()您有可能会进入the Schlemiel's algorithm

保持当前字符串长度并改为sprintf()(或snprintf()):

char *result;
size_t len = 0;
while (1) {
    /* make sure result points to a large enough area! */
    len += sprintf(result + len, "%s", "test ")
    if (stuff()) break;
}