Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: akif в Feb 28, 2005, 00:00



Титла: C API за MYSQL
Публикувано от: akif в Feb 28, 2005, 00:00
Здравейте приятели!
Пиша "Склад" на MYSQL като  използвам "С" за писане на клиента.
Заявката с която имам проблем има следния вид:
sprintf(query, "isert ito my_table values(%d, %d, %d, %f, %f)",
                cl_id, st_id, doc_id,  cena, colicestvo);
printf("%s\n", query);
Низа който се получава има следния вид:
 insert into my_table values(1, 2, 3,  20,33,  11,4)
Проблема е във последните 2 стойности които са от
тип  double.
MYSQL  иска стойностит да имат вида 22.(точка)33, а
в моя случай аз плучавам от потребителя тази променлива във вид на низ и като я преобразувам чрез  cena = atof(my_cena); , променливата cena=22,(запетая)33.
Всъщност трябва да заменя символа ',' във '.' във заявката, но
 във случая това не низ, а променлива от тип double.
Ако някой ми даде идея как да реша този проблем ще
съм му много благодарен :)


Титла: C API за MYSQL
Публикувано от: в Feb 28, 2005, 00:54
replace() в повечето езици я има тая функция. Не съм сигурен обаче за С :) Иначе прави точно това - заменя синвол/и с друг/и

П.П. погледни тук http://bg2.php.net/manual/en/function.str-replace.php за да видим дали правилно се насочвам какво ти трбва - знам че това е за ПХП а не за С :)


Титла: C API за MYSQL
Публикувано от: в Feb 28, 2005, 01:04
MySQL не може да иска да са в формата еди-кво-си. Може да иска да е определен тип променливата. Виж точно какъв тип приема функцията(в .h където е декларирана функцията, която ползваш). Като видиш какъв е типа, просто използвай type-casting и си готов. Примерно ако иска да е тип float, правиш така:
Примерен код

blablabla(float(name_of_double_var), float(bla_bla_var))

или ако ти е удобно си ги cast-ни предварително.


Титла: C API за MYSQL
Публикувано от: в Feb 28, 2005, 20:43
Цитат (Guest @ Фев. 28 2005,02:04)
MySQL не може да иска да са в формата еди-кво-си. Може да иска да е определен тип променливата. Виж точно какъв тип приема функцията(в .h където е декларирана функцията, която ползваш). Като видиш какъв е типа, просто използвай type-casting и си готов. Примерно ако иска да е тип float, правиш така:
Примерен код

blablabla(float(name_of_double_var), float(bla_bla_var))

или ако ти е удобно си ги cast-ни предварително.

Това нещо -
insert into my_table values(1, 2, 3, double(33,32);
не работи.
Не съм сигурен че сте разбрали въпроса ми.
Имам низ  char str = "33,32";
double my_double =(double) atof(str);

insert into my_table values( double(my_double) );
Проблема е че my_double=33,32
Обърнете внимание на ЗАПЕТАЯТА.
Запетаята е разделител м/у отделните стойности
които са записани във заявката, а в моя случай ЗАПЕТАЯТА при my_double разделя цялата част от дробната.
ERROR 1064  blablabal Check the manual that corresponds to your MySQL server version for the right syntax to use near 'double(33,32)'
Надявам се че съм по-ясен.
Благодаря предварително за съдействието!  :)


Титла: C API за MYSQL
Публикувано от: ivak в Mar 01, 2005, 00:38
нормално printf ползва точка за разделяне на цялата от дробната част, обаче в твоя случай явно въпросният символ е предефиниран. нямам unix подръка, за да проверя, но по стари спомени някъде в locale.h имаше char *decimal_point. май беше в някаква структура.

ако не можеш да го намериш или пък не искаш да го променяш, можеш да направиш sprintf в междинен буфер и после да замениш запетаята с точка, като ползваш strchr.

и един последен съвет: мъдрите хора ползват int за цената, представена в стотинки, защото иначе рискуват да получат зверски грешки от закръгляне.


Титла: C API за MYSQL
Публикувано от: ivak в Mar 01, 2005, 00:45
мда, кажи "man 7 locale" и може би ще ти просветне малко.


Титла: C API за MYSQL
Публикувано от: akif в Mar 01, 2005, 21:23
Цитат (ivak @ Март 01 2005,01:38)
нормално printf ползва точка за разделяне на цялата от дробната част, обаче в твоя случай явно въпросният символ е предефиниран. нямам unix подръка, за да проверя, но по стари спомени някъде в locale.h имаше char *decimal_point. май беше в някаква структура.

ако не можеш да го намериш или пък не искаш да го променяш, можеш да направиш sprintf в междинен буфер и после да замениш запетаята с точка, като ползваш strchr.

и един последен съвет: мъдрите хора ползват int за цената, представена в стотинки, защото иначе рискуват да получат зверски грешки от закръгляне.

Благодарности за съвета да използвам цената в стотинки и int стойност за цената.
В този случай отпада проблема със double.
Но все пак трябва да го реша проблема, за да си изясня
нещата за в бъдещи потребности.
Ако имаш някакви конкретни идеи за СУРБД за Скалд ще
съм ти задължен.
Защото за първи път пиша софтуер със Бази от Данни.
Благодарности  :) !


Титла: C API за MYSQL
Публикувано от: в Mar 01, 2005, 23:33
Или използвай този код да замениш запетаите с точки:
Примерен код

char str[] = "32,33";
int i = 0;
for(i; i < strlen(str); i++)
{
if(str[i] == ',') str[i] = '.';
}
// str вече е 32.33


Поздрави,
gamehack


Титла: C API за MYSQL
Публикувано от: ivak в Mar 02, 2005, 01:29
Цитат (akif @ Март 01 2005,22:23)
Но все пак трябва да го реша проблема, за да си изясня нещата за в бъдещи потребности.

писах ти вече, проблемът ти е в локала. sprintf, fprintf и прочее деривати на printf ползват decimal_point символа, зададен в него.

Цитат (akif @ Март 01 2005,22:23)
Ако имаш някакви конкретни идеи за СУРБД за Скалд ще съм ти задължен.

по принцип не се занимавам с бази данни и не мога да ти дам кой знае какви идеи. Все пак, ако имаш някакви конкретни питания, давай. Наоколо има достатъчно сведущи хора.


Титла: C API за MYSQL
Публикувано от: mironcho в Mar 02, 2005, 10:31
Цитат (Guest @ Март 02 2005,00:33)
Или използвай този код да замениш запетаите с точки:
Примерен код

char str[] = "32,33";
int i = 0;
for(i; i < strlen(str); i++)
{
if(str[i] == ',') str[i] = '.';
}
// str вече е 32.33


Поздрави,
gamehack

Или използвай strchr():

Примерен код

char *p;
if ((p = strchr(str, ',')) != NULL) {
        *p = '.';
}


Ако очакваш повече от една запетайки, примера на gamehack е по удачен, или ще трябва да си направиш цикъл с strchr().
За подробно описание - man 3 strchr.


Титла: C API за MYSQL
Публикувано от: Hapkoc в Mar 02, 2005, 10:35
@gamehack: не си прав, човече. твоето решение ще работи, но само в конкретния случай. представи си, че тоя софтуер в някакъв момент се пусне в Танзания, където да кажем разделителя за десетичната част е ! (това е примерно само, разбира се).
нещата трябва да се правят да работят във всички ситуации.

поздрави :)


Титла: C API за MYSQL
Публикувано от: в Mar 02, 2005, 10:59
много идеи и всичките сложни :)

sprintf(query, "iнsert ito my_table values(%d, %d, %d, %f, %f)",
cl_id, st_id, doc_id,  cena, colicestvo);
сложи double стойностите в единични кавички и enjoy :)
sprintf(query, "insert ito my_table values('%d', '%d', '%d', '%f', '%f';)",
cl_id, st_id, doc_id,  cena, colicestvo);


Титла: C API за MYSQL
Публикувано от: akif в Mar 02, 2005, 20:22
Цитат (mironcho @ Март 02 2005,11:31)
Цитат (Guest @ Март 02 2005,00:33)
Или използвай този код да замениш запетаите с точки:
Примерен код

char str[] = "32,33";
int i = 0;
for(i; i < strlen(str); i++)
{
if(str[i] == ',') str[i] = '.';
}
// str вече е 32.33


Поздрави,
gamehack

Или използвай strchr():

Примерен код

char *p;
if ((p = strchr(str, ',')) != NULL) {
        *p = '.';
}


Ако очакваш повече от една запетайки, примера на gamehack е по удачен, или ще трябва да си направиш цикъл с strchr().
За подробно описание - man 3 strchr.

Благодаря за отзивите.
Този код със промяна на "," със "." ми е ясен,
но моя проблем беше друг.
Потребителя въвежда низ във entry, след което
този низ се поставя във заявката към сървъра чрез
spirintf("insert into my_table %f", atof(niz));
Фактичесики проблема не е в низа, а във това че след
като atof(...); преобразува низа във double се получава стойност
(например 22,32 ОТБЕЛЯЗВАМ ЧЕ 22,32 е число, а не НИЗ) при която разделителя на цялата част от десетичната е ЗАПЕТАЯ което е проблем за заявката,
защото ЗАПЕТАЯТА се явява разделител м/у отделните стойности които се пращат към сървъра. :)  
Мисля че проблема ще се реши със locale();
Прегледах man 7 locale, но честно казано не можах да разбера как да променя разделителя м/у цялата и десетичната част.
Ако ми изпратите някакъв кокретен код за промяна
на този разделител ще ме трогнете :) .


Титла: C API за MYSQL
Публикувано от: в Mar 02, 2005, 22:12
Цитат (Guest @ Март 02 2005,11:59)
много идеи и всичките сложни :)

sprintf(query, "iнsert ito my_table values(%d, %d, %d, %f, %f)",
cl_id, st_id, doc_id,  cena, colicestvo);
сложи double стойностите в единични кавички и enjoy :)
sprintf(query, "insert ito my_table values('%d', '%d', '%d', '%f', '%f';)",
cl_id, st_id, doc_id,  cena, colicestvo);

daf Това нещо със еденични кавички не работи коректоно.
опитна да изпратиш заявка от вида:
insert ito my_table values('1' ,  '33,32';);
и ще видиш.   :)
Проблема го реших като низа не го преобразувам
във доубле, а променям само ЗАПЕТАЯТА в низа с ТОЧКА и го поставям в заявката.
Например:
sprintf(query, "insert into my_table values(%d, '%s';)", atoi(niz1), niz2);
Като niz2 се очаква да чесло.  ;)
Благодарности на всички.  :D


Титла: C API за MYSQL
Публикувано от: mironcho в Mar 02, 2005, 22:27
Айде сега - в първия ти пост написа (цитирам) - " моя случай аз плучавам от потребителя тази променлива във вид на низ и като я преобразувам чрез  cena = atof(my_cena);".... значи все пак първо я имаш като низ ;)

И все пак, дори ако я нямаш първоначално в низ, какъв ти е проблема да sprintf -неш по отделно в низове и низовете да си ги обработиш по по-горе посочените начини. Може би става дълго, но ако наистина няма друг начин да се справиш с проблема, и това е вариант ;)

Иначе, това което казва ivak звучи логично - погледни все пак какъв ти е локала при изпълнението на програмата, и дори за по сигурно, в началото можеш да си го сетваш на някой стандартен.. примерно на 'C' ;). Начини разни - setenv(), setlocale()...


Успех


Титла: C API за MYSQL
Публикувано от: rpetrov в Mar 02, 2005, 22:50
Нищо не разбрах от цялата идея да се прави конвентиране низ-число-низ.

В такава ситуация обикновено се използва "prepared statement" с параметри, към които се свърват/привързват променливите. Това трябва да го има под една или друга форма.

Пример на псевдо код:
sqlcmd = "insert into ... values(:1, :2)"
stmnt = PREPARE STATEMENT(sqlcmd)
BIND_DOUBLE_PARAM(stmnt, 1, double_value);
BIND_INT_PARAM(stmnt, 2, int_value);
EXECUTE(stmnt);

Бел.: при някой бази вместо :1, :2 и т.н. се използва ?, т.е. горната команда би имала вида sqlcmd = "insert into ... values(?, ?)".

Ако има embedded sql може да се напише нещо такова:
EXEC SQL BEGIN DECLARE SECTION;
  double_value double;
  int_value int;
EXEC SQL END DECLARE SECTION;
EXEC SQL INSERT INTO mytbl (price, unit) VALUES (:double_value, :int_value);
След това SQL препроцесора ще генерира съответния код.


Титла: C API за MYSQL
Публикувано от: akif в Mar 02, 2005, 22:53
Цитат (mironcho @ Март 02 2005,23:27)
Айде сега - в първия ти пост написа (цитирам) - " моя случай аз плучавам от потребителя тази променлива във вид на низ и като я преобразувам чрез  cena = atof(my_cena);".... значи все пак първо я имаш като низ ;)

И все пак, дори ако я нямаш първоначално в низ, какъв ти е проблема да sprintf -неш по отделно в низове и низовете да си ги обработиш по по-горе посочените начини. Може би става дълго, но ако наистина няма друг начин да се справиш с проблема, и това е вариант ;)

Иначе, това което казва ivak звучи логично - погледни все пак какъв ти е локала при изпълнението на програмата, и дори за по сигурно, в началото можеш да си го сетваш на някой стандартен.. примерно на 'C' ;). Начини разни - setenv(), setlocale()...


Успех

Това с НИЗА се оплете нещо.
Аз мислех че ако напирмер променливат се съхранява  от тип double
тябва да изпратя заявката във следия вид:
 блабла values(33.32);, но полседно видях че и това:
  блабла values('33.32';); работи,
ОБАЧЕ АКО имаш низ  char str[] ="33,32"  sprint'vas
sprintf(buff, "%f", atof(str));
buff = "33,32"  и ако изпратиш към сървъра balbal values('buff';);
Получаваш грешка. защото сървъра ги вижда като 2 стойности 33 и 32, а не числото 33,32

Все пак горещо умолявам за съдействие
как да ги използвам функциите setlocale(), или
locale().
Погледнах ги във main'a. но нещо ми се губи.
Може ли конкретен код.   :)
Благодаря!!!


Титла: C API за MYSQL
Публикувано от: akif в Mar 02, 2005, 23:12
Цитат (rpetrov @ Март 02 2005,23:50)
Нищо не разбрах от цялата идея да се прави конвентиране низ-число-низ.

В такава ситуация обикновено се използва "prepared statement" с параметри, към които се свърват/привързват променливите. Това трябва да го има под една или друга форма.

Пример на псевдо код:
sqlcmd = "insert into ... values(:1, :2)"
stmnt = PREPARE STATEMENT(sqlcmd)
BIND_DOUBLE_PARAM(stmnt, 1, double_value);
BIND_INT_PARAM(stmnt, 2, int_value);
EXECUTE(stmnt);

Бел.: при някой бази вместо :1, :2 и т.н. се използва ?, т.е. горната команда би имала вида sqlcmd = "insert into ... values(?, ?)".

Ако има embedded sql може да се напише нещо такова:
EXEC SQL BEGIN DECLARE SECTION;
  double_value double;
  int_value int;
EXEC SQL END DECLARE SECTION;
EXEC SQL INSERT INTO mytbl (price, unit) VALUES (:double_value, :int_value);
След това SQL препроцесора ще генерира съответния код.

Какво ще направим ако потребителя въведе невалидно число или някаква безсмислица и ние го
поставим във заявката като влаидна стойност?
Имаш ли идея как да постъпя?
Да проверявам всеки символ който се въвежда от потребителя, да проверявям целия низ след като се въведе от потребителя или нещо друго?
Например:
Продавам 5 различни стоки, за всяка отделна стока
правя заявки към сървъра:
       2Актуализирам количеството (наличноста)
       3Добавям запис към изходящия документ, който
    съдържа запис за всяка продадена стока със този документ.
Ако Например ТРЕТАТА стока се продава със невалидна стойност?
Отбелязвам че вече са направни АКТУАЛИЗАЦИИ за предните 2!


Титла: C API за MYSQL
Публикувано от: в Mar 03, 2005, 18:04
Цитат (Guest @ Март 02 2005,23:12)
Цитат (Guest @ Март 02 2005,11:59)
много идеи и всичките сложни :)

sprintf(query, "iнsert ito my_table values(%d, %d, %d, %f, %f)",
cl_id, st_id, doc_id,  cena, colicestvo);
сложи double стойностите в единични кавички и enjoy :)
sprintf(query, "insert ito my_table values('%d', '%d', '%d', '%f', '%f';)",
cl_id, st_id, doc_id,  cena, colicestvo);

daf Това нещо със еденични кавички не работи коректоно.
опитна да изпратиш заявка от вида:
insert ito my_table values('1' ,  '33,32';);
и ще видиш.   :)
Проблема го реших като низа не го преобразувам
във доубле, а променям само ЗАПЕТАЯТА в низа с ТОЧКА и го поставям в заявката.
Например:
sprintf(query, "insert into my_table values(%d, '%s';)", atoi(niz1), niz2);
Като niz2 се очаква да чесло.  ;)
Благодарности на всички.  :D

тогава друга идея, която заобикаля проблема..
когато insert-ваш не можеш ли да направиш:
sprintf(query, "insert into my_table values(%d, %d, %d, replace('%f', ',', '.';), %f)", cl_id, st_id, doc_id,  cena, colicestvo);

т.е. да замениш запетаята с точка в самия mysql


Титла: C API за MYSQL
Публикувано от: akif в Mar 03, 2005, 21:29
Цитат (Guest @ Март 03 2005,19:04)
Цитат (Guest @ Март 02 2005,23:12)
Цитат на: Guest,Март 02 2005,11:59
много идеи и всичките сложни :)

sprintf(query, "iнsert ito my_table values(%d, %d, %d, %f, %f)",
cl_id, st_id, doc_id,  cena, colicestvo);
сложи double стойностите в единични кавички и enjoy :)
sprintf(query, "insert ito my_table values('%d', '%d', '%d', '%f', '%f';)",
cl_id, st_id, doc_id,  cena, colicestvo);

daf Това нещо със еденични кавички не работи коректоно.
опитна да изпратиш заявка от вида:
insert ito my_table values('1' ,  '33,32';);
и ще видиш.   :)
Проблема го реших като низа не го преобразувам
във доубле, а променям само ЗАПЕТАЯТА в низа с ТОЧКА и го поставям в заявката.
Например:
sprintf(query, "insert into my_table values(%d, '%s';)", atoi(niz1), niz2);
Като niz2 се очаква да чесло.  ;)
Благодарности на всички.  :Dтогава друга идея, която заобикаля проблема..
когато insert-ваш не можеш ли да направиш:
sprintf(query, "insert into my_table values(%d, %d, %d, replace('%f', ',', '.';), %f)", cl_id, st_id, doc_id,  cena, colicestvo);

т.е. да замениш запетаята с точка в самия mysql

daf супер си (replace('%f', ',', '.';) ) е решението на проблема. Работи така както се очаква.
Благодаря на всички за отзивчивоста.  :(


Титла: C API за MYSQL
Публикувано от: в Mar 04, 2005, 00:30
Цитат (Guest @ Фев. 28 2005,01:54)
replace() в повечето езици я има тая функция. Не съм сигурен обаче за С :) Иначе прави точно това - заменя синвол/и с друг/и

П.П. погледни тук http://bg2.php.net/manual/en/function.str-replace.php за да видим дали правилно се насочвам какво ти трбва - знам че това е за ПХП а не за С :)

Това е точно 1-вия отговор, май не си си направил труда да потърсиш , отдавна да си свършил работа, но нищо гледам е станало интересно - поне има доста мнения и идеи :)

И все пак от мен получаваш едно  :angry: !

Tъй то ??? .


Титла: C API за MYSQL
Публикувано от: akif в Mar 04, 2005, 22:36
Цитат (Guest @ Март 04 2005,01:30)
Цитат (Guest @ Фев. 28 2005,01:54)
replace() в повечето езици я има тая функция. Не съм сигурен обаче за С :) Иначе прави точно това - заменя синвол/и с друг/и

П.П. погледни тук http://bg2.php.net/manual/en/function.str-replace.php за да видим дали правилно се насочвам какво ти трбва - знам че това е за ПХП а не за С :)

Това е точно 1-вия отговор, май не си си направил труда да потърсиш , отдавна да си свършил работа, но нищо гледам е станало интересно - поне има доста мнения и идеи :)

И все пак от мен получаваш едно  :angry: !

Tъй то ??? .

ИЗВИНЯВАЙ *real* в отговари си говореше за php и за
това не я потърсих тази функция в C  :) .
И З В И Н Я В А Й.
Надявам се че не съм те огорчил невъзвратимо  :( .


Титла: C API за MYSQL
Публикувано от: the_real_maniac в Mar 05, 2005, 00:36
hehe-he спокойно бе :) Няма да те ям :D

Просто ми направи впечатление , а и човека е писал - виж дали я има и за С , тъй като я има в повечето езици :)

Успех с проектчето.