关于C#:如何使用sprintf附加字符串?

How to append strings using sprintf?

我面临sprintf的严重问题。

假设我的代码段是:

1
2
3
4
5
6
sprintf(Buffer,"Hello World");
sprintf(Buffer,"Good Morning");
sprintf(Buffer,"Good Afternoon");
.
.
.

几百冲刺...

如果我这样做,它就会被覆盖。

如何避免使用sprintf覆盖过多。 如果我在最后给出一个printf,我想查看所有行。


你需要:

1
2
3
sprintf(Buffer,"Hello World");
sprintf(Buffer + strlen(Buffer),"Good Morning");
sprintf(Buffer + strlen(Buffer),"Good Afternoon");

当然,您需要缓冲区足够大。


1
2
3
4
int length = 0;
length += sprintf(Buffer+length,"Hello World");
length += sprintf(Buffer+length,"Good Morning");
length += sprintf(Buffer+length,"Good Afternoon");

这是对错误有一定抵抗力的版本。如果您不关心何时会发生错误,这将很有用,只要您可以继续按照自己的喜好继续操作即可。

1
2
3
4
5
6
7
8
9
int bytes_added( int result_of_sprintf )
{
    return (result_of_sprintf > 0) ? result_of_sprintf : 0;
}

int length = 0;
length += bytes_added(sprintf(Buffer+length,"Hello World"));
length += bytes_added(sprintf(Buffer+length,"Good Morning"));
length += bytes_added(sprintf(Buffer+length,"Good Afternoon"));


为了安全(缓冲区溢出),我建议使用snprintf()

1
2
3
4
5
6
7
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);

int length = 0;
length += snprintf(Buffer+length, MAX_BUF-length,"Hello World");
length += snprintf(Buffer+length, MAX_BUF-length,"Good Morning");
length += snprintf(Buffer+length, MAX_BUF-length,"Good Afternoon");


snprintf()snprintfcat()包装器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
size_t
snprintfcat(
    char* buf,
    size_t bufSize,
    char const* fmt,
    ...)
{
    size_t result;
    va_list args;
    size_t len = strnlen( buf, bufSize);

    va_start( args, fmt);
    result = vsnprintf( buf + len, bufSize - len, fmt, args);
    va_end( args);

    return result + len;
}

使用sprintf()的返回值

1
2
3
Buffer += sprintf(Buffer,"Hello World");
Buffer += sprintf(Buffer,"Good Morning");
Buffer += sprintf(Buffer,"Good Afternoon");


当有专门针对您需要的方法(例如strcatstrncat)时,为什么要使用sprintf进行字符串连接?


我认为您正在寻找fmemopen(3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include
#include <stdio.h>

int main(void)
{
    char buf[128] = { 0 };
    FILE *fp = fmemopen(buf, sizeof(buf),"w");

    assert(fp);

    fprintf(fp,"Hello World!
"
);
    fprintf(fp,"%s also work, of course.
"
,"Format specifiers");
    fclose(fp);

    puts(buf);
    return 0;
}

如果动态存储更适合您的用例,则可以遵循Liam关于使用open_memstream(3)的出色建议:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char *buf;
    size_t size;
    FILE *fp = open_memstream(&buf, &size);

    assert(fp);

    fprintf(fp,"Hello World!
"
);
    fprintf(fp,"%s also work, of course.
"
,"Format specifiers");
    fclose(fp);

    puts(buf);
    free(buf);
    return 0;
}


您是否只是在附加字符串文字?还是要追加各种数据类型(int,float等)?

将其抽象到其自己的函数中可能会更容易(以下假设为C99):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

int appendToStr(char *target, size_t targetSize, const char * restrict format, ...)
{
  va_list args;
  char temp[targetSize];
  int result;

  va_start(args, format);
  result = vsnprintf(temp, targetSize, format, args);
  if (result != EOF)
  {
    if (strlen(temp) + strlen(target) > targetSize)
    {
      fprintf(stderr,"appendToStr: target buffer not large enough to hold additional string");
      return 0;
    }
    strcat(target, temp);
  }
  va_end(args);
  return result;
}

您将像这样使用它:

1
2
3
4
5
char target[100] = {0};
...
appendToStr(target, sizeof target,"%s %d %f
"
,"This is a test", 42, 3.14159);
appendToStr(target, sizeof target,"blah blah blah");

等等

该函数从vsprintf返回值,在大多数实现中,该值是写入目标的字节数。此实现中有一些漏洞,但是应该给您一些想法。


我发现以下方法很好用。

1
2
3
sprintf(Buffer,"Hello World");
sprintf(&Buffer[strlen[Buffer]],"Good Morning");
sprintf(&Buffer[strlen[Buffer]],"Good Afternoon");


使用strcat http://www.cplusplus.com/reference/cstring/strcat/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main ()
    {
      char str[80];
      strcpy (str,"these");
      strcat (str,"strings");
      strcat (str,"are");
      strcat (str,"concatenated.");
      puts (str);
      return 0;
    }




    Output:


    these strings are concatenated.

您可以使用下面显示的简单行将字符串追加到一个缓冲区中:

1
sprintf(Buffer,"%s %s %s","Hello World","Good Morning","Good Afternoon");


小完整代码示例

仅使用平面stdio标准库

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
    {
    char c[1024];
    int  i=0;

    i+=sprintf(c+i,"We"   );
    i+=sprintf(c+i,"Love" );
       sprintf(c+i,"Coding");

    printf("%s",c);
    }

输出:我们喜欢编码


我编写了一个函数支持动态变量字符串附加,例如PHP str append:str。海峡...等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

int str_append(char **json, const char *format, ...)
{
    char *str = NULL;
    char *old_json = NULL, *new_json = NULL;

    va_list arg_ptr;
    va_start(arg_ptr, format);
    vasprintf(&str, format, arg_ptr);

    // save old json
    asprintf(&old_json,"%s", (*json == NULL ?"" : *json));

    // calloc new json memory
    new_json = (char *)calloc(strlen(old_json) + strlen(str) + 1, sizeof(char));

    strcat(new_json, old_json);
    strcat(new_json, str);

    if (*json) free(*json);
    *json = new_json;

    free(old_json);
    free(str);

    return 0;
}

int main(int argc, char *argv[])
{
    char *json = NULL;

    /*
    str_append(&json,"name: %d, %d, %d", 1, 2, 3);
    str_append(&json,"sex: %s","male");
    str_append(&json,"end");
    str_append(&json,"");
    str_append(&json,"{"ret":true}");
    */


    int i;
    for (i = 0; i < 100; i++) {
        str_append(&json,"id-%d", i);
    }

    printf("%s
"
, json);

    if (json) free(json);

    return 0;
}

使用strcat(buffer," Your new string...here")作为选项。


关于什么:

1
2
3
4
5
6
7
8
9
char s[100] ="";

sprintf(s,"%s%s", s,"s1");

sprintf(s,"%s%s", s,"s2");

sprintf(s,"%s%s", s,"s3");

printf("%s", s);

但是要考虑可能的缓冲区卵流!