Подробности
[В начало]
Проблема в реализации № S0694
Краткое описание
time_get<>::do_get_weekday не всегда распознает полные названия дней недели; похожая проблема есть и в time_get<>::do_get_monthname
Подробное описание
Из описания time_get<>::do_get_weekday() и time_get<>::do_get_monthname() (22.2.5.1.2):
Effects: Reads characters starting at s until it has extracted the (perhaps abbreviated) name of a weekday or month. If it finds an abbreviation that is followed by characters that could match a full name, it continues reading until it matches the full name or fails.Однако в случае, когда полное название дня недели не является продолжением его сокращенного названия, это название не распознается функцией.
Например, в русской локали (ru_RU.iso88595) не распознается "Понедельник" как понедельник, так как его сокращением является "Пнд". Зато распознается как понедельник последовательность "Пндедельник", что неверно.
Судя по коду реализации и комментариям к нему, в функцию изначально заложено такое ограничение, что сокращенное название каждого дня недели является подстрокой его полного названия.
Аналогичная проблема имеет место для функции time_get<>::do_get_monthname().
Раздел стандарта
Linux Standard Base C++ Specification 3.2, Chapter 9. Libraries, 9.1. Interfaces for libstdcxx, который ссылается на ISO/IEC 14882: 2003 Programming languages --C++, section 22.2.5.1.2
Способ воспроизведения
- Проверьте, что локаль "ru_RU.iso88595" есть на данной системе. Если такой локали нет - добавьте её вручную.
- Соберите и запустите приведённую ниже программу-пример.
Пример
#include <stdio.h>
#include <locale>
#include <sstream>
using namespace std;
int main()
{
tm t;
t.tm_wday = -1;//initial value
locale loc("ru_RU.iso88595");
const time_get<char>& tg = use_facet<time_get<char> >(loc);
// The 1st option
// Monday in Russian - it is not recognized
// const char* input_string = "\xbf\xde\xdd\xd5\xd4\xd5\xdb\xec\xdd\xd8\xda";
// The 2nd option
// Incorrect name of weekday, but it is recognized as Monday
// because it begins with the abbreviated Russian name of Monday
const char* input_string = "\xbf\xdd\xd4\xd5\xd4\xd5\xdb\xec\xdd\xd8\xda";
printf("Input string is '%s'.\n", input_string);
istringstream is(input_string);
ios_base::iostate err = (ios_base::iostate)0;
ios_base& str = is;
str.imbue(loc);
istreambuf_iterator<char> s = is;
istreambuf_iterator<char> end;
//this function call protected virtual function do_get_weekday
tg.get_weekday(s, end, str, err, &t);
string rest;
while(s != end) rest+= *s++;
printf("Rest of the string after parsing is '%s'.\n", rest.c_str());
printf("ios_base::failbit was%s set in err.\n",
err & ios_base::failbit ? "" : "n't");
printf("tm_wday became %d.\n", t.tm_wday);
return 0;
}
Компонент
libstdc++
Принято
GCC Bugzilla 38081
Статус
Исправлено в gcc-4.5.0
[В начало]