Jak dodawać ciągi za pomocą sprintf?

Mam poważny problem ze sprintf.

Załóżmy, że mój fragment kodu to:

sprintf(Buffer,"Hello World");
sprintf(Buffer,"Good Morning");
sprintf(Buffer,"Good Afternoon");
.
.
.
Sto sprintów....

Jeśli to zrobię, to zostanie nadpisane.

Jak mogę uniknąć nadpisywania za pomocą sprintf. Jeśli podam printf na końcu chcę zobaczyć wszystkie linie.

 48
Author: Starfish, 2010-04-20

15 answers

Potrzebujesz:

sprintf(Buffer,"Hello World");
sprintf(Buffer + strlen(Buffer),"Good Morning");
sprintf(Buffer + strlen(Buffer),"Good Afternoon");
I oczywiście musisz mieć wystarczająco duży bufor.
 86
Author: hypercrypt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-02 17:55:33
int length = 0;
length += sprintf(Buffer+length, "Hello World");
length += sprintf(Buffer+length, "Good Morning");
length += sprintf(Buffer+length, "Good Afternoon");

Oto wersja z pewną odpornością na błędy. Jest to przydatne, jeśli nie obchodzi cię, kiedy błędy się zdarzają, tak długo, jak możesz kontynuować swoją wesołą drogę, Kiedy to robią.

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"));
 61
Author: Matthew T. Staebler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-20 11:36:06

Dla bezpieczeństwa (przepełnienie bufora) polecam użycie snprintf ()

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");
 27
Author: Oleg Razgulyaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-20 12:03:29

A snprintfcat() wrapper dla snprintf():

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;
}
 12
Author: Michael Burr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-20 17:10:08

Dlaczego chcesz używać sprintf do konkatenacji łańcuchów, gdy istnieją metody przeznaczone specjalnie do tego, czego potrzebujesz, takie jak strcat oraz strncat?

 6
Author: SergGr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-20 10:44:05

Użyj wartości zwracanej sprintf()

Buffer += sprintf(Buffer,"Hello World");
Buffer += sprintf(Buffer,"Good Morning");
Buffer += sprintf(Buffer,"Good Afternoon");
 6
Author: Jeegar Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-18 12:25:07

Czy po prostu dodajesz literały łańcuchów? A może będziesz dodawać różne typy danych (int, float, itp.)?

Może być łatwiej wyodrębnić to do własnej funkcji (następująca zakłada C99):

#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;
}

I użyłbyś go tak:

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

Itd.

Funkcja zwraca wartość z vsprintf, która w większości implementacji jest liczbą bajtów zapisanych do miejsca docelowego. Jest kilka dziur w tej implementacji, ale powinno mam kilka pomysłów.

 3
Author: John Bode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-20 14:39:38

Uważam, że poniższa metoda działa ładnie.

sprintf(Buffer,"Hello World");
sprintf(&Buffer[strlen[Buffer]],"Good Morning");
sprintf(&Buffer[strlen[Buffer]],"Good Afternoon");
 3
Author: McBartok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-18 15:54:38

Myślę, że szukasz fmemopen(3):

#include <assert.h>
#include <stdio.h>

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

    assert(fp);

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

    puts(buf);
    return 0;
}

Jeśli dynamic storage jest bardziej odpowiedni dla Ciebie use-case, możesz zastosować się do doskonałej sugestii Liama o użyciu open_memstream(3):

#include <assert.h>
#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!\n");
    fprintf(fp, "%s also work, of course.\n", "Format specifiers");
    fclose(fp);

    puts(buf);
    free(buf);
    return 0;
}
 3
Author: wkz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-01 17:21:34

Możesz użyć prostej linii pokazanej poniżej, aby dodać łańcuchy w jednym buforze:

sprintf(Buffer,"%s %s %s","Hello World","Good Morning","Good Afternoon");
 1
Author: ravibhuva9955,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-18 16:08:23

Użyj strcat http://www.cplusplus.com/reference/cstring/strcat/

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
Author: arun pal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-29 05:06:26

Piszę funkcję obsługującą dynamiczną zmienną string append, jak PHP str append: str . str . ... itd.

#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\n", json);

    if (json) free(json);

    return 0;
}
 0
Author: Wei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-16 01:09:33

PRZYKŁAD MAŁEGO PEŁNEGO KODU

Korzystanie z flat plain stdio tylko z biblioteki standardowej

(i nie martw się o rozmiar wektora znaków crash z " out bounds "sprintf , cool hun?!!):

#include <stdio.h>
char c[]="";
int main()
    {
    int i=0;
    i+=sprintf(c+i,"Sergio ");
    i+=sprintf(c+i,"Mcfly ");
    i+=sprintf(c+i,"NY-USA ");
    i+=sprintf(c+i,"bla bla blahh...455453853;-)");
    printf("%s",c);
    }

Wyjście: Sergio Mcfly NY-USA bla bla blah...455453853;-)

 0
Author: PYK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-30 23:26:17

Using strcat(buffer,"Your new string...here"), jako opcja.

 -2
Author: kahsay kalayu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-17 06:49:26

A co z:

char s[100] = "";

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

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

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

printf("%s", s);

Ale weź pod uwagę możliwe przepływy buforowe!

 -4
Author: Jordi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-20 10:56:31