הבלוג של ארתיום
בלוג על לינוקס, תוכנה חופשית, מוזיקה, סלסה, ומה לא!
על תמיכה בלוקליזציה ב־C++ ועל תקן שבור
ככל שעובד הזמן אנחנו מתקרבים יותר ויותר לתקן C++ החדש שבהחלט מעשיר את השפה בהרבה כלים חיוניים -- הן מבחינת ליבת השפה והן לבחינת הספריה הסטנדרטית.
אבל נשאר מקום אחד שבו C++0x כמעט ולא נגע, אפילו שהתקן שבור לחלוטין -- לוקליזציה...
לצורך הדגמה בואו נכתוב תכנה טרוייואלית שמדפיסה מספר לקובץ טקסט number.txt:
#include <iostream>
#include <fstream>
#include <locale>
int main()
{
// Set global locale to system default;
std::locale::global(std::locale(""));
// open file "number.txt"
std::ofstream number("number.txt");
// write a number to file and close it
number<<13456<<std::endl;
}
תכנה פשוטה אפילו טריוויאלית. עכשיו בואו נעשה אותו דבר ב־C.
#include <stdio.h>
#include <locale.h>
int main()
{
setlocale(LC_ALL,"");
FILE *f=fopen("number.txt","w");
fprintf(f,"%'i\n",13456);
fclose(f);
return 0;
}
גם פשוט ביותר.
בואו נריץ את התכנות כאשר הלוקל הוא en_US.UTF-8
... ונקבל בקובץ number.txt את המספר: 13,456, עכשיו נעשה אותו דבר, רק נגדיר לוקל נפוץ אחר ru_RU.UTF-8
: כך LC_ALL=ru_RU.UTF-8 ./a.out
ונקבל:
13<?>456
כאשר אם נריץ תכנה ב־C נקבל דווקא משהו נכון: 13 456
אופס... מה קרה כאן? כשאני עושה את אותו הדבר דרך C ודרך C++ אני מקבל תוצאה שונה, יותר מזה, הפלט של תכנה שכתובה ב־C++ מצביעה על טקסט UTF-8 לא תקין! (אפשר לבדוק בקלות עם iconv).
מה בעצם קראה כאן?
לפי הגדרות הלוקל הרוסי. התו שמפריד בין אלפים ומאות הוא תו U2002 -- EN SPACE -- סוג של רווח שונה מרווח ASCII רגיל U0020. כלומר בגלל שמדובר בתו Unicode שהוא לא בתחום ASCII הוא צריך להיות מקודד כמחרוזת ארוכה מבית 1.
אז למה ספריית C מתמודדת יפה מאוד עם בעיה זו וספריית C++ לא?
עכשיו בואו נסתכל בהגדרות הסביבה להצגת מספרים: המחלקה std::numpunct
זאת הייתה דוגמה של בעיוה הטריוויאלית לשחזור. קיימים עוד בעיות עקרוניות רבות כאלה בתקן לוקליזציה הקיים ב־C++ היום. חבל שהוועדה שמטפלת ב־C++0x כלל לא התייחסת לנושא זה --- אולי הגיע זמן להעלות את הנושא?
הוסף תגובה:
חובה לאפשר JavaScript כדי להגיב.