+ Reply to Thread
Results 1 to 2 of 2

Thread: locale messes up sprintf, but only in Qt program

  1. #1
    Join Date
    Jul 2017
    Posts
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default locale messes up sprintf, but only in Qt program

    I have the following function:
    Qt Code:
    1. string ldecimal(double x,double toler)
    2. {
    3. double x2;
    4. int h,i,iexp,chexp;
    5. size_t zpos;
    6. char *dotpos,*epos,*pLcNumeric;
    7. string ret,s,m,antissa,exponent,saveLcNumeric;
    8. char buffer[32],fmt[8];
    9. assert(toler>=0);
    10. pLcNumeric=getenv("LC_NUMERIC");
    11. if (pLcNumeric)
    12. saveLcNumeric=pLcNumeric;
    13. setenv("LC_NUMERIC","C",true);
    14. if (toler>0 && x!=0)
    15. {
    16. iexp=floor(log10(fabs(x/toler))-1);
    17. if (iexp<0)
    18. iexp=0;
    19. }
    20. else
    21. iexp=DBL_DIG-1;
    22. h=-1;
    23. i=iexp;
    24. while (true)
    25. {
    26. sprintf(fmt,"%%.%de",i);
    27. sprintf(buffer,fmt,x);
    28. x2=atof(buffer);
    29. if (h>0 && (fabs(x-x2)<=toler || i>=DBL_DIG+3))
    30. break;
    31. if (fabs(x-x2)>toler || i<=0)
    32. h=1;
    33. i+=h;
    34. }
    35. dotpos=strchr(buffer,'.');
    36. epos=strchr(buffer,'e');
    37. if (epos && !dotpos) // e.g. 2e+00 becomes 2.e+00
    38. {
    39. memmove(epos+1,epos,buffer+31-epos);
    40. dotpos=epos++;
    41. *dotpos=='.';
    42. }
    43. if (dotpos && epos)
    44. {
    45. m=string(buffer,dotpos-buffer);
    46. antissa=string(dotpos+1,epos-dotpos-1);
    47. exponent=string(epos+1);
    48. if (m.length()>1)
    49. {
    50. s=m.substr(0,1);
    51. m.erase(0,1);
    52. }
    53. iexp=atoi(exponent.c_str());
    54. zpos=antissa.find_last_not_of('0');
    55. antissa.erase(zpos+1);
    56. iexp=stoi(exponent);
    57. if (iexp<0 && iexp>-5)
    58. {
    59. antissa=m+antissa;
    60. m="";
    61. iexp++;
    62. }
    63. if (iexp>0)
    64. {
    65. chexp=iexp;
    66. if (chexp>antissa.length())
    67. chexp=antissa.length();
    68. m+=antissa.substr(0,chexp);
    69. antissa.erase(0,chexp);
    70. iexp-=chexp;
    71. }
    72. while (iexp>-5 && iexp<0 && m.length()==0)
    73. {
    74. antissa="0"+antissa;
    75. iexp++;
    76. }
    77. while (iexp<3 && iexp>0 && antissa.length()==0)
    78. {
    79. m+='0';
    80. iexp--;
    81. }
    82. sprintf(buffer,"%d",iexp);
    83. exponent=buffer;
    84. ret=s+m;
    85. if (antissa.length())
    86. ret+='.'+antissa;
    87. if (iexp)
    88. ret+='e'+exponent;
    89. }
    90. else
    91. ret=buffer;
    92. setenv("LC_NUMERIC",saveLcNumeric.c_str(),true);
    93. return ret;
    94. }
    To copy to clipboard, switch view to plain text mode 
    The function is used to format numbers when writing to files, so it has to use '.' for the decimal point regardless of locale. I added the saving and restoring LC_NUMERIC code to fix this bug. It didn't work.

    I am using it in at least two programs: bezitest, which is a non-Qt test program, and viewtin, which is a Qt GUI program. Until I implement hit-testing, viewtin is displaying the coordinates of the cursor in world space. "bezitest ldecimal" outputs, among others, "3.141592653589793". viewtin displays a tooltip saying something like "3,141592653589793,2,718281828459045". I ran it in gdb and found that the comma is put there by sprintf.

    locale outputs the following:
    Qt Code:
    1. LANG=en_DK.UTF-8
    2. LANGUAGE=en_US:es
    3. LC_CTYPE="en_DK.UTF-8"
    4. LC_NUMERIC="en_DK.UTF-8"
    5. LC_TIME="en_DK.UTF-8"
    6. LC_COLLATE="en_DK.UTF-8"
    7. LC_MONETARY="en_DK.UTF-8"
    8. LC_MESSAGES="en_DK.UTF-8"
    9. LC_PAPER="en_DK.UTF-8"
    10. LC_NAME="en_DK.UTF-8"
    11. LC_ADDRESS="en_DK.UTF-8"
    12. LC_TELEPHONE="en_DK.UTF-8"
    13. LC_MEASUREMENT="en_DK.UTF-8"
    14. LC_IDENTIFICATION="en_DK.UTF-8"
    15. LC_ALL=
    To copy to clipboard, switch view to plain text mode 
    LC_NUMERIC is actually unset.

  2. #2
    Join Date
    Jul 2017
    Posts
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: locale messes up sprintf, but only in Qt program

    I catted /proc/<pid>/environ into two files while the programs were running and compared them. They are identical, except for the last entry, which is the name of the program. Here it is, with some entries snipped:
    Qt Code:
    1. XDG_VTNR=7
    2. XDG_SESSION_ID=2
    3. SSH_AGENT_PID=3140
    4. PAM_KWALLET5_LOGIN=<snip>
    5. KDE_MULTIHEAD=false
    6. GPG_AGENT_INFO=/home/phma/.gnupg/S.gpg-agent:0:1
    7. TERM=xterm
    8. SHELL=/bin/bash
    9. XDG_SESSION_COOKIE=<snip>
    10. GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/home/phma/.gtkrc-2.0:/home/phma/.config/gtkrc-2.0
    11. KONSOLE_DBUS_SERVICE=:1.500
    12. KONSOLE_PROFILE_NAME=Shell
    13. QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1
    14. GS_LIB=/home/phma/.fonts
    15. GTK_RC_FILES=/etc/gtk/gtkrc:/home/phma/.gtkrc:/home/phma/.config/gtkrc
    16. WINDOWID=310378531
    17. SHELL_SESSION_ID=<snip>
    18. XDG_SESSION_CLASS=user
    19. KDE_FULL_SESSION=true
    20. USER=phma
    21. LS_COLORS=<snip>
    22. XCURSOR_SIZE=0
    23. QT_ACCESSIBILITY=1
    24. XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session1
    25. XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
    26. SSH_AUTH_SOCK=<snip>
    27. DEFAULTS_PATH=/usr/share/gconf//usr/share/xsessions/plasma.default.path
    28. SESSION_MANAGER=<snip>
    29. XDG_CONFIG_DIRS=/etc/xdg/xdg-/usr/share/xsessions/plasma:/etc/xdg:/usr/share/kubuntu-default-settings/kf5-settings
    30. PATH=/home/phma/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
    31. DESKTOP_SESSION=/usr/share/xsessions/plasma
    32. QT_QPA_PLATFORMTHEME=appmenu-qt5
    33. QT_IM_MODULE=compose
    34. PWD=/home/phma/build/bezitopo/dbg
    35. XDG_SESSION_TYPE=x11
    36. KONSOLE_DBUS_WINDOW=/Windows/2
    37. KDE_SESSION_UID=1000
    38. LANG=en_DK.UTF-8
    39. MANDATORY_PATH=/usr/share/gconf//usr/share/xsessions/plasma.mandatory.path
    40. KONSOLE_DBUS_SESSION=/Sessions/4
    41. SHLVL=1
    42. XDG_SEAT=seat0
    43. COLORFGBG=15;0
    44. HOME=/home/phma
    45. KDE_SESSION_VERSION=5
    46. LANGUAGE=en_US:es
    47. XCURSOR_THEME=oxy-blue
    48. LOGNAME=phma
    49. XDG_SESSION_DESKTOP=KDE
    50. XDG_DATA_DIRS=/usr/share//usr/share/xsessions/plasma:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
    51. DBUS_SESSION_BUS_ADDRESS=<snip>
    52. LESSOPEN=| /usr/bin/lesspipe %s
    53. DISPLAY=:0
    54. XDG_RUNTIME_DIR=/run/user/1000
    55. PROFILEHOME=
    56. XDG_CURRENT_DESKTOP=KDE
    57. GTK_IM_MODULE=xim
    58. LESSCLOSE=/usr/bin/lesspipe %s %s
    59. PAM_KWALLET_LOGIN=/tmp/kwallet_phma.socket
    60. XAUTHORITY=/tmp/xauth-1000-_0
    61. OLDPWD=/home/phma
    62. _=./viewtin
    To copy to clipboard, switch view to plain text mode 

+ Reply to Thread

Similar Threads

  1. Adding a QListWidget messes up entire layout
    By Kasea in forum Qt Programming
    Replies: 0
    Last Post: 9th June 2017, 07:43
  2. Replies: 1
    Last Post: 31st October 2015, 16:21
  3. example for using sprintf and vsprintf in Qt-4.7.4
    By gunturrohith in forum Qt Programming
    Replies: 4
    Last Post: 8th September 2015, 09:08
  4. Sprintf in QT ?
    By wilcd in forum Newbie
    Replies: 1
    Last Post: 28th April 2012, 11:05
  5. Libcurl messes up the order of execution
    By phoenix12345 in forum Qt Programming
    Replies: 2
    Last Post: 7th September 2010, 11:14

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts