Path: csiph.com!weretis.net!feeder9.news.weretis.net!news.quux.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: Something like string-streams existing in "C"? Date: Wed, 18 Dec 2024 18:14:22 -0800 Organization: None to speak of Lines: 50 Message-ID: <87a5csxvup.fsf@nosuchdomain.example.com> References: MIME-Version: 1.0 Content-Type: text/plain Injection-Date: Thu, 19 Dec 2024 03:14:23 +0100 (CET) Injection-Info: dont-email.me; posting-host="a3ce534ada3cb53cff25f1c73ad51d3e"; logging-data="2687855"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/Kd6A6ZYNRYrCTf8qy5q/+" User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:RbtSdiZU5AvfM4i7GzJqoiZsJCk= sha1:HSanGr+lugiQrDFmKhCEY7KRCLM= Xref: csiph.com comp.lang.c:389736 Janis Papanagnou writes: > Inspecting some of my "C" source code here I noticed a construct that > I dislike... > > static char buf[32]; // sufficient space for ansi sequence > ... > sprintf (buf, "\033[38;5;%dm%c\033[0m", ...); > > In case of known or deducible string sizes I'm preferring and using > some of the alloc() functions. In the sample I can at least deduce an > upper-bound for the buffer-size. But it's anyway still an undesired > hard-coded buffer size that I'd like to avoid. > > I recall that in C++ I used "String-Streams" for dynamically extended > strings. But in "C" my reflex (and habit) is to write things like the > above code. > > Is there something in "C" that allows dynamic flexibility of strings? > (Or are there other options that an experienced "C" programmer would > use instead?) > > (If there's something available only with newer C-standards I'd also > appreciate a hint.) You can use snprintf() for this. If the size argument is too small, it still returns the number of characters (excluding the terminating '\0') that would have been written to the buffer. char *buf; int arg1 = 42; int arg2 = 'x'; int size = snprintf(buf, 0, "\033[38;5;%dm%c\033[0m", arg1, arg2); printf("Allocating %d bytes\n", size + 1); buf = malloc(size + 1); // error checking skipped int actual_size = snprintf(buf, size + 1, "\033[38;5;%dm%c\033[0m", arg1, arg2); printf("actual_size = %d, buf = \"%s\"\n", actual_size, buf); Note that the output includes non-printing characters, so you'll want to pipe it throught `cat -A` or something similar. Beware that the size argument includes the terminating null byte, but the value returned does not (it returns the length of the resulting string, not its size). GNU and BSD provide a non-standard asprintf() function that lets you do this in one step. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com void Void(void) { Void(); } /* The recursive call of the void */