strcat() for formatted strings

前端 未结 6 1474
予麋鹿
予麋鹿 2021-02-20 05:37

I\'m building a string piece by piece in my program and am currently using a mix of strcat() when I\'m adding a simple string onto the end, but when im adding a formatted string

相关标签:
6条回答
  • 2021-02-20 05:52

    Everything can be more simpler

    void strfcat(char *src, char *fmt, ...)
    {
        char buf[2048];
        va_list args;
    
        va_start(args, fmt);
        vsprintf(buf, fmt, args);
        va_end(args);
    
        strcat(src, buf);
    }
    

    Use it like strcat().

    strfcat(dst, "%d:%s:%c\n", 4,"bla",'c');
    strfcat(dst, "%d:%d:%c\n", 4,13,'s');
    
    0 讨论(0)
  • 2021-02-20 05:56

    Write your own wrapper for your need.

    A call to this would look like this :-

    result = universal_concatenator(4,result,"numbers are %d %f\n",5,16.045);  
    result = universal_concatenator(2,result,"tail_string");
    

    You could define one function, that would take care of worrying about, if you need to use sprintf() or strcat(). This is what the function would look like :-

    /* you should pass the number of arguments
     * make sure the second argument is a pointer to the result always
     * if non formatted concatenation:
     *         call function with number_of_args = 2
     * else
     *         call function with number of args according to format
     *         that is, if five inputs to sprintf(), then 5.
     *
     * NOTE : Here you make an assumption that result has been allocated enough memory to
     *        hold your concatenated string. This assumption holds true for strcat() or
     *        sprintf() of your previous implementation 
     */
    
    char* universal_concaternator(int number_of_args,...)
    {
      va_list args_list;
      va_start(args_list,number_of_args);
      int counter = number_of_args;
      char *result = va_arg(args_list, char*);
      char *format;
      if(counter == 2) /* it is a non-formatted concatenation */
      {
          result = strcat(result,va_arg(args_list,char*));
          va_end(args_list);
          return result;
      }
      /* else part - here you perform formatted concatenation using sprintf*/
      format = va_arg(args_list,char*);
      vsprintf(result + strlen(result),format,args_list);
      va_end(args_list);
      return result; 
    }
    
    /* dont forget to include the header 
     * <stdarg.h> #FOR-ANSI 
     * or <varargs.h> #FOR-UNIX
     */ 
    

    It should firstly, determine, which of the two it should call(strcat or sprintf), then it should make the call, and make it easy for you to concentrate on the actual logic of whatever you are working on! Just ctrl+c code above and ctrl+v into your code base.

    Note : Matt's answer is a good alternative for long strings. But for short string lengths(<250), this should do.

    0 讨论(0)
  • 2021-02-20 06:01

    To answer the direct question, sure, it's possible to use strcat to append formatted strings. You just have to build the formatted string first, and then you can use strcat to append it:

    #include <stdio.h>
    #include <string.h>
    int main(void) {
        char s[100];
        char s1[20];
        char s2[30];
        int n = 42;
        double x = 22.0/7.0;
    
        strcpy(s, "n = ");
        sprintf(s1, "%d", n);
        strcat(s, s1);
    
        strcat(s, ", x = ");
        sprintf(s2, "%.6f", x);
        strcat(s, s2);
    
        puts(s);
        return 0;
    }
    

    Output:

    n = 42, x = 3.142857
    

    But this is not a particularly good approach.

    sprintf works just as well writing to the end of an existing string. See Mats's answer and mux's answer for examples. The individual arrays used to hold individual fields are not necessary, at least not in this case.

    And since this code doesn't keep track of the end of the string, the performance is likely to be poor. strcat(s1, s2) first has to scan s1 to find the terminating '\0', and then copy the contents of s2 into it. The other answers avoid this by advancing an index or a pointer to keep track of the end of the string without having to recompute it.

    Also, the code makes no effort to avoid buffer overruns. strncat() can do this, but it just truncates the string; it doesn't tell you that it was truncated. snprintf() is a good choice; it returns the number of characters that it would have written if enough space were available. If this exceeds the size you specify, then the string was truncated.

    /* other declarations as above */
    size_t count;
    count = snprintf(s, sizeof s, "n = %d, x = %.6f", n, x);
    if (count > sizeof s) {
        /* the string was truncated */
    }
    

    And to append multiple strings (say, if some are appended conditionally or repeatedly), you can use the methods in the other answers to keep track of the end of the target string.

    So yes, it's possible to append formatted strings with strcat(). It's just not likely to be a good idea.

    0 讨论(0)
  • 2021-02-20 06:01

    What the preferred method is, depends on what you are willing to use. Instead of doing all those manual (and potentially dangerous) string operations, I would use the GString data structure from GLib or GLib's g_strdup_print function. For your problem, GString provides the g_string_append_printf function.

    0 讨论(0)
  • 2021-02-20 06:08

    no it's not possible but you could use sprintf() on those simple strings and avoid calling strlen() every time:

    len = 0;
    len += sprintf(buf+len, "%s", str);    
    len += sprintf(buf+len, " number %d", one);
    
    0 讨论(0)
  • 2021-02-20 06:13

    Your solution will work. Calling strlen is a bit awkward (particularly if the string gets quite long). sprintf() will return the length you have used [strcat won't], so one thing you can do is something like this:

     char str[MAX_SIZE];
     char *target = str;
    
     target += sprintf(target, "%s", str_value);
     target += sprintf(target, "somestuff %d", number);
     if (something)
     {
        target += sprintf(target, "%s", str_value2);
     }
     else
     {
        target += sprintf(target, "%08x", num2);
     }
    

    I'm not sure strcat is much more efficient than sprintf() is when used in this way.

    Edit: should write smaller examples...

    0 讨论(0)
提交回复
热议问题