开发者

How to build char* from array of char*

开发者 https://www.devze.com 2023-03-17 17:46 出处:网络
Please have a look at the following code: #include <stdio.h> #include <stdlib.h> typedef struct {

Please have a look at the following code:

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

typedef struct {
        const char * cmd;
        const char * help;
} CmdEnum;

static CmdEnum cmd_enum[] = {
        {"help", "This help..."},
        {"first", "The first command"},
        {"second", "The second command"},
};

void main()
{
    int i,n;
    char *out = "";

        n = sizeof(cmd_enum) / sizeof(CmdEnum);
        for (i=0; i<n; i++)
        {
            char *oldOut = out;
            CmdEnum cmd = cmd_enum[i];
            asprintf(&out, "%s%s -> %s\n", oldOut, cmd.cmd, cmd.help);
            if(i>0) free(oldOut);
        }

    printf("%s", out);
    printf("Done.\n");
}

Is this a good way to build a text from the CmdEnum?

Is there a "nicer" way do define cmd in the first place as to avoid the if(i>0) free...?

Or am I doing something entirely wrong?

EDIT:

After reading larsmans' answer I modified main to:

int main()
{
    int i,n, copied, siz;
    char *out, *cursor;
    siz = 1;// 1 for NUL char
    n = sizeof(cmd_enum) / sizeof(开发者_JAVA技巧CmdEnum);

    for (i=0; i<n; i++)
    {
        siz += strlen(cmd_enum[i].cmd) + strlen(cmd_enum[i].help) + strlen(":\n\t\n\n");
    }

    out = malloc(siz);
    if(!out)
    {
        printf("Could not alloc!\n");
        return 1;
    }

    cursor = out;
    for (i=0; i<n; i++)
    {
        copied = snprintf(cursor, siz, "%s:\n\t%s\n\n", cmd_enum[i].cmd, cmd_enum[i].help);
        if(copied < 0 || copied >= siz)
        {
            printf("snprintf failed: %i chars copied.\n", copied);
            return 1;
        }

        cursor += copied;
        siz -= copied;
    }

    printf("%s", out);
    printf("Done.\n");
    free(out);
    return 0;
}

(Note: I also changed the output format...)


Is this a good way to build a text from the CmdEnum?

Yes, except that asprintf is not portable (although you can define it easily in terms of snprintf for platforms that don't have it) and you're not checking error returns. void main isn't valid C btw.

Is there a "nicer" way do define cmd in the first place as to avoid the if(i>0) free...?

You could allocate the whole string beforehand.

size_t i, siz = 1;  // 1 for NUL char
for (i=0; i<n; i++)
    siz += strlen(cmd_enum[i].cmd) + strlen(cmd_enum[i].help) + strlen(" -> \n");

char *out = malloc(siz);
// check for errors

then build the string with snprintf. This saves you some malloc'ing and error checking in the loop.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号