2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2, 3  След.
 
 c++ проблемы с перекодировкой
Сообщение15.03.2007, 22:13 
Аватара пользователя


24/10/05
400
задача так поставлена : с cin вводятся символы в latin 1 кодировке.
на выходе должны быть символы, преобразованные в кодировку utf-8
почему такой код неправильно работает?
Код:
unsigned char Y,Z,u[2],ch;
cin>>ch;
Y = ch&0xC0;
Y = Y>>6;
u[0] = 0xC0|Y;
Z = ch&0x3F;
u[1] = 0x80|Z;
cout<<u[0]<<u[1];

что я делаю не так?

 Профиль  
                  
 
 
Сообщение16.03.2007, 18:28 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Посмотрите описание, но одна, бросающаяся в глаза, ошибка — то, что Вы не отделяете символы диапазона 0 — 0x7F в отдельную ветку, а преобразуете их тоже. Согласно стандарту, это недопустимо (иначе нарушается однозначность представления, и многие хорошие свойства).

 Профиль  
                  
 
 
Сообщение16.03.2007, 19:40 
Аватара пользователя


24/10/05
400
нет, про символы с кодами от 0x00 до 0x7f я не забыл
у меня там перед этим кодом уже есть строчка
if (c<128) cout<<c;
что-то никак не могу разобраться, в чем проблема :(

 Профиль  
                  
 
 
Сообщение17.03.2007, 02:25 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Я проверил логику происходящего, всё работает (на Python).

1) Поместите полный текст функции.
2) Приведите пример, когда, по Вашему мнению, не работает. Включите вход, результат и ожидаемый результат.
3) Проверьте, Вы не путаете UTF-7 и UTF-8?

 Профиль  
                  
 
 
Сообщение17.03.2007, 16:06 
Аватара пользователя


24/10/05
400
1)это не так просто сделать , потому что программа на Си++ и это вообще не функция, а конструктор класса с параметрами.
2) здесь тоже есть проблема: не буду скрывать, что эту задачу нам задали в универе, но проверяется она дистанционно и автоматизированно и узнать, почему именно она не работает весьма и весьма затруднительно.
3)в каком смысле не путаю? вроде бы нет...

PS могу в ЛС кинуть код

 Профиль  
                  
 
 
Сообщение18.03.2007, 03:07 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Шлите. А еще лучше, положите файлы куда-нибудь, я мне ссылку.

Против автомата не попрешь, но кодировку я проверю. Хотя, я ведь задавал вопрос, какой ответ Вы ожидаете, а не автомат.

 Профиль  
                  
 
 
Сообщение18.03.2007, 19:03 
Аватара пользователя


24/10/05
400
послано в ЛС

 Профиль  
                  
 
 
Сообщение19.03.2007, 02:22 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Как Вы, наверное, догадываетесь, я узнаю о ЛС в тот момент, когда вхожу на форум. Так что … :wink:

Теперь по существу:
Код:
   while(cin>>c){
      if(c<128) cout<<c;continue;
      a=c;
      a.print();
   }

Я не в восторге от Вашего подхода, поскольку считаю, что класс utf8 должен преобразовывать все символы (а не только в диапазоне 0x80 - 0xFF), но это — Ваше дело. А ошибка Ваша в другом: Ваш условный оператор выводит символ, но не прерывает выполнение цикла (отсутствие пробела после ; ничего не меняет). Именно поэтому я всем и всегда рекомендую вставлять фигурные скобки, не думая и не заботясь ни о чем. Есть if, while, whatever … — поставил {}. У Вас же continue исполняется безусловно, то есть некоторые преобразования не происходит никогда. Вы должны были бы это увидеть, сравнив вывод программы с ожидаемым.

 Профиль  
                  
 
 
Сообщение19.03.2007, 07:54 


21/03/06
1545
Москва
незванный гость писал(а):
Именно поэтому я всем и всегда рекомендую вставлять фигурные скобки, не думая и не заботясь ни о чем. Есть if, while, whatever … — поставил {}.

Подписываюсь. Сколько дурацких ошибок совершают из-за того, что пытаются не ставить скобок. Пример:
Код:
if( foo() )
  if ( bar() )
    do_smth();
else
  do_smth2();

Может работать совсем не так, как вы ожидаете.

 Профиль  
                  
 
 
Сообщение19.03.2007, 18:01 
Аватара пользователя


24/10/05
400
насчет continue -это конечно позор мне. Cитуация изменилась к лучшему - вместо 1 теста прога проходит половину тестов
может надо добавить обработку символов с бОльшими, чем 0xFF кодами? хотя, нет - они же в 1 char не помещаются :(

 Профиль  
                  
 
 
Сообщение19.03.2007, 20:13 


21/03/06
1545
Москва
antoshka1303, я не знаком с кодировкой latin 1, но из того, что прочитал за 5 мин в инете, не вижу сложности в написании перекодировщика самым банальным образом: табличным. Всего 256 символов, таблица составит 256 байт, в чем проблема?
И еще: думаю, вам бы смогли помочь большее число людей, если бы вы не обсуждали свою проблему наполовину в привате с незванным гостем. То, что ваш перекодировщик содержится в конструкторе класса, не является препятствием для его публикации :).
Может быть, у вашего преподавателя особые требования к заданию? Огласите их.

Добавлено спустя 3 минуты 9 секунд:

Цитата:
может надо добавить обработку символов с бОльшими, чем 0xFF кодами? хотя, нет - они же в 1 char не помещаются

А вот я в данный момент работаю на системе, где char представляет 16 бит. В си нет четкой привязки типов к кол-ву занимаемых ими бит, есть только строгое требование, что sizeof(char) == 1.

 Профиль  
                  
 
 
Сообщение19.03.2007, 20:26 
Аватара пользователя


24/10/05
400
если угодно, то точная постановка задания такова
На стандартный поток ввода подаётся последовательность символов, завершающа-
яся признаком конца файла. Предполагается, что входной текст задан в кодировке latin-1. На
стандартный поток вывода выведите текст, преобразованный в кодировку utf-8. Символы с
кодами меньшими 128 должны выводится без изменений.
Указания. Символы в кодировке latin-1 непосредственно отображаются в кодировку ucs-4
(то есть символу с кодом XX в latin-1 соответствует символ с кодом XX в кодировке ucs-4).
Для ввода и вывода символов используйте посимвольный ввод с помощью operator >> и
operator <<.

мне кажется, что преподаватель меня убьет :oops:

упд: я, кстати, и не пользуюсь табличкой из-за этого: "то есть символу с кодом XX в latin-1 соответствует символ с кодом XX в кодировке ucs-4)." требования

 Профиль  
                  
 
 
Сообщение19.03.2007, 21:08 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
По всей видимости, Вам пора закатать рукава и начать тестировать программу. Ошибка с continue была бы найдена на первом же тесте с символом из второй половины таблицы. Значит, Вы не прогоняли подобный тест.

Поставьте себя на место автомата: подайте некоторый текст на вход, и сравните выход с ожидаемым. Это позволит Вам сделать большой шаг вперед. Вам, разумеется, понадобятся символы из первой и из второй половины таблицы во входном тексте, то есть, придется использовать шестнадцатеричный редактор или генерировать текст.

И еще: я не исключаю, что Вас ловят на особенностях оператора <<. Как себя поведет Ваша программа, если ей встретятся два пробела подряд? Пробел и пара табуляций?.. Что произойдет, если встретится \0 во входном потоке?

Я большой поклонник книжки Майерса "Искусство тестирования программ" (Myers G.J. — Art of Software Testing, но она выходила и в переводе; увы, мою книжку с автографом переводчика зачитали). Позволю себе большую цитату из предисловия, поскольку библиотека доступна не всем (да что там, ничтожному меньшинству с МГУ):
Цитата:
Self-Assessment Test

Before beginning the book, it is strongly recommended that you take the following short test. The prob­lem is the testing of the following program:

The program reads three integer val­ues from a card. The three values are interpreted as repre­senting the lengths of the sides of a triangle. The program prints a message that states whether the triangle is scalene, isos­celes, or equilateral.

On a sheet of paper, write a set of test cases (i.e., specific sets of data) that you feel would adequately test this program. When you have completed this, turn the page to analyze your tests.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The next step is an evaluation of the effectiveness of your testing. It turns out that this program is more difficult to write than it first appears to be. As a result, different versions of this program have been studied, and a list of common errors has been compiled. Evaluate your set of test cases by using it to answer the following questions. Give yourself one point for each “yes” answer.
  1. Do you have a test case that represents a valid scalene triangle? (Note that test cases such as 1,2,3 and 2,5,10 do not warrant a “yes” answer, because there does not exist a triangle having such sides.)
  2. Do you have a test case that represents a valid equilateral triangle?
  3. Do you have a test case that represents a valid isosceles triangle? (A test case specifying 2,2,4 would not be counted.)
  4. Do you have at least three test cases that represent valid isosceles triangles such that you have tried all three permu­tations of two equal sides (e.g., 3,3,4; 3,4,3; and 4,3,3)?
  5. Do you have a test case in which one side has a zero value?
  6. Do you have a test case in which one side has a negative value?
  7. Do you have a test case with three integers greater than zero such that the sum of two of the numbers is equal to the third? (That is, if the program said that 1,2,3 represents a scalene trian­gle, it would contain a bug.)
  8. Do you have at least three test cases in category 7 such that you have tried all three permuta­tions where the length of one side is equal to the sum of the lengths of the other two sides (e.g., 1,2,3; 1,3,2; and 3,1,2)?
  9. Do you have a test case with three integers greater than zero such that the sum of two of the numbers is less than the third (e.g., 1,2,4 or 12,15,30)?
  10. Do you have at least three test cases in category 9 such that you have tried all three permuta­tions (e.g., 1,2,4; 1,4,2; and 4,1,2)?
  11. Do you have a test case in which all sides are 0 (i.e., 0,0,0)?
  12. Do you have at least one test case specifying noninteger values?
  13. Do you have at least one test case specifying the wrong number of values (e.g., two, rather than three, integers)?
  14. For each test case, did you specify the expected output from the program in addition to the input values?
Of course, a set of test cases that satisfies the above condi­tions does not guarantee that all possible er­rors would be found, but since questions 1-13 represent errors that have actually oc­curred in different versions of this program, an adequate test of this program should expose these errors. If you are typical, you have done poorly on this test. As a point of reference, highly experienced professional program­mers score, on the average, only 7.8 out of a possible 14. The point of the exercise is to illus­trate that the testing of even a trivial program such as this is not an easy task. And if this is true, consider the dif­ficulty of testing a 100,000-statement air-traffic-control system, a compiler, or even a mundane payroll program.


Добавлено спустя 2 минуты 53 секунды:

e2e4 писал(а):
Всего 256 символов, таблица составит 256 байт,

Это неверно. Таблица должна будет состоять из строк переменной величины, длиной 1-2 байта.

 Профиль  
                  
 
 
Сообщение19.03.2007, 21:30 


21/03/06
1545
Москва
Извините, я не знаю уровня ваших знаний си/си++, поэтоум, может, напишу банальности:
По-моему вот такой должен быть алгоритм действий (с моей точки зрения, я весьма далек и от latin 1, и от ucs-4):
1. Язык, как я понял - чистый си++? Ваша задача явно может быть решена без всяких классов и т.п. наворотов си++. Тут они избыточны. Вам точно хочется иметь с ними дело? Если так, то пишем собственный класс, грамотно оформив его в виде .cpp и .h файлов. В конструкторе класса выполняем только те действия, которые необходимо выполнять для инициализации членов класса. Помещать в конструктор основной алгоритм - ввод, преобразование, вывод - неправильно. Далее в public секции вашего класса определяем и реализуем ф-ию преобразования одного кода в latin 1 в символ utf-8. Об этом чуть ниже. Возможно, вы захотите сделать такой конструктор, который получает указатель на объект класса iostream, или даже ios, сохранет его, и, в дальнейшем, при вызове соответствующей ф-ии, считывает и работает с данным потоком. Ваше право.
2. Создаем экземпляр вашего класса. В main() считываем символ из cin, проверем на eof, если не конец файла, передаем нашей ф-ии-члену класса, печатаем результат ее работы в cout:
Код:
while(!cin.eof())
{
  char c;
  cin >> c;
  cout << myClass->Transform(c);
}


Если вы выбрали второй вариант - просто создаем объект класса, передаем ему указаетль на cin, cout, запускаем волшебную ф-ию-член, и вуаля - он все сделает сам.
3. Самое сложное - пишем волшебную ф-ию. Для этого ищем в инете документацию на utf-8 и latin-1 (той, что я нашел только что, недостаточно для решения задача, поэтому не буду приводить ссылки). Внимательно читаем и пишем. Лучше всего все же найти информацию в виде таблицы latin1->utf-8. Задача стандартна, в инете наверняка есть уже готовые решения, но пользоваться ими не советую. Лучше всего выдрать оттуда готовую таблицу - меньше править придется.

Добавлено спустя 3 минуты 6 секунд:

незванный гость писал(а):
e2e4 писал(а):
Всего 256 символов, таблица составит 256 байт,

Это неверно. Таблица должна будет состоять из строк переменной величины, длиной 1-2 байта.

Это все равно не так много. Учитывая текущие объемы памяти ПК, и размеры откомпилированных программ, потеря места на таблицу, относительно алгоритмического подхода, ничтожна. Впрочем, я не настаиваю. Практически любую программную задачу можно решить уймой способов.

 Профиль  
                  
 
 
Сообщение19.03.2007, 21:44 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
e2e4 писал(а):
Код:
while(!cin.eof())
{
  char c;
  cin >> c;
  cout << myClass->Transform(c);
}

Вы будете долго смеяться, но я бы настойчиво рекомендовал посмотреть на результат еще более простого кода:
Код:
while(!cin.eof())
{
  char c;
  cin >> c;
  cout << с;
}

Нет у меня субъективной уверенности, что будет выведен входной текст. Ну нетути.

e2e4 писал(а):
Это все равно не так много.

Абсолютно согласен. Я возражал против 1 байт на вход, а не против табличного подхода. Впрочем, утверждение, что «таблица свыше нам дана, // замена счастию она» не всегда верно: надо уметь и построить таблицу…

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 36 ]  На страницу 1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group