fork download
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <string.h>
  4. #include <stdint.h>
  5.  
  6. char *fmtp04f(char *buf, char *lim, double d) {
  7. // if there's no space at all don't bother
  8. if(buf==lim) return buf;
  9. // 10 characters in maximum 32 bit integer, one for the dot,
  10. // one for the terminating NUL in debug prints
  11. char b[12];
  12. // current position in the buffer
  13. char *bp = b;
  14. // scale and round
  15. int32_t i = lrint(d * 10000.);
  16. // write sign and fix i sign
  17. // (we do have at least one character available in buf)
  18. if(signbit(d)) {
  19. *buf++='-';
  20. i = -i;
  21. } else {
  22. *buf++='+';
  23. }
  24. // *always* write down the last 4 digits, even if they are zeroes
  25. // (they'll become the 4 digits after the decimal dot)
  26. for(; bp!=b+4; ) {
  27. *bp++ = '0' + i%10;
  28. i/=10;
  29. }
  30. *bp++='.';
  31. // write down the remaining digits, writing at least one
  32. do {
  33. *bp++ = '0' + i%10;
  34. i/=10;
  35. } while(i != 0);
  36. // bp is at the character after the last, step back
  37. --bp;
  38. // data is now into b *in reversed order*;
  39. // reverse-copy it into the user-provided buffer
  40. while(buf!=lim) {
  41. *buf++ = *bp;
  42. // check before decrementing, as a pointer to one-before-first
  43. // is not allowed in C
  44. if(bp == b) break;
  45. --bp;
  46. }
  47. if(buf!=lim) *buf=0; // "regular" case: terminate *after*
  48. else lim[-1]=0; // bad case: truncate
  49. return buf;
  50. }
  51.  
  52. void doformat(char *buf, char *lim, double a, double b) {
  53. if(buf==lim) return; // cannot do anything
  54. *buf++='{';
  55. if(buf==lim) goto end;
  56. buf = fmtp04f(buf, lim, a);
  57. if(buf==lim) return; // already terminated by fmtp04f
  58. *buf++=',';
  59. if(buf==lim) goto end;
  60. buf = fmtp04f(buf, lim, b);
  61. if(buf==lim) return; // idem
  62. *buf++='}';
  63. if(buf==lim) goto end;
  64. *buf++=0;
  65. end:
  66. lim[-1]=0; // always terminate
  67. }
  68.  
  69. int main() {
  70. double test_cases[] = {0., 1., 100., 1.2345678, 12345.678, 3.1415, 9.115251, 99999.1234, 0.};
  71. char buf1[22];
  72. char buf2[256];
  73. char *buf2r = buf2+128;
  74. for(int i=0, n=(sizeof(test_cases)/sizeof(*test_cases))-1; i<n; ++i) {
  75. for(int sgn = 0; sgn<4; ++sgn) {
  76. memset(buf2, 255, sizeof(buf2));
  77. double a = test_cases[i];
  78. if(sgn&1) a = -a;
  79. double b = test_cases[i+1];
  80. if(sgn&2) b = -b;
  81. snprintf(buf1, sizeof(buf1), "{%+0.4f,%+0.4f}", a, b);
  82. puts(buf1);
  83. doformat(buf2r, buf2r+22, a, b);
  84. puts(buf2r);
  85. if(strcmp(buf2r, buf1)) {
  86. printf("buf1 [%s] != buf2r [%s]\n", buf1, buf2r);
  87. }
  88. for(const char *p=buf2; p<buf2r; ++p) {
  89. if((unsigned char)(*p)!=255) {
  90. printf("unexpected %d at %d\n", *p, (int)(p-buf2));
  91. }
  92. }
  93. for(const char *p=buf2r+22; p<buf2 + sizeof(buf2); ++p) {
  94. if((unsigned char)(*p)!=255) {
  95. printf("unexpected %d at %d\n", *p, (int)(p-buf2));
  96. }
  97. }
  98. }
  99. }
  100. return 0;
  101.  
  102. }
  103.  
Success #stdin #stdout 0s 9432KB
stdin
Standard input is empty
stdout
{+0.0000,+1.0000}
{+0.0000,+1.0000}
{-0.0000,+1.0000}
{-0.0000,+1.0000}
{+0.0000,-1.0000}
{+0.0000,-1.0000}
{-0.0000,-1.0000}
{-0.0000,-1.0000}
{+1.0000,+100.0000}
{+1.0000,+100.0000}
{-1.0000,+100.0000}
{-1.0000,+100.0000}
{+1.0000,-100.0000}
{+1.0000,-100.0000}
{-1.0000,-100.0000}
{-1.0000,-100.0000}
{+100.0000,+1.2346}
{+100.0000,+1.2346}
{-100.0000,+1.2346}
{-100.0000,+1.2346}
{+100.0000,-1.2346}
{+100.0000,-1.2346}
{-100.0000,-1.2346}
{-100.0000,-1.2346}
{+1.2346,+12345.6780}
{+1.2346,+12345.6780}
{-1.2346,+12345.6780}
{-1.2346,+12345.6780}
{+1.2346,-12345.6780}
{+1.2346,-12345.6780}
{-1.2346,-12345.6780}
{-1.2346,-12345.6780}
{+12345.6780,+3.1415}
{+12345.6780,+3.1415}
{-12345.6780,+3.1415}
{-12345.6780,+3.1415}
{+12345.6780,-3.1415}
{+12345.6780,-3.1415}
{-12345.6780,-3.1415}
{-12345.6780,-3.1415}
{+3.1415,+9.1153}
{+3.1415,+9.1153}
{-3.1415,+9.1153}
{-3.1415,+9.1153}
{+3.1415,-9.1153}
{+3.1415,-9.1153}
{-3.1415,-9.1153}
{-3.1415,-9.1153}
{+9.1153,+99999.1234}
{+9.1153,+99999.1234}
{-9.1153,+99999.1234}
{-9.1153,+99999.1234}
{+9.1153,-99999.1234}
{+9.1153,-99999.1234}
{-9.1153,-99999.1234}
{-9.1153,-99999.1234}
{+99999.1234,+0.0000}
{+99999.1234,+0.0000}
{-99999.1234,+0.0000}
{-99999.1234,+0.0000}
{+99999.1234,-0.0000}
{+99999.1234,-0.0000}
{-99999.1234,-0.0000}
{-99999.1234,-0.0000}