В когось є красиве рішення цієї проблеми?Чим запропоноване DalekiyObriy некрасиве? Аргумент "смішно" смішний.
китайцями чи арабами з їх ієрогліфамиА з яких це пір у арабській писемності використовуються ієрогліфи?
Чим запропоноване DalekiyObriy некрасиве? Аргумент "смішно" смішний.Бо переналаштування локалі для того, щоб попарсити число з плаваючою точкою - постріл з танка пого горобцю: результат має не завжди естетичний вигляд.
Гм. А поставити назад на системну релігія не дозволяє? Якщо це вас так турбує перформанс:Чим запропоноване DalekiyObriy некрасиве? Аргумент "смішно" смішний.Бо переналаштування локалі для того, щоб попарсити число з плаваючою точкою - постріл з танка пого горобцю: результат має не завжди естетичний вигляд.
#include <locale.h>
int main(void)
{
int i;
for (i=0; i < 1e6; ++i)
{
setlocale(LC_NUMERIC, "C");
setlocale(LC_NUMERIC, "UK_UA.utf8");
}
return 0;
}
$ gcc test.c -o test
$ time ./test
./test 1,35s user 0,03s system 99% cpu 1,385 total
Для вас це забагато?
$gcc ttlc.c -o ttlc -O0
$ time ./ttlc
4.48user 0.00system 0:04.49elapsed 99%CPU
Raven, для чистоти експерименту треба робити так:Ну... тоді вже краще просто -funroll-loops, щоб прибрати час на преінкремент.Код: [Вибрати]$gcc ttlc.c -o ttlc -O0
$ time ./ttlc
4.48user 0.00system 0:04.49elapsed 99%CPU
#include <locale.h>
int main(void)
{
int i;
for (i=0; i < 1e6; ++i)
{
char* locale,buf[20];
locale=getlocale(LC_NUMERIC);
strcpy(buf,locale);
setlocale(LC_NUMERIC, "C");
setlocale(LC_NUMERIC, buf);
}
return 0;
}
а так можна?
Ну, якщо хочеться замірити з часом на виконання getlocale і strcpy, то можна. Але навіщо?Код: [Вибрати]char* locale,buf[20];
locale=getlocale(LC_NUMERIC);
strcpy(buf,locale);
#include <stdio.h>
#define __USE_GNU 1
#include <locale.h>
char *def = "12.3456";
int
main (int argc, char **argv)
{
char *s;
char *endp;
double d=0.0;
locale_t c_locale;
// Set default locale
setlocale (LC_ALL, "");
if ( argc > 1)
s=argv[1];
else
s=def;
endp=s;
printf("String: %s\n", s);
// Create "C" locale
c_locale = newlocale(LC_ALL_MASK, "C", NULL);
if (c_locale == NULL)
{
puts("Cannot get C locale.\n");
return 1;
}
// Convert string to double using "C" locale
d = strtod_l (s, &endp, c_locale);
if (s != endp && *endp == '\0')
printf("%s - it's a float with value %.2lf\n", s, d);
else
{
printf("%s - it's not a number.", s);
}
// Free unused locale
freelocale(c_locale);
}
#include <stdio.h>
int
main (int argc, char **argv)
{
char *endp;
double d;
d=1.2;
printf("%f\n", d);
d=strtod ("1.2", NULL);
printf("%f\n", d);
d=strtod ("1,2", NULL);
printf("%f\n", d);
}
$ ./test
1.200000
1072902963.000000
1072693248.000000
Прикол в тому, що в мене strtod взагалі не працює. :oГм, і то правда...
Насправді, я все життя використовував sprintf. Чого можу побажати і топікстартеру=)А можна приклад коду з використанням sprintf для перетворення строки в раціональне число?
А можна приклад коду з використанням sprintf для перетворення строки в раціональне число?Пардон, помилився напрямком.
Код: [Вибрати]#include <stdio.h>
...
$ ./test
1.200000
1072902963.000000
1072693248.000000
#include <stdio.h>
#define __USE_GNU 1
#include <stdlib.h>
#include <locale.h>
char *def = "12.3456";
int
main (int argc, char **argv)
{
char *s;
char *endp;
double d=0.0;
locale_t c_locale;
// Set default locale
setlocale (LC_ALL, "");
if ( argc > 1)
s=argv[1];
else
s=def;
endp=s;
printf("String: %s\n", s);
// Create "C" locale
c_locale = newlocale(LC_ALL_MASK, "C", NULL);
if (c_locale == NULL)
{
puts("Cannot get C locale.\n");
return 1;
}
// Convert string to double using "C" locale
d = strtod_l (s, &endp, c_locale);
if (s != endp && *endp == '\0')
printf("%s - it's a float with value %f\n", s, d);
else
{
printf("%s - it's not a number.", s);
}
// Free unused locale
freelocale(c_locale);
return 0;
}
$ ./test-strtod
String: 12.3456
12.3456 - it's a float with value 12,345600
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <locale.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include "prj.h"
int numword (char *str)
{
char *keys = "sphere\0intersphcyl\0";
int sl, siz, i = 0;
siz = 0;
do
{
if (!strcmp (keys + siz, str))
return i;
sl = strlen (keys + siz);
siz += sl + 1;
i++;
} while (sl);
return -1;
}
int getword (char *from, char *to)
{
int i, dsp;
for (dsp = 0; isspace (from[dsp]); dsp++);
for (i = dsp; !isspace (from[i]); i++)
to[i - dsp] = from[i];
to[i - dsp] = 0;
return i;
}
CYLINDER interspher_cyl (SPHERE * sph1, SPHERE * sph2, double r)
{
double r1, r2, l;
vector nap;
CYLINDER res;
r1 = sqrt (sph1->r * sph1->r - r * r);
r2 = sqrt (sph2->r * sph2->r - r * r);
nap = VecIneq (sph1->o, sph2->o);
l = sqrt (VecAbs2 (nap));
res.r = r;
res.n = ProdScal (1. / l, nap);
res.o = VecIneq (sph1->o, ProdScal (r1, res.n));
res.l = l - r1 - r2;
// ADDING holes to spheres
sph2->holes = realloc (sph2->holes, (sph2->nh + 1) * sizeof (HOLE));
sph2->holes[sph2->nh].n = res.n;
sph2->holes[sph2->nh].o = VecSum (sph2->o, ProdScal (r2, res.n));
sph2->holes[sph2->nh].r = r;
sph2->holes[sph2->nh].figure = 1;
sph2->nh++;
sph1->holes = realloc (sph1->holes, (sph1->nh + 1) * sizeof (HOLE));
sph1->holes[sph1->nh].n = ProdScal (-1., res.n);
sph1->holes[sph1->nh].o = res.o; // VecSum(sph1->o,ProdScal(-r1
// ,res.n));
sph1->holes[sph1->nh].r = r;
sph1->holes[sph1->nh].figure = 1;
sph1->nh++;
res.figure1 = 1;
res.figure0 = 1;
return res;
}
KUPA3D interpret_3dvl (FILE * fp)
{
KUPA3D res;
char buff[100];
memset (&res, 0, sizeof (KUPA3D));
res.cyls = 0;
res.sphers = 0;
res.ncyls = 0;
res.nsphers = 0;
while (fgets (buff, 100, fp))
{
char word[15];
int pos;
pos = getword (buff, word);
switch (numword (word))
{
double r, x, y, z;
int n1, n2;
case 0:
sscanf (buff + pos, "%lf %lf %lf %lf", &x, &y, &z, &r);
res.sphers = realloc (res.sphers, sizeof (SPHERE) * (res.nsphers + 1));
res.sphers[res.nsphers].r = r;
res.sphers[res.nsphers].o.x = x;
res.sphers[res.nsphers].o.y = y;
res.sphers[res.nsphers].o.z = z;
res.sphers[res.nsphers].holes = NULL;
res.sphers[res.nsphers].nh = 0;
res.nsphers++;
break;
case 1:
sscanf (buff + pos, "%d %d %lf", &n1, &n2, &r);
if (n1 >= res.nsphers || n2 >= res.nsphers)
{
fprintf (stderr, "Spheres Overflow\n");
break;
}
res.cyls = realloc (res.cyls, sizeof (CYLINDER) * (res.ncyls + 1));
res.cyls[res.ncyls] =
interspher_cyl (res.sphers + n1, res.sphers + n2, r);
res.ncyls++;
break;
}
}
return res;
}
typedef struct {
int n1, n2;
double r;
} INTERSPHERCYL;
INTERSPHERCYL parse_intersphcyl (xmlDocPtr doc, xmlNodePtr cur)
{
INTERSPHERCYL res;
xmlChar *key;
int neibours = 0;
cur = cur->xmlChildrenNode;
while (cur != NULL)
{
if ((!xmlStrcmp (cur->name, (const xmlChar *) "radius")))
{
key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
res.r = atof (key);
// printf("keyword: %s\n", key);
xmlFree (key);
}
if ((!xmlStrcmp (cur->name, (const xmlChar *) "neibour")))
{
key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
if (neibours == 0)
{
res.n1 = atoi (key);
neibours++;
}
else
res.n2 = atoi (key);
// printf("keyword: %s\n", key);
xmlFree (key);
}
if ((!xmlStrcmp (cur->name, (const xmlChar *) "neibours")))
{
char *endptr, *sptr;
long int val;
key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
sptr = key;
val = strtol (sptr, &endptr,10);
if (sptr != endptr && *sptr != 0)
{
res.n1 = val;
sptr = endptr;
}
else
fprintf (stderr, "error reading neibours numbers\n");
val = strtol (sptr, &endptr,10);
if (sptr != endptr && *sptr != 0)
{
res.n2 = val;
// sptr = endptr;
}
else
fprintf (stderr, "error reading neibours numbers\n");
// printf("keyword: %s\n", key);
xmlFree (key);
}
cur = cur->next;
}
return res;
}
SPHERE parse_sphere (xmlDocPtr doc, xmlNodePtr cur)
{
xmlChar *key;
cur = cur->xmlChildrenNode;
SPHERE res;
while (cur != NULL)
{
if ((!xmlStrcmp (cur->name, (const xmlChar *) "center")))
{
char *endptr, *sptr;
double val;
// fprintf(stderr,"pos 1\n");fprintf(stderr,"pos 2\n");
key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
// printf("keyword: %s\n", key);
sptr = key;
val = strtod (sptr, &endptr);
if (sptr != endptr && *sptr != 0)
{
res.o.x = val;
sptr = endptr;
}
else
fprintf (stderr, "error reading atom coordinates\n");
val = strtod (sptr, &endptr);
if (sptr != endptr && *sptr != 0)
{
res.o.y = val;
sptr = endptr;
}
else
fprintf (stderr, "error reading atom coordinates\n");
val = strtod (sptr, &endptr);
if (sptr != endptr && *sptr != 0)
{
res.o.z = val;
sptr = endptr;
}
else
fprintf (stderr, "error reading atom coordinates\n");
// res.r=atof(key);
xmlFree (key);
}
if ((!xmlStrcmp (cur->name, (const xmlChar *) "radius")))
{
key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
// printf("keyword: %s\n", key);
res.r = atof (key);
xmlFree (key);
}
cur = cur->next;
}
res.holes = NULL;
res.nh = 0;
return res;
}
KUPA3D interpret_3d_xml (char *docname)
{
xmlDocPtr doc;
xmlNodePtr cur;
KUPA3D res;
setlocale(LC_NUMERIC,"C");
doc = xmlParseFile (docname);
memset (&res, 0, sizeof (KUPA3D));
if (doc == NULL)
{
fprintf (stderr, "Document not parsed successfully. \n");
return res;
}
cur = xmlDocGetRootElement (doc);
if (cur == NULL)
{
fprintf (stderr, "empty document\n");
xmlFreeDoc (doc);
return res;
}
// printf ("rootname is %s\n", cur->name);
if (xmlStrcmp (cur->name, (const xmlChar *) "box"))
{
fprintf (stderr, "document of the wrong type, root node != box");
xmlFreeDoc (doc);
return res;
}
cur = cur->xmlChildrenNode;
// printf ("current name xmlChildrenNode: %s\n", (cur != NULL) ? cur->name : 0);
while (cur != NULL)
{
if ((!xmlStrcmp (cur->name, (const xmlChar *) "sphere")))
{
SPHERE sph = parse_sphere (doc, cur);
res.sphers = realloc (res.sphers, sizeof (SPHERE) * (res.nsphers + 1));
res.sphers[res.nsphers] = sph;
res.nsphers++;
///// printf ("x=%g,y=%g,z=%g,r=%g\n", sph.o.x, sph.o.y, sph.o.z, sph.r); // //
}
if ((!xmlStrcmp (cur->name, (const xmlChar *) "intersphcyl")))
{
INTERSPHERCYL isph = parse_intersphcyl (doc, cur);
if (isph.n1 >= res.nsphers || isph.n2 >= res.nsphers)
{
fprintf (stderr, "Spheres Overflow\n");
continue;
}
res.cyls = realloc (res.cyls, sizeof (CYLINDER) * (res.ncyls + 1));
res.cyls[res.ncyls] =
interspher_cyl (res.sphers + isph.n1, res.sphers + isph.n2, isph.r);
res.ncyls++;
//// printf ("n1=%d,n2=%d, r=%g\n", isph.n1, isph.n2, isph.r); // //
}
cur = cur->next; // printf("current name cur->next: %s\n",(cur
// != NULL)?cur->name:0);
}
xmlFreeDoc (doc);
setlocale(LC_NUMERIC,"");
return res;
}
Воно працює. Принаймні в мене :)#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
(...) ... (...). ;) (...) fprintf(stderr,...);Сергій, та забий ти на цей Сі, в тебе явна тяга до ліспа=)
Чи можна якось примусити sizeof говорити розмір типу, пойнтером на який є елемент структури, явно цей тип не задаючи?Точніше. В мене асоціації з вінегретом із typedef-ів і #define-ів.