Подробности

[В начало]

Проблема в реализации № 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

Способ воспроизведения

  1. Проверьте, что локаль "ru_RU.iso88595" есть на данной системе. Если такой локали нет - добавьте её вручную.
  2. Соберите и запустите приведённую ниже программу-пример.

Пример

#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

[В начало]