lblinc
asked on
C --> how to apply a comma format to any column, or multiple columns of either int OR float data
Guys, I was only able to get my "Commify" function to work on 1 column at a time, thus only 1 column in the print statement could be "commify'd". Admit that i am lost with this one as i need to get more experience programming C using buffers, etc. If anyone has some thoughts in the meantime, here is some example data and the code I'm using below... using Kent's advice I started to add buffers to the beginning of the insert_commas() function, but still unsure how to put this all together.. ? - LBL (I will make this more points b/c i really would like to resolve this one!)
Data Before --> (would like to Commify cols 2, 5, 6, 7 here...)
AAA 1000000 10.000 1.000 1000000 1000000 1000000
BBB 2000000 20.000 2.000 2000000 2000000 2000000
CCC 3000000 30.000 3.0000 3000000 3000000 3000000
Data After --> (Requested Output should look like here...)
AAA 1,000,000 10.000 1.000 1,000,000 1,000,000 1,000,000
BBB 2,000,000 20.000 2.000 2,000,000 2,000,000 2,000,000
CCC 3,000,000 30.000 3.0000 3,000,000 3,000,000 3,000,000
The print statement -->
(void)printf("%-7s%7.0f%8. 3f%8.3f %10.0f %8.0f %9.0f\n", col1, col2, col3, col4, col5, col6, col7); // trying to commify col2, col5, col6, col7
char *CommifyInt(long *Value)
{
int orig_value;
int abs_value;
char sibuf[512];
char sibuf2[512];
orig_value = *Value;
abs_value = abs(orig_value);
sprintf( sibuf, "%ld", abs_value );
insert_commas(sibuf);
sprintf( sibuf2, "%s%s", orig_value < 0 ? "-" : "", sibuf );
return sibuf2;
}
char *CommifyFloat(double *Value)
{
int orig_value;
int abs_value;
char sfbuf[512];
char sfbuf2[512];
orig_value = *Value;
abs_value = abs(orig_value);
sprintf( sfbuf, "%lf", abs_value );
insert_commas(sfbuf);
sprintf( sfbuf2, "%s%s", orig_value < 0 ? "-" : "", sfbuf );
return sfbuf2;
}
void
*insert_commas(char *s1)
{
char *s2,*s3, *s5;
static char b0[15];
static char b1[15];
static char b2[15];
static char b3[15];
static char b4[15];
static char b5[15];
static char b6[15];
static char b7[15];
static char *bx[8] = {&b0, &b1, &b2, &b3, &b4, &b5, &b6, &b7};
static int BufferCount = 0;
s5 = bx[(BufferCount++) & 7];
s3 = strchr(s1,'.');
if(s3 == NULL) {
reverse(s1);
doit(s1);
reverse(s1);
} else {
s2 = strtok(s1,".");
s3 = strtok('\0',".");
strcpy(s5,s3);
reverse(s2);
doit(s2);
reverse(s2);
sprintf(s1,"%s.%s",s2,s5);
}
return s5;
}
void
*reverse(char *s1)
{
int i, len;
if(strlen(s1) < 1)
return;
for (i=0, len=strlen(s1)-1; i<(strlen(s1)/2); i++, len--) {
char t = s1[i];
s1[i] = s1[len];
s1[len] = t;
}
return;
}
void
*doit(char *s1)
{
int len = strlen(s1);
int i, j;
char t1[30];
for(i=0, j=0; i<len; i++) {
if((!(i % 3)) && (i > 0))
t1[j++] = ',';
t1[j++] = s1[i];
}
t1[j] = '\0';
strcpy(s1,t1);
return;
}
Data Before --> (would like to Commify cols 2, 5, 6, 7 here...)
AAA 1000000 10.000 1.000 1000000 1000000 1000000
BBB 2000000 20.000 2.000 2000000 2000000 2000000
CCC 3000000 30.000 3.0000 3000000 3000000 3000000
Data After --> (Requested Output should look like here...)
AAA 1,000,000 10.000 1.000 1,000,000 1,000,000 1,000,000
BBB 2,000,000 20.000 2.000 2,000,000 2,000,000 2,000,000
CCC 3,000,000 30.000 3.0000 3,000,000 3,000,000 3,000,000
The print statement -->
(void)printf("%-7s%7.0f%8.
char *CommifyInt(long *Value)
{
int orig_value;
int abs_value;
char sibuf[512];
char sibuf2[512];
orig_value = *Value;
abs_value = abs(orig_value);
sprintf( sibuf, "%ld", abs_value );
insert_commas(sibuf);
sprintf( sibuf2, "%s%s", orig_value < 0 ? "-" : "", sibuf );
return sibuf2;
}
char *CommifyFloat(double *Value)
{
int orig_value;
int abs_value;
char sfbuf[512];
char sfbuf2[512];
orig_value = *Value;
abs_value = abs(orig_value);
sprintf( sfbuf, "%lf", abs_value );
insert_commas(sfbuf);
sprintf( sfbuf2, "%s%s", orig_value < 0 ? "-" : "", sfbuf );
return sfbuf2;
}
void
*insert_commas(char *s1)
{
char *s2,*s3, *s5;
static char b0[15];
static char b1[15];
static char b2[15];
static char b3[15];
static char b4[15];
static char b5[15];
static char b6[15];
static char b7[15];
static char *bx[8] = {&b0, &b1, &b2, &b3, &b4, &b5, &b6, &b7};
static int BufferCount = 0;
s5 = bx[(BufferCount++) & 7];
s3 = strchr(s1,'.');
if(s3 == NULL) {
reverse(s1);
doit(s1);
reverse(s1);
} else {
s2 = strtok(s1,".");
s3 = strtok('\0',".");
strcpy(s5,s3);
reverse(s2);
doit(s2);
reverse(s2);
sprintf(s1,"%s.%s",s2,s5);
}
return s5;
}
void
*reverse(char *s1)
{
int i, len;
if(strlen(s1) < 1)
return;
for (i=0, len=strlen(s1)-1; i<(strlen(s1)/2); i++, len--) {
char t = s1[i];
s1[i] = s1[len];
s1[len] = t;
}
return;
}
void
*doit(char *s1)
{
int len = strlen(s1);
int i, j;
char t1[30];
for(i=0, j=0; i<len; i++) {
if((!(i % 3)) && (i > 0))
t1[j++] = ',';
t1[j++] = s1[i];
}
t1[j] = '\0';
strcpy(s1,t1);
return;
}
Maybe this previous question could be helpful:
https://www.experts-exchange.com/questions/20409761/how-do-i-insert-commas-in-a-number.html
https://www.experts-exchange.com/questions/20409761/how-do-i-insert-commas-in-a-number.html
Two threads closed within the last week on this subject, too.
Kent
https://www.experts-exchange.com/questions/21281084/1-How-to-pass-data-to-insert-commas-char-function-2-AND-how-to-print-out-the-comma-formatted-numbers.html
https://www.experts-exchange.com/questions/21281756/C-code-comma-format-works-however-140000-passed-to-insert-commas-returns-140-000.html
ASKER
Kent - I closed the threads on this last week when I got this working properly, but only on 1 column of data! I thought I could easily move ahead to the rest of the columns... but i could only get 1 variable from the printf statement to be comma formatted.
I do not have ANY questions on how to do the comma formatting on the numbers (i've been shown plenty of examlpes).
My question remaining, before i give up on this ;), is how to successfully printf multiple columns in this comma format. I realize it's a simple concept, but I've made so many different attempts with no luck.
Isn't there a brief example of this somewhere? Should the printf statement look like the following?
Let's say you wanted to comma format float data columns 2, 3, 4 and 7 from below printf... is this correct to try to use printf this way?
(void)printf("%7s %12s %12s %12s %8.3f %9.5f %12s\n", name, CommaConvertFloat(&data2), CommaConvertFloat(&data3), CommaConvertFloat(&data4), data5, data6, CommaConvertFloat(&data7)) ;
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- -----
If there was just one working example (not just the comma format piece) where this Data Before could look like this Data After (see below). Again, the before data in cols 2, 5, 6, 7 is type FLOAT because calcs need to be performed before the formatting.
Data Before --> (would like to Commify cols 2, 5, 6, 7 here...)
AAA 1000000.00 10.000 1.000 1000000.00 1000000.00 1000000.00
BBB 2000000.00 20.000 2.000 2000000.00 2000000.00 2000000.00
CCC 3000000.00 30.000 3.0000 3000000.00 3000000.00 3000000.00
Data After --> (Requested Output should look like here...)
AAA 1,000,000.00 10.000 1.000 1,000,000.00 1,000,000.00 1,000,000.00
BBB 2,000,000.00 20.000 2.000 2,000,000.00 2,000,000.00 2,000,000.00
CCC 3,000,000.00 30.000 3.0000 3,000,000.00 3,000,000.00 3,000,000.00
I know, i know... All this just to get float data formatted properly. Not sure if homework will do me any good today, i'm fairly beat up over this. - LBL
I do not have ANY questions on how to do the comma formatting on the numbers (i've been shown plenty of examlpes).
My question remaining, before i give up on this ;), is how to successfully printf multiple columns in this comma format. I realize it's a simple concept, but I've made so many different attempts with no luck.
Isn't there a brief example of this somewhere? Should the printf statement look like the following?
Let's say you wanted to comma format float data columns 2, 3, 4 and 7 from below printf... is this correct to try to use printf this way?
(void)printf("%7s %12s %12s %12s %8.3f %9.5f %12s\n", name, CommaConvertFloat(&data2),
--------------------------
If there was just one working example (not just the comma format piece) where this Data Before could look like this Data After (see below). Again, the before data in cols 2, 5, 6, 7 is type FLOAT because calcs need to be performed before the formatting.
Data Before --> (would like to Commify cols 2, 5, 6, 7 here...)
AAA 1000000.00 10.000 1.000 1000000.00 1000000.00 1000000.00
BBB 2000000.00 20.000 2.000 2000000.00 2000000.00 2000000.00
CCC 3000000.00 30.000 3.0000 3000000.00 3000000.00 3000000.00
Data After --> (Requested Output should look like here...)
AAA 1,000,000.00 10.000 1.000 1,000,000.00 1,000,000.00 1,000,000.00
BBB 2,000,000.00 20.000 2.000 2,000,000.00 2,000,000.00 2,000,000.00
CCC 3,000,000.00 30.000 3.0000 3,000,000.00 3,000,000.00 3,000,000.00
I know, i know... All this just to get float data formatted properly. Not sure if homework will do me any good today, i'm fairly beat up over this. - LBL
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
btw - the data I'm working with is read in from a text file and convereted to float type in most cases in order to do the calcs...
strncpy(buf, str+7+6, 10); buf[10] = 0; data2 = atof(buf);
strncpy(buf, str+7+6+10,13); buf[13] = 0; data5 = atof(buf);
strncpy(buf, str+7+6+10+13, 13); buf[13] = 0; data6 = atof(buf);
after performaing the calcs, I then can do the comma formatting just fine. But...
where I'm stuck now is in these 2 areas...
1) passing the data back to the printf
2) running this function on multiple columns of data, all that were of type float
Somebody out there must have had to do a very similar comma format procedure on multiple columns of float numbers? No? - LBL
strncpy(buf, str+7+6, 10); buf[10] = 0; data2 = atof(buf);
strncpy(buf, str+7+6+10,13); buf[13] = 0; data5 = atof(buf);
strncpy(buf, str+7+6+10+13, 13); buf[13] = 0; data6 = atof(buf);
after performaing the calcs, I then can do the comma formatting just fine. But...
where I'm stuck now is in these 2 areas...
1) passing the data back to the printf
2) running this function on multiple columns of data, all that were of type float
Somebody out there must have had to do a very similar comma format procedure on multiple columns of float numbers? No? - LBL
There are several good techniques. Here's one that will work no matter how many fields you want to format.
char Buffer[200];
char *Object;
fgets (Buffer, 200, stdin);
Object = strtok (Buffer, " "); /* note that strtok will write in the source string */
fprintf (" %s ", Buffer); /* echo the first column back to the output file */
Object = strtok (NULL, " ");
while (Object)
{
/* insert commas into Ojbect */
fprintf (stdout, " %s ", ConvertedObject);
}
fprintf (stdout, "\n");
Kent
ASKER
Sunnycoder, Thanks for your reply. Yes, all i want is to be able to commify the value, but in "multiple" column(s) of my choice. I am able to develop some code which can get me the value in the desired column.
I have to step away now for a bit, but I will look over your comment... I think that may be what I've been trying to do. - LBL
I have to step away now for a bit, but I will look over your comment... I think that may be what I've been trying to do. - LBL
ASKER
Kent, Thanks much. I have to step away from this now. but later today I'm going to try to get closure on this, I'll try your technique, and look over sunnycoder's control flow...
I feel like I'm getting closer. :)
I feel like I'm getting closer. :)
Cool.
When you try it, you'd better modify the loop to be:
while (Object)
{
/* insert commas into Ojbect */
fprintf (stdout, " %s ", ConvertedObject);
Object = strtok (NULL, " ");
}
Otherwise it will run a llooonnnnnnggggggggggggggg
Kent
what about formatting using a single tick modifier? I had to set the locale first explicitly:
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
main()
{
struct lconv *l;
setlocale(LC_NUMERIC,"en_U S");
l = localeconv();
printf("separator: %s\n", l->thousands_sep);
printf ("%+-'17.2f", 10000000.00);
}
This produces the following output:
separator: ,
+10,000,000.00
tested on Solaris and RedHat.
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
main()
{
struct lconv *l;
setlocale(LC_NUMERIC,"en_U
l = localeconv();
printf("separator: %s\n", l->thousands_sep);
printf ("%+-'17.2f", 10000000.00);
}
This produces the following output:
separator: ,
+10,000,000.00
tested on Solaris and RedHat.
ASKER
zdes - I tried the setlocale code from above, but on my PC... it compiles fine using cc -o and .Net
but the output is as follows:
separator:
10000000.00
not sure why it seems to not recognize the separator? i'm using both cygwin and Microsoft VS .Net
? - LBL
but the output is as follows:
separator:
10000000.00
not sure why it seems to not recognize the separator? i'm using both cygwin and Microsoft VS .Net
? - LBL
The names of the locales can differ between the platforms. I do not have access to windoze now. I'll try to check it later today.
ASKER
zdes - On windoze, I noticed when I change to english instead of en_US i now see the comma separator as follows:
separator: ,
+10000000.00
but still lacking format... ?
thanks,
- LBL
separator: ,
+10000000.00
but still lacking format... ?
thanks,
- LBL
ASKER
below code on Win XP produces... no commas.. ? need to update locale.h ? - LBL
separator: ,
+10000000.00
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- --
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
main()
{
struct lconv *l;
setlocale(LC_NUMERIC, "english");
l = localeconv();
printf("separator: %s\n", l->thousands_sep);
printf("%+-17.2f", 10000000.00);
}
separator: ,
+10000000.00
--------------------------
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
main()
{
struct lconv *l;
setlocale(LC_NUMERIC, "english");
l = localeconv();
printf("separator: %s\n", l->thousands_sep);
printf("%+-17.2f", 10000000.00);
}
I am looking through MSDN docs. Apparently, the format specs in printf are different and do not include single tick that I saw documented on Unix. I see that another member of the same lconv struct (grouping) has a correct value of 3, which means to put thousands_set every 3 chars going from the decimal point to the left, but I do not know how to trigger this behavior on windows at the moment (lack of POSIX?)
I have not found C solution for Windows without writing custom code to insert comas. There are some on 'net using C++ and STL. PHP and such.
From the docs I see, C code with a single tick format modifier works ok on aix, hpux, solaris, and linux. but not on Windows. I've installed the latest cygwin with gcc 3.3.3, but it too does not take this modifier. So roll back to what Kdo and others suggest. Or format C:, install Linux :-)
From the docs I see, C code with a single tick format modifier works ok on aix, hpux, solaris, and linux. but not on Windows. I've installed the latest cygwin with gcc 3.3.3, but it too does not take this modifier. So roll back to what Kdo and others suggest. Or format C:, install Linux :-)
ASKER
Ok. Thanks zdes. - LBL
ASKER
THANKS TO ALL FOR THE POSTS! I finally got it the way it should look; it works fine. I KNOW it could probably be made more efficient, look forward to that actually... So maybe next questions could be about cleaning it up a bit, but for now the output looks precisely as i wanted.
In the end I really found Sunnycoder's post above to be the most useful to get to completion with things. I used a derivation of Sunnycoder's control flow example above. Kdo, as always, ...Kent provided some great input. The tricky part was that only a few columns out of many (not in order) needed to be Commified... I would have really liked to use the change of locale using LC_NUMERIC that zdes mentioned, but no luck on windows using .Net after much trial and error. After this project i decided that Cygwin is ok for now, but thinking of installing Linux in the near future.
My biggest issues were:
1) I had an existing insert_comma() function that was not perfect, but functional...needs some work to be 100%... i wanted to keep it, but it was not easy... i had to pass abs() values converted into string format to the insert_commas().
2) The file read into the program had columns in no specific priority making it hard to just print out the entire commified string as Sunnycoder suggested, but i adapted finally using that concept.
- LBL
In the end I really found Sunnycoder's post above to be the most useful to get to completion with things. I used a derivation of Sunnycoder's control flow example above. Kdo, as always, ...Kent provided some great input. The tricky part was that only a few columns out of many (not in order) needed to be Commified... I would have really liked to use the change of locale using LC_NUMERIC that zdes mentioned, but no luck on windows using .Net after much trial and error. After this project i decided that Cygwin is ok for now, but thinking of installing Linux in the near future.
My biggest issues were:
1) I had an existing insert_comma() function that was not perfect, but functional...needs some work to be 100%... i wanted to keep it, but it was not easy... i had to pass abs() values converted into string format to the insert_commas().
2) The file read into the program had columns in no specific priority making it hard to just print out the entire commified string as Sunnycoder suggested, but i adapted finally using that concept.
- LBL
Cheers!!!
Thanks for the points and the praise ...
https://www.experts-exchange.com/help.jsp#hi73
https://www.experts-exchange.com/help.jsp#hi18
Thanks for the points and the praise ...
https://www.experts-exchange.com/help.jsp#hi73
https://www.experts-exchange.com/help.jsp#hi18
LBL, thank you for the props.
ASKER
Guys - As I am fairly new on the experts-exchange board... I did not realize points could be split. I will have many more questions in future, I'm sure, so next time, when all answers are good, or even have indirect solution (but correct) answer to the question, I'll divvy up some points to those that answer this way.
Thanks again.
- LBL
Thanks again.
- LBL
That's OK. We're used to Sunny grabbing all of the points.
;)
Yeah Right ... Cant recollect where I saw this
Kdo 24192
grg99 14188
sunnycoder 13932
ummm ... darn ... <scratching head>
;-)
Kdo 24192
grg99 14188
sunnycoder 13932
ummm ... darn ... <scratching head>
;-)
As near as I can tell, you were on holiday until about the 15th. :)
It's kind of like when the home team lets the visitors jump out to an early lead and then come storming back to win the game.
Except in this case, you may have let one get away. If I can only hold you at bay for 3 more days.......
Or maybe you were posting what the monthly totals will have to continue to be for either grg99 or me to catch you in a single lifetime. ;)
You've been quiet this month. Good to see you back at it.
Kent
>If I can only hold you at bay for 3 more days.......
What do you think is keeping me awake in front of my PC at 12:15 AM ;-)
At the rates of current month, and indications of work pressures, you will be able to catch up with me in 6-9 months ... I am just trying to stretch that to early 2006 ... If you are going to get it, I may as well make you sweat a bit ;-)
What do you think is keeping me awake in front of my PC at 12:15 AM ;-)
At the rates of current month, and indications of work pressures, you will be able to catch up with me in 6-9 months ... I am just trying to stretch that to early 2006 ... If you are going to get it, I may as well make you sweat a bit ;-)
>>What do you think is keeping me awake in front of my PC at 12:15 AM ;-)
Actually, I WAS going to ask you that!
>>If you are going to get it, I may as well make you sweat a bit ;-)
You're assuming that I won't decide to acquire a life in this time. :)
>>>If you are going to get it, I may as well make you sweat a bit ;-)
>You're assuming that I won't decide to acquire a life in this time. :)
:-( :-( .. dont spoil my fun :-(
>You're assuming that I won't decide to acquire a life in this time. :)
:-( :-( .. dont spoil my fun :-(
Then do substring operations
Search for decimal point. say ith position
Using this i u can decide where commas should be. Just make a new string using commas.
Like 123456.99900 index will be 6,
need to insert comma at (6-3) = 3rd position,
and another (6-5) = 1st position.
So it would be 1,23,456.999900