Alternative and probable better way to printf

R

Rudra Banerjee

Hello friends,
I am writing some string to a gstring using printf as:

g_string_append_printf (ustring, "@%s{%s,\n",string1, string0);
if( strlen(string2)!=0 ||string2!=NULL)
g_string_append_printf (ustring,"\tAuthor=\"%s\",\n", string2);
if( strlen(string3)!=0 ||string3!=NULL)
g_string_append_printf (ustring,"\tYear=\"%s\",\n", string3);
if( strlen(string4)!=0 ||string4!=NULL)
g_string_append_printf (ustring, "\tTitle=\"%s\",\n", string4);

GLib's are probably not exactly important here. Consider it as

printf ("\tAuthor=\"%s\",\n", string<i>)

When this works rather fine, it seems not the best way(i have strings string<1> to string<30>) and I am looking for some better way.

Some points to consider:
Any string may be empty/NULL, as checked by every line before the printf.
Any better way of implementing this?
 
E

Eric Sosman

Hello friends,
I am writing some string to a gstring using printf as:

g_string_append_printf (ustring, "@%s{%s,\n",string1, string0);
if( strlen(string2)!=0 ||string2!=NULL)

Aside: This test (and the others like it) should be

if (string2 != NULL && strlen(string2) != 0)

.... or (for fanatical cycle-shavers)

if (string2 != NULL && *string2 != '\0')
g_string_append_printf (ustring,"\tAuthor=\"%s\",\n", string2);
if( strlen(string3)!=0 ||string3!=NULL)
g_string_append_printf (ustring,"\tYear=\"%s\",\n", string3);
if( strlen(string4)!=0 ||string4!=NULL)
g_string_append_printf (ustring, "\tTitle=\"%s\",\n", string4);

GLib's are probably not exactly important here. Consider it as

printf ("\tAuthor=\"%s\",\n", string<i>)

When this works rather fine, it seems not the best way(i have strings string<1> to string<30>) and I am looking for some better way.

Some points to consider:
Any string may be empty/NULL, as checked by every line before the printf.
Any better way of implementing this?

C has a feature called the "array," which is quite helpful in
situations like this. You could use one string[] array instead of
string2,string3,...,string30 (they'd now be called string[0] through
string[28]), and a similar keyword[] array

static const char *keyword[29] = {
"Author", "Year", "Title", ... };

Then,

g_string_append_printf (ustring, "@%s{%s,\n",string1, string0);
for (int i = 0; i < 29; ++i) {
if (string != NULL && string[0] != '\0') {
g_string_append_printf(ustring, "\t%s=\"%s\",\n",
keyword, string);
}

I've left string0 and string1 as special cases, partly because
their formatting looks different from all the others and partly
because their order is swapped, but with sufficient ingenuity
you could subsume them in the loop, too.

Aside: The quotes you're adding around the data fields may
not be enough -- in particular, a data field that contains a
quote is likely to mess things up. See, for example, Harlan
Ellison's

"Repent, Harlequin!" Said the Ticktockman
 
M

Malcolm McLean

Hello friends,

I am writing some string to a gstring using printf as:



g_string_append_printf (ustring, "@%s{%s,\n",string1, string0);

if( strlen(string2)!=0 ||string2!=NULL)

g_string_append_printf (ustring,"\tAuthor=\"%s\",\n", string2);

if( strlen(string3)!=0 ||string3!=NULL)

g_string_append_printf (ustring,"\tYear=\"%s\",\n", string3);

if( strlen(string4)!=0 ||string4!=NULL)

g_string_append_printf (ustring, "\tTitle=\"%s\",\n", string4);



GLib's are probably not exactly important here. Consider it as



printf ("\tAuthor=\"%s\",\n", string<i>)



When this works rather fine, it seems not the best way(i have strings
string<1> to string<30>) and I am looking for some better way.



Some points to consider:
Any string may be empty/NULL, as checked by every line before the printf.
Any better way of implementing this?
Write a function on top of g_string_append_printf() which modifies it slightly
so that it takes a name and a string value as parameters, and appends a Perl-
parseable ? line in the form name = "value".
Make sure you handle the empty string, the null string, and the string
containing quote characters as the parser expects.
Then the higher level code is just a list of calls to this function, as before,
but with all the special cases and difficulty of adding the = sign stripped
out.
 
K

Keith Thompson

Rudra Banerjee said:
if( strlen(string2)!=0 ||string2!=NULL)
[...]

This test is incorrect. Calling strlen() on a null pointer has
undefined behavior, so you want to do the NULL check first, and you want
"&&", not "||":

if (string2 != NULL && strlen(string2) != 0)
 
N

Noob

Eric said:
Aside: This test (and the others like it) should be

if (string2 != NULL && strlen(string2) != 0)

... or (for fanatical cycle-shavers)

if (string2 != NULL && *string2 != '\0')

And fanatical character-shavers may write

if (string2 && *string2)

Regards.
 
E

Eric Sosman

And fanatical character-shavers may write

if (string2 && *string2)

What's with all that wasteful white space, huh? :)

A true story concerning cycle-shaving: I once got a
substantial speedup by making exactly the change shown above.
The program in question frequently used strlen() as the O.P.
does, in "Is this string empty?" queries where one doesn't
really need to know the length, just whether it's zero. All
was well on the machines where the program was developed and
on a few others it was ported to ...

.... and then we ported it to something called the MicroVAX II.
This was a small DEC machine, cost-reduced by implementing the
VAX architecture on just a few chips. Chips were smaller in
those days (ca. 1985), and there wasn't room for all of the
VAX' famously rich instruction set. So some instructions were
omitted: The hardware trapped, and a trap handler decoded the
offending instruction and emulated it in software.

All (or most) of VAX' string-handling instructions were
absent from MicroVAX, but the system shipped with the same C
library that grown-up VAXen used. Anybody want to speculate
on what VAX capabilities the <string.h> functions used, and on
how well MicroVAX ran them?

Ugh.
 
B

BartC

Rudra Banerjee said:
Hello friends,
I am writing some string to a gstring using printf as:

g_string_append_printf (ustring, "@%s{%s,\n",string1, string0);
if( strlen(string2)!=0 ||string2!=NULL)
g_string_append_printf (ustring,"\tAuthor=\"%s\",\n", string2);
if( strlen(string3)!=0 ||string3!=NULL)
g_string_append_printf (ustring,"\tYear=\"%s\",\n", string3);
if( strlen(string4)!=0 ||string4!=NULL)
g_string_append_printf (ustring, "\tTitle=\"%s\",\n", string4);
printf ("\tAuthor=\"%s\",\n", string<i>)

When this works rather fine, it seems not the best way(i have strings
string<1> to string<30>) and I am looking for some better way.

Create two arrays: one with the labels ("Author", "Year", etc), another with
pointers to the strings (or form string/2/3/etc into an array).

Then a simple loop will call a function on each corresponding pair of
strings, that will contain the print statement as well as any checks needed,
eg:

if (text)
. ..print("\t%s=%s",label,text);
 
S

Siri Cruise

Create two arrays: one with the labels ("Author", "Year", etc), another with
pointers to the strings (or form string/2/3/etc into an array).

Then a simple loop will call a function on each corresponding pair of
strings, that will contain the print statement as well as any checks needed,
eg:

if (text && *text)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top