PLN amount in words (kwota słownie)  1.6
plntowords.c
Go to the documentation of this file.
1 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <math.h>
31 #include "plntowords.h"
32 /*----------------------------------------------------------------------------*/
33 static const char
34 *hundreds[] = {
35  "", "sto ", "dwieście ", "trzysta ", "czterysta ", "pięćset ",
36  "sześćset ", "siedemset ", "osiemset ", "dziewięćset "};
37 static const char
38 *teens[] = {
39  "dziesięć ", "jedenaście ", "dwanaście ", "trzynaście ",
40  "czternaście ", "piętnaście ", "szesnaście ", "siedemnaście ",
41  "osiemnaście ", "dziewiętnaście "};
42 static const char
43 *tens[] = {
44  "", "", "dwadzieścia ", "trzydzieści ", "czterdzieści ",
45  "pięćdziesiąt ", "sześćdziesiąt ", "siedemdziesiąt ",
46  "osiemdziesiąt ", "dziewięćdziesiąt "};
47 static const char
48 *ones[] = {
49  "", "jeden ", "dwa ", "trzy ", "cztery ", "pięć ",
50  "sześć ", "siedem ", "osiem ", "dziewięć "};
51 static const char
52 *ends[11][3] = {
53  {"złoty ", "złote ", "złotych "},
54  {"tysiąc ", "tysiące ", "tysięcy "},
55  {"milion ", "miliony ", "milionów "},
56  {"miliard ", "miliardy ", "miliardów "},
57  {"bilion ", "biliony ", "bilionów "},
58  {"biliard", "biliardy", "biliardów"},
59  {"trylion", "tryliony", "trylionów"},
60  {"tryliard", "tryliardy", "tryliardów"},
61  {"kwadrylion", "kwadryliony", "kwadrylionów"},
62  {"kwintylion", "kwintyliony", "kwintylionów"},
63  {"sekstylion", "sekstyliony", "sekstylionów"}};
64 /*----------------------------------------------------------------------------*/
99 /*----------------------------------------------------------------------------*/
100 static uint64_t power (uint64_t x,
101  int n) __attribute__ ((const));
102 
103 static uint8_t get_digit (uint64_t x,
104  uint8_t pos) __attribute__ ((const));
105 
106 static void divide_split (uint64_t *x,
107  uint8_t *y);
108 
109 static void check_resize (char **buff,
110  const size_t ui_len);
111 
112 static int prestr (uint8_t n,
113  ...);
114 /*----------------------------------------------------------------------------*/
118 static uint64_t
119 power (uint64_t x,
120  int n)
121 {
122  if (n == 0)
123  return 1;
124  else
125  return x * power (x, n - 1);
126 }
127 /*----------------------------------------------------------------------------*/
131 static uint8_t
132 get_digit (uint64_t x,
133  uint8_t pos)
134 {
135  return (uint8_t) ((x - x / power (10, pos + 1) * power (10, pos + 1)) /
136  power (10, pos));
137 }
138 /*----------------------------------------------------------------------------*/
142 static void
143 divide_split (uint64_t *x,
144  uint8_t *y)
145 {
146  y[2] = get_digit (*x, 0);
147  y[1] = get_digit (*x, 1);
148  y[0] = get_digit (*x, 2);
149  *x /= 1000;
150 }
151 /*----------------------------------------------------------------------------*/
156 static void
157 check_resize (char **buff,
158  const size_t ui_len)
159 {
160  if (*buff == NULL) {
161  *buff = malloc (ui_len * sizeof (char));
162  }
163  else {
164  *buff = realloc (*buff, ui_len * sizeof (char));
165  }
166  if (*buff == NULL) {
167  puts ("Error (re)allocating memory");
168  exit (1);
169  }
170 }
171 /*----------------------------------------------------------------------------*/
175 static int
176 prestr (uint8_t n, ...)
177 {
178  char **dst = NULL; /* Pointer to destination string */
179  char *src = NULL; /* Source strings to prepend */
180  uint8_t i = 0; /* i */
181  size_t ui_srl = 0; /* Length of source string */
182  size_t ui_dsl = 0; /* Length of destination string */
183  va_list vl; /* Information about variable arguments */
184 
185  va_start (vl, n);
186  dst = va_arg (vl, char**);
187  for (i = 1; i < n; ++i) {
188  src = va_arg (vl, char*);
189  ui_srl = strlen (src);
190  ui_dsl = strlen (*dst);
191  check_resize (dst, ui_srl + ui_dsl + 1);
192  memmove ((*dst) + ui_srl, *dst, ui_dsl + 1);
193  memmove (*dst, src, ui_srl);
194  }
195  return 0;
196 }
197 /*----------------------------------------------------------------------------*/
202 char *
203 pln_amount_txt_double (double d_price)
204 {
205  double d_val = 0;
206 
207  d_val = d_price * 100.0;
208  d_val = round (d_val);
209 
210  return pln_amount_txt ((uint64_t) d_val );
211 }
212 /*----------------------------------------------------------------------------*/
217 char *
218 pln_amount_txt (uint64_t ui_inprice)
219 {
220  char *s_price = NULL; /* Result string with price */
221  uint64_t ui_price = 0; /* Price without "gr" after comma */
222  uint64_t ui_gr = 0; /* After comma "gr" rest */
223  uint64_t ui_prtmp = 0; /* Temp price to count length */
224  uint8_t ui_prlen = 0; /* Length of price in 3 char portions */
225  uint8_t p [3] = {0, 0, 0}; /* 3 chars of a price portion */
226  uint8_t i = 0; /* i */
227 
228  ui_price = ui_inprice / 100;
229  ui_prtmp = ui_price;
230  ui_gr = ui_inprice - (ui_inprice / 100 * 100);
231 
232  while (ui_prtmp || ui_prlen % 3) {
233  ++ui_prlen;
234  ui_prtmp /= 10;
235  }
236  check_resize (&s_price, 10);
237  sprintf (s_price, "%" PRIu64 "/100", ui_gr);
238  for (i = 0; i < ui_prlen / 3; ++i) {
239  divide_split (&ui_price, p);
240  if (p[1] == 1) prestr (3, &s_price, ends[i][2], teens[p[2]]);
241  else {
242  if (p[2] == 0) {
243  if (i == 0) {
244  prestr (2, &s_price, ends[i][2]);
245  if (p[0] == 0 && p[1] == 0 && ui_prlen == 3)
246  prestr (2, &s_price, "zero ");
247  }
248  else if (! (p[0] == 0 && p[1] == 0 && ui_prlen > ((i + 1) * 3)))
249  prestr (2, &s_price, ends[i][2]);
250  }
251  else if (p[2] == 1) {
252  if (p[0] == 0 && p[1] == 0)
253  prestr (3, &s_price, ends[i][0], ones[p[2]]);
254  else prestr (3, &s_price, ends[i][2], ones[p[2]]);
255  }
256  else if (p[2] > 1 && p[2] < 5)
257  prestr (3, &s_price, ends[i][1], ones[p[2]]);
258  else prestr (3, &s_price, ends[i][2], ones[p[2]]);
259  prestr (2, &s_price, tens[p[1]]);
260  }
261  prestr (2, &s_price, hundreds[p[0]]);
262  }
263  return s_price;
264 }
265 /*----------------------------------------------------------------------------*/
266 
plntowords.h
PLN numerical amount in words.
pln_amount_txt
char * pln_amount_txt(uint64_t ui_inprice)
Function converts price (in PLN) given as an integer number to a word version.
Definition: plntowords.c:218
pln_amount_txt_double
char * pln_amount_txt_double(double d_price)
Function converts price (in PLN) given as a floating point number to a word version.
Definition: plntowords.c:203