Linux.org.ua

Технічні питання => Розробка => Гілку створено: Сергій Лисовенко від 2008-06-20 01:00:31

Тема: Кляті бібліотеки! не можу більше
Автор: Сергій Лисовенко від 2008-06-20 01:00:31
Проблема наступна: треба завантажити конкретну функцію з конкретної бібліотеки при чому перекриваюча функція завантажена і нахабно заважає працювати ;)
Справа в тому, що хочу використати strtod з stdlibc а завантажена glibc, її функція реагує на локаль, що мені аж ніяк не потрібно. Треба розглянути поля з бази даних (грубо кажучи, іншими словами треба працювати з файлом, вмісту якого має бути начхати на локаль - мається на увазі xml файл з данними) .
Або підкажіть яку функцію, яка не належить glibc і переводить в числа з плаваючою точкою строки, які складаються з цифр і крапки, а не коми з китайськими ієрогліфами ;)
Ну не писати ж мені функцію замінника, коли вже існує одна.
Тема: Re: Кляті бібліотеки! не можу більше
Автор: DalekiyObriy від 2008-06-20 01:45:00
а може простіше

setlocale( LC_NUMERIC, ... )
...
strtod(...)

?
Тема: Re: Кляті бібліотеки! не можу більше
Автор: fk4mam від 2008-06-20 10:54:20
Off-topic:
До адміна: приберіть, будьласка, прив'язку esc до "скинути" або нехай хоч перепитує перед скиданням - воістину занадто нерозумна функція для клавіші, яку можна натискати ненароком.
Ескейпав вибрик миші, а воно мені все набране до дідька послало.
Питання ж в обходженні налаштувань локалі. Тобто щоб один і той же набір даних міг використовуватись хоч і китайцями чи арабами з їх ієрогліфами, а не в переналаштовуванні її якось смішно переналаштовувати локаль для однієї функції (а якщо треба, щоб вивід на термінал йшов в локалі користувача - совати локаль туди-сюди?). Вже краще вигрепати потрібну функцію з stdlibc і перейменувавши вставити в код (в цьому перевага опенсорса).
В когось є красиве рішення цієї проблеми?
Тема: Re: Кляті бібліотеки! не можу більше
Автор: raven від 2008-06-20 11:16:39
В когось є красиве рішення цієї проблеми?
Чим запропоноване DalekiyObriy некрасиве? Аргумент "смішно" смішний.
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Praporshic від 2008-06-20 11:33:23
Off-topic:
китайцями чи арабами з їх ієрогліфами
А з яких це пір у арабській писемності використовуються ієрогліфи?
Тема: Re: Кляті бібліотеки! не можу більше
Автор: xbvjm3 від 2008-06-20 12:27:52
Чим запропоноване DalekiyObriy некрасиве? Аргумент "смішно" смішний.
Бо переналаштування локалі для того, щоб попарсити число з плаваючою точкою - постріл з танка пого горобцю: результат має не завжди естетичний вигляд.
Тема: Re: Кляті бібліотеки! не можу більше
Автор: raven від 2008-06-20 12:48:07
Чим запропоноване 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
Для вас це забагато?
Тема: Re: Кляті бібліотеки! не можу більше
Автор: cx8vdv від 2008-06-20 13:07:23
Геніальна простота: залишилось впарити цей код арабу з китайською розкладкою або тому ж москалеві чи молдовану  ;D
Тема: Re: Кляті бібліотеки! не можу більше
Автор: mim від 2008-06-20 13:37:01
Raven, для чистоти експерименту треба робити так:
$gcc ttlc.c -o ttlc -O0
$ time ./ttlc
4.48user 0.00system 0:04.49elapsed 99%CPU
Тема: Re: Кляті бібліотеки! не можу більше
Автор: cij7sq від 2008-06-20 13:38:20
А ще краще побити програму на потоки щоб вони конфліктували локалями  ;D
Тема: Re: Кляті бібліотеки! не можу більше
Автор: raven від 2008-06-20 13:55:19
Raven, для чистоти експерименту треба робити так:
$gcc ttlc.c -o ttlc -O0
$ time ./ttlc
4.48user 0.00system 0:04.49elapsed 99%CPU
Ну... тоді вже краще просто -funroll-loops, щоб прибрати час на преінкремент.

У всякому разі, будь-який рівень оптимізації дає однаковий порядок. Так що це вже інша тема для обговорення=)
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Soft від 2008-06-20 14:29:20
#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;
}

а так можна?
Тема: Re: Кляті бібліотеки! не можу більше
Автор: raven від 2008-06-20 14:53:15
     char* locale,buf[20];
                  locale=getlocale(LC_NUMERIC);
                  strcpy(buf,locale);
Ну, якщо хочеться замірити з часом на виконання getlocale і strcpy, то можна. Але навіщо?
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Володимир Лісівка від 2008-06-20 15:11:41
#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);
}

Прикол в тому, що в мене strtod взагалі не працює.  :o

#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
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Soft від 2008-06-20 15:12:10
З розрахунку на китайців з арабами
Тема: Re: Кляті бібліотеки! не можу більше
Автор: raven від 2008-06-20 15:19:52
Прикол в тому, що в мене strtod взагалі не працює.  :o
Гм, і то правда...

Насправді, я все життя використовував sprintf. Чого можу побажати і топікстартеру=)
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Сергій Лисовенко від 2008-06-20 15:57:14
Насправді, я все життя використовував sprintf. Чого можу побажати і топікстартеру=)
А можна приклад коду з використанням sprintf для перетворення строки в раціональне число?
 ;D ;D ;D
Тема: Re: Кляті бібліотеки! не можу більше
Автор: raven від 2008-06-20 17:10:27
А можна приклад коду з використанням sprintf для перетворення строки в раціональне число?
Пардон, помилився напрямком.

Btw, atof?
Тема: Re: Кляті бібліотеки! не можу більше
Автор: DalekiyObriy від 2008-06-20 17:19:47
#include <stdio.h>

...
$ ./test
1.200000
1072902963.000000
1072693248.000000

1) компілювати треба з -Wall, а краще з -pedantic
2) включати треба всі файли заголовків:

#include <stdlib.h>

тоді все гаразд:
1.200000
1.200000
1.000000

P.S. мушу зазначити, що С без -Wall та -pedantic взагалі СТРАШНА МОВА!! :))
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Сергій Лисовенко від 2008-06-20 20:57:07
.2 - it's a float with value -1,71799e+09
дійсно отткровення
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Володимир Лісівка від 2008-06-21 16:59:16
Дякую за підказку з -Wall -pedantic (мав би й сам здогадатися  :-[ ). Виправлений варіант:
#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
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Сергій Лисовенко від 2008-06-22 18:26:11
Так і бути розкрию повністю
#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;
}
Воно працює. Принаймні в мене :)
Тут зашито 2 варіанти парсера - один з них XML


P.S.
щоб не дивувались чого я код не розкриваю: я його путньо писати не вмію  ;D
(камінчик в бік майкрософта)
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Володимир Лісівка від 2008-06-23 15:32:20
Ну так поміняй всі strtod на strtod_l(..., ..., c_locale), і замість setlocale(LC_NUMERIC,"C"); постав c_locale = newlocale(LC_ALL_MASK, "C", NULL);

Тема: Re: Кляті бібліотеки! не можу більше
Автор: Володимир Лісівка від 2008-06-23 15:43:17
І не забудь перед першим #include написати
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

 або компілюй з -D_GNU_SOURCE . Мій варіант з #define __USE_GNU - не зовсім коректний, так як це внутрішня макрозмінна glibc.
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Сергій Лисовенко від 2008-06-23 19:00:50
А як тоді що до фсіляких fprintf , fscanf?
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Володимир Лісівка від 2008-06-24 14:51:00
Наскільки я бачу, стандартних методів нема. Можна використовувати g_ascii_formatd з glib. Треба напевно накопати Дрепера, щоб додали _l версії для функцій *printf/*scanf, як це зроблено в BSD.
Тема: Повернути чудодійність sizeof
Автор: Сергій Лисовенко від 2008-07-02 16:31:28
Та сам розробка, але інша тема: під час розвитку проекту (якщо так можна назвати моє кодіння, в результаті якого виникають текстові файли для галереї) в деяких структурах позмінював типи членів (були пойнтери на одні структури - стали на інші). На одній машині наче нормально працювала, а на іншій - гуп... аж скалки скла полетіли ;)
Беру бубна, танцюю... Нічого - гупається і гупається, навіть gdb дає надто прозорі натяки (зазвичай, він при гупі вказує стрічку, а тут і цього не захотів, не дивлячись, що програма зібрана з відлагоджувальним кодом). Почаклував вставлянням відлагоджувальних стрічок типу fprintf(stderr,...); аж раптом надибав, що при виділенні пам'яті зазначена sizeof старої структури...
От мене і цікавить як проти таких граблів боротись. Чи можна якось примусити sizeof говорити розмір типу, пойнтером на який є елемент структури, явно цей тип не задаючи?
Тема: Re: Кляті бібліотеки! не можу більше
Автор: Михайло Даниленко від 2008-07-02 16:53:35
ви маєте на увазі
struct aa {
        struct bb * c;
} a;
sizeof(*(a.c))

? тоді працює.
а якщо
struct aa {
        void *c;
} a;
a.c = &b;
sizeof (*(a.c))

тоді не працює.
Тема: Re: Повернути чудодійність sizeof
Автор: raven від 2008-07-02 16:57:14
(...) ... (...). ;) (...) fprintf(stderr,...);
Сергій, та забий ти на цей Сі, в тебе явна тяга до ліспа=)

Чи можна якось примусити sizeof говорити розмір типу, пойнтером на який є елемент структури, явно цей тип не задаючи?
Точніше. В мене асоціації з вінегретом із typedef-ів і #define-ів.