Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как разобрать строку? 
:(
    Опции темы
ТарасАтавин
Дата 28.8.2013, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Дана строка std::wstring, в неё прочитан из преобразован и кодировки utf8 файл, требуется вывести файл на экран с сохранением перевода строк, а для этого надо разобрать строку на строки файла. 
Код
  HWND                        Handle;
  int                         Left;
  int                         Top;
  int                         Width;
  int                         Height;
  bool                        Flag;
  std::wstring                File;
  std::wstring                Text;
,
Код
 HANDLE    File;
 DWORD     LoLength;
 DWORD     HiLength;
 uint64_t  Length;
 char     *Utf8Buffer;
 DWORD     Readed;
 size_t    wchar_tBufferSize;
 wchar_t  *wchar_tBuffer;
 if (Flag)
 {
  File=CreateFileW(this->File.c_str(), GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL);
  if (File==INVALID_HANDLE_VALUE)
  {
   Text=L"";
   return;
  }
  LoLength=GetFileSize(File, &HiLength);
  Length=(uint64_t)LoLength+(((uint64_t)HiLength)<<32);
  if (Length==0)
  {
   Text=L"";
   CloseHandle(File);
   return;
  }
  Utf8Buffer=new char [Length];
  if (Utf8Buffer==NULL)
  {
   Text=L"";
   CloseHandle(File);
   return;
  }
  ReadFile(File, Utf8Buffer, Length, &Readed, NULL);
  if (Readed!=Length)
  {
   delete [] Utf8Buffer;
   Text=L"";
   CloseHandle(File);
   return;
  }
  wchar_tBufferSize=MultiByteToWideChar(CP_UTF8, 0, Utf8Buffer, Length, NULL, 0);
  if ((wchar_tBufferSize==0)&&((wchar_tBufferSize+1)==0))
  {
   delete [] Utf8Buffer;
   Text=L"";
   CloseHandle(File);
   return;
  }
  wchar_tBuffer=new wchar_t [wchar_tBufferSize+1];
  if (wchar_tBuffer==NULL)
  {
   delete [] wchar_tBuffer;
   delete [] Utf8Buffer;
   Text=L"";
   CloseHandle(File);
   return;
  }
  MultiByteToWideChar(CP_UTF8, 0, Utf8Buffer, Length, wchar_tBuffer, wchar_tBufferSize);
  wchar_tBuffer[wchar_tBufferSize]=(wchar_t)0;
  Text=wchar_tBuffer;
 }
 else
 {
  Text=L"";
 }
. Вот это поле Text и надо вывести с сохранением перевода строк, а для этого разобрать на строки файла. Как это сделать? Заранее не известно, сохранён ли файл в виндузячем, или в линуксоидном переводе строк.

Это сообщение отредактировал(а) ТарасАтавин - 28.8.2013, 09:09


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
bsa
Дата 28.8.2013, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



ТарасАтавин, ты лучше приведи пример того, что находится в файле.
Кстати, а кто сохраняет HWND в файл?!? Это же указатель и он валиден только в пределах одного приложения (более того, после перезапуска приложения он станет невалиден).
PM   Вверх
ТарасАтавин
Дата 28.8.2013, 11:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(bsa @  28.8.2013,  10:22 Найти цитируемый пост)
 ты лучше приведи пример того, что находится в файле.
Код
inсlude "strams.obj"
inсlude "streams.obj"
code from "strams.obj"
code from "streams.obj"
include "test.hmmz"
:= procedure main ()
procedure main ()
begin
     streams<NameSpaseMember>console<RightAssigne>x
     y<LeftAssigne>sin(x)
     streams<LefAssigne>stream<NameSpaseMember>line()<NameSpaseMember>console<LefAssigne>"sin("<LefAssigne>x<LefAssigne>"="<LefAssigne>y<LefAssigne>stream<NameSpaseMember>line()
end
И что это дало?

Добавлено @ 11:15
Цитата(bsa @  28.8.2013,  10:22 Найти цитируемый пост)
Кстати, а кто сохраняет HWND в файл?!?
Это где ж такое?

Это сообщение отредактировал(а) ТарасАтавин - 28.8.2013, 11:17


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
akizelokro
Дата 28.8.2013, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Цитата

. Вот это поле Text и надо вывести с сохранением перевода строк, а для этого разобрать на строки файла. Как это сделать? Заранее не известно, сохранён ли файл в виндузячем, или в линуксоидном переводе строк.


Если <regex> не реализован, а в винде С++ он пока не реализован, то тупо разбираешь строку на подстроки по символам новой строки TCHAR('\n') или 

Код

size_t pos1 = str.find("\n");
size_t pos = 0;
while(pos1 != -1)
{
     wstring new_str = str.substr(pos, pos1); 
// Здесь проверяешь что не пустая новая строка
// новую строку проверишь, есть ли в конце юниковский символ TCHAR('\r'), если есть, то вычистишь
     pos = pos1 + 1;  // переносишь отсчёт для нового поиска
     pos1 = str.find("\n", pos);
}


как-то так. да и разбор файла можешь попроще сделать. если файл текстовый, то 

Код

    tifstream f(filename, ios::in);
    if (f)
    {
        while (f.getline(buffer, bufferLength)) 
        {
// здесь на каждой итерации цикла делаешь что пожелаешь с содержимом буфера, которое и есть очередная строка
        }
        f.close();
    }
    else
    {
        MessageBox(NULL, _T("Ошибка открытия файла."), _T("ini"), 0);
        result = false;
    }


Добавлено @ 11:44
и, кстати, здесь тебе сразу же разница между ifstream.getline(..) и std::getline(..)

Это сообщение отредактировал(а) akizelokro - 28.8.2013, 12:17


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
ТарасАтавин
Дата 28.8.2013, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(akizelokro @  28.8.2013,  11:42 Найти цитируемый пост)
Если <regex> не реализован, а в винде С++ он пока не реализован, то тупо разбираешь строку на подстроки по символам новой строки TCHAR('\n') или 
Вопрос не в парсинге строк, а в том, как разобрать на них единую строку. То есть задача не 
Код
streams
 получить, а целиком 
Код
streams<LefAssigne>stream<NameSpaseMember>line()<NameSpaseMember>console<LefAssigne>"sin("<LefAssigne>x<LefAssigne>"="<LefAssigne>y<LefAssigne>stream<NameSpaseMember>line()
. Именно в той разбивке на строки, как в файле.

Добавлено @ 12:20
Цитата(akizelokro @  28.8.2013,  11:42 Найти цитируемый пост)
Код
find("\n");
Проект полностью юникодовый. И я не знаю, в каких переносах сохранён файл.

Добавлено через 6 минут и 1 секунду
Цитата(akizelokro @  28.8.2013,  11:42 Найти цитируемый пост)
как-то так. да и разбор файла можешь попроще сделать. если файл текстовый, то 

код C++
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
    tifstream f(filename, ios::in);
    if (f)
    {
        while (f.getline(buffer, bufferLength)) 
        {
// здесь на каждой итерации цикла делаешь что пожелаешь с содержимом буфера, которое и есть очередная строка
        }
        f.close();
    }
    else
    {
        MessageBox(NULL, _T("Ошибка открытия файла."), _T("ini"), 0);
        result = false;
    }
Имя файла тоже в широкой уникодовой стоке, у потоков с этим проблемы, даже у щироких,


Это сообщение отредактировал(а) ТарасАтавин - 28.8.2013, 12:21


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
akizelokro
Дата 28.8.2013, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Цитата

Вопрос не в парсинге строк, а в том, как разобрать на них единую строку. То есть задача не получить, а целиком 


Поточнее можно? Потому что термин "парсить" разбор именно и означает.
Заменить все вхождения символов '\r' '\n' на Сишные '\0'?


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
ТарасАтавин
Дата 28.8.2013, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Кстати, никсовый перевод \r\n, или наоборот?

Добавлено через 2 минуты и 46 секунд
Цитата(akizelokro @  28.8.2013,  12:29 Найти цитируемый пост)
Поточнее можно? Потому что термин "парсить" разбор именно и означает.

Разбор ченго? И на основании чего? Мне надо разобрать переменную на строки, а сами строки разбирать на лексемы уже не надо, это парсит сама функция вывода строки. Проблема в том, что на строки она разбирает совсем не так, как надо, а на основании ширины страницы, а с символами перевода строки не дружит вовсе.


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
akizelokro
Дата 28.8.2013, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Цитата(ТарасАтавин @  28.8.2013,  12:30 Найти цитируемый пост)
Кстати, никсовый перевод \r\n, или наоборот?

А чёрт его знает, похоже на то, что никсовый (бухал 4 года, много забыл).


Цитата

Разбор ченго? И на основании чего? Мне надо разобрать переменную на строки, а сами строки разбирать на лексемы уже не надо, это парсит сама функция вывода строки. Проблема в том, что на строки она разбирает совсем не так, как надо, а на основании ширины страницы, а с символами перевода строки не дружит вовсе. 



Давай ещё раз. По самым основам. Строка в Си (С++) завершается на нуль-символе '\0'. Экранное представление это совсем другое, здесь в теме, когда говорят про строку, говорят про Сишную строку с неограниченным числом символов и с произвольной длиной, ограниченной лишь нуль-символом.

Код

while (f.getline(buffer, bufferLength)) 


Цитата

Имя файла тоже в широкой уникодовой стоке, у потоков с этим проблемы, даже у щироких,

Это у кого проблемы? Сколько ни работаю, ещё не встречался. Я тебе работающий код привёл (выжимки из работающего кода).

Цитата

Проект полностью юникодовый. И я не знаю, в каких переносах сохранён файл.

А тебя это и не должно волновать. У тебя несколько вариантов действий. Заменить ещё в начале работы "\r\n" на "\n" и потом работать с "\n" (раз ты пишешь под Виндой). Либо разбивать сразу по '\n', а '\r' искать потом. С обязательным преобразование, конечно, раз ты юникоидную строку смотришь к WCHAR('\n'). 


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
akizelokro
Дата 28.8.2013, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Давай ещё раз посмотрим. Чтобы у тебя не возникало проблем с работой со строками string и wstring

Я как-то перекомпилировал две юникоидных библиотеки под VS проекты (не особо много, но по остальным были версии под Винду). Ребята и там уже берут и чтобы не париться с разницей между двумя этими типа строк при перекомпиляции пишут уже не string, не wstring, а tstring, определяя её так

#ifdef _UNICODE
typedef wstring tstring
// прочие обозначения, если надо
typedef wifstream tifstream; 
#else
typedef string tstring
// и здесь аналогично
typedef ifstream tifstream; 
#endif

Потому что в некоторых случаях бывает нужно в коде явно указать, что нужна строка string или wstring, просто строка в кавычках или L"..".
Потому что есть функции или классы, которые работают только с одним видом строк.
И, соответственно, в Виндоус 
И TCHAR() и _T()  будeт зависеть от метода компиляции. А WCHAR или char - уже нет.
Это делает простым и явным код, что если идёт tstring, то безразлично, как строка будет перекомпилирована, в Юникоде или вмультибайте. А если явное указание string или wstring, то кодер желает привлечь внимание, что здесь нужен именно такой вид строки.

И всё нормально в Винде читается в файловых операциях (рад буду узнать новое, если где-то это не так), если всё задать и присвоить нормально. И в Юникоде работает.

Это сообщение отредактировал(а) akizelokro - 28.8.2013, 13:25


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
xvr
Дата 28.8.2013, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(ТарасАтавин @  28.8.2013,  12:30 Найти цитируемый пост)
Кстати, никсовый перевод \r\n, или наоборот?

Это Win перевод строк. В Unix'ах это просто '\n'. (А в Маках кажется '\r')

PM MAIL   Вверх
akizelokro
Дата 28.8.2013, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Цитата(xvr @  28.8.2013,  13:22 Найти цитируемый пост)
Это Win перевод строк. В Unix'ах это просто '\n'. (А в Маках кажется '\r')

В Маках там вроде позашибенней что-то придумано. smile 

Пусть разбирает оба варианта сразу и, когда забудет, чем они там отличаются, то будет получаться переносимый код.
Вообще, вся эта канитель полезла из-за Доса (вспомнил). Потому что они в '\n' умудрились разместитьсразу два символа CRLF. Или LFCR


Это сообщение отредактировал(а) akizelokro - 28.8.2013, 13:38


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
ТарасАтавин
Дата 29.8.2013, 08:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(akizelokro @  28.8.2013,  12:51 Найти цитируемый пост)
Заменить ещё в начале работы "\r\n" на "\n" и потом работать с "\n" (раз ты пишешь под Виндой).
Нельзя, это редактор и он не должен самостоятельно заменять переносы строк, а визуализация нужна именно с полного буфера в оперативе, а не со строчного буфера.

Добавлено @ 09:00
Проблема решена так: 
Код
int          Top;
 int          Left1;
 int          Left2;
 int          x1;
 int          x2;
 int          y1;
 int          y2;
 size_t       i;
 size_t       n;
 size_t       L;
 size_t       Pos;
 size_t       Next;
 std::wstring s;
 HFONT FontMain;
 HFONT FontHeader1;
 SetMapMode(Context, MM_HIMETRIC);
 SetBkMode(Context, TRANSPARENT);
 SetViewportOrgEx(Context, 0, 0, NULL);
 FontHeader1=EasyFontCreate(Context, L"Times New Roman", 20.0, 0.5, IDFANormal);
 FontMain   =EasyFontCreate(Context, L"Arial"          , 16.0, 0.5, IDFANormal);
 Top   =- 200.0-PosY;
 Left1 =  200.0-PosX;
 Left2 = 3400.0-PosX;
 LeftText(Context, Left1, Top, WindowListing.File, x1, x2, y1, y2, FontHeader1);
 for (i=0, L=WindowListing.Text.length(), Pos=0; Pos<L; ++i)
 {
  Next=Min(WindowListing.Text.find(L"\n", Pos), WindowListing.Text.find(L"\r", Pos));
  s=WindowListing.Text.substr(Pos, Next-Pos);
  LeftText(Context, Left1, y2, Size_tToStr(i), x1, x2, y1, y2, FontMain);
  LeftLine(Context, Left2, y1, s, x1, x2, y1, y2, FontMain);
  for (Pos=Next; (((WindowListing.Text[Pos]==L'\n')||(WindowListing.Text[Pos]==L'\r'))&&(Pos<L)); ++Pos);
 }
 DeleteObject(FontHeader1);
 DeleteObject(FontMain);
 27-я строка ищёт перенос строки, а 31-я ищет начало следующей.

Это сообщение отредактировал(а) ТарасАтавин - 29.8.2013, 09:01


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
bsa
Дата 29.8.2013, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Если у тебя есть строка string x, которая содержит некий текст с разбивкой на строки, то самое простое засунуть ее в stringstream, а затем читать из него с помощью std::getline.
Можно извратиться и сделать тоже самое с помощью strtok.
PM   Вверх
ТарасАтавин
Дата 2.9.2013, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Нафига мне на пустом месте потоки?


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
bsa
Дата 2.9.2013, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(ТарасАтавин @  2.9.2013,  10:35 Найти цитируемый пост)
Нафига мне на пустом месте потоки? 
А нафига тебе куча тем в форуме?
Если бы место было простым, ты бы вопросов не задавал. логично?
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0589 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.