Имеется небольшая программа, которая получает строки из файла и с определенного символа разбивает его выводя на экран, то что, соответственно, разбила. Но вывод у меня получается кривой, например:
�С СПб Мегафон 1:00
Как победить такую проблему? Заранее спасибо.Код программы и содержимое текстового файлика ниже.
$less ./1.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> v;
string str_t, str;
char intchar;
ifstream in ("1.txt"); //Открываем поток для файла
while (in.get(intchar)) { //Читаем посимвольно
if (intchar == '\n') { //Если символ является переводом строки то ..
v.push_back(str); // добавляем строку в массив
str.erase(); // отчищаем строку
} else {
str += intchar; //иначе добавляем символы в строку
};
};
in.close(); // Заканчиваем работу с файлом
for (unsigned int i=0; i<v.size(); i++) {
for (int k=51;k<=103;k++) {
str_t+=v[i][k];
};
cout << str_t << endl;
str_t.clear();
};
};$less ./1.txt
134-65-10 01/09 14:04 8-921-946-19-50 СПС СПб Мегафон 1:00 1.50
134-65-10 01/09 14:05 8-911-167-24-24 СПС СПб Телеком 21 1:00 1.50
>у меня получается кривой, например:
>Как победить такую проблему? Заранее спасибо.gawk '{print substr($0,51,103-51+1)}' <1.txt
Не за что.
>for (int k=51;k<=103;k++) {
> str_t+=v[i][k];
>};
>>у меня получается кривой, например:
>>Как победить такую проблему? Заранее спасибо.
>
>gawk '{print substr($0,51,103-51+1)}' <1.txt
>
>Не за что.
>>for (int k=51;k<=103;k++) {
>> str_t+=v[i][k];
>>};Спасибо за ответ, но мне бы в c++ виде =) ибо там не только, те строки что в примере.
>[оверквотинг удален]
>>
>>gawk '{print substr($0,51,103-51+1)}' <1.txt
>>
>>Не за что.
>>>for (int k=51;k<=103;k++) {
>>> str_t+=v[i][k];
>>>};
>
>Спасибо за ответ, но мне бы в c++ виде =) ибо там
>не только, те строки что в примере.Чтобы правильно разбивать строки utf8 надо с ним работать как с utf8 а не как с char
вот посмотрите: http://utfcpp.sourceforge.net/
>[оверквотинг удален]
>>>>for (int k=51;k<=103;k++) {
>>>> str_t+=v[i][k];
>>>>};
>>
>>Спасибо за ответ, но мне бы в c++ виде =) ибо там
>>не только, те строки что в примере.
>
>Чтобы правильно разбивать строки utf8 надо с ним работать как с utf8
>а не как с char
>вот посмотрите: http://utfcpp.sourceforge.net/Спасибо за статью, буду сейчас курить ее.
>[оверквотинг удален]
>>>>>};
>>>
>>>Спасибо за ответ, но мне бы в c++ виде =) ибо там
>>>не только, те строки что в примере.
>>
>>Чтобы правильно разбивать строки utf8 надо с ним работать как с utf8
>>а не как с char
>>вот посмотрите: http://utfcpp.sourceforge.net/
>
>Спасибо за статью, буду сейчас курить ее.Да если перевести как изначально было в CP-1251, то все нормально. Но я не как не могу понять, почему когда выводил всю строку было все ОК, а когда часть не отрабатывало?
>[оверквотинг удален]
>>>
>>>Чтобы правильно разбивать строки utf8 надо с ним работать как с utf8
>>>а не как с char
>>>вот посмотрите: http://utfcpp.sourceforge.net/
>>
>>Спасибо за статью, буду сейчас курить ее.
>
>Да если перевести как изначально было в CP-1251, то все нормально. Но
>я не как не могу понять, почему когда выводил всю строку
>было все ОК, а когда часть не отрабатывало?cp1251 это однобайтовый символ, с ним все будет работать.
чего вам не понятно? вы разбиваете половину символа utf8, из за этого и знак вопроса.
ссылка показывает как я понял библиотеку, которая нормально решает проблемы с утф8, используйте ее.
>[оверквотинг удален]
>>>Не за что.
>>>>for (int k=51;k<=103;k++) {
>>>> str_t+=v[i][k];
>>>>};
>>
>>Спасибо за ответ, но мне бы в c++ виде =) ибо там
>>не только, те строки что в примере.
>
>Чтобы правильно разбивать строки utf8 надо с ним работать как с utf8
>а не как с charА вот и нифига. Если требуется разбивка на слова (space,comma,semicolon-separated) или разбивка на строки по \n, то никаких дополнительных знаний об том что это кодировка именно utf8 не надо. Просто работаеш как с однобайтной и паришся - в этом и сила utf8.
>[оверквотинг удален]
>>>Спасибо за ответ, но мне бы в c++ виде =) ибо там
>>>не только, те строки что в примере.
>>
>>Чтобы правильно разбивать строки utf8 надо с ним работать как с utf8
>>а не как с char
>
>А вот и нифига. Если требуется разбивка на слова (space,comma,semicolon-separated) или разбивка
>на строки по \n, то никаких дополнительных знаний об том что
>это кодировка именно utf8 не надо. Просто работаеш как с однобайтной
>и паришся - в этом и сила utf8.Я собственно так и сделал, по " " разбил и не стал заморачиваться.
Спасибо.
// как-то так
#include <iostream>
#include <fstream>
#include <string>
#include <vector>using namespace std; // вообще-то не гуд
// выносим константы из кода
const streamsize SIZE_LINE = 256; // должно существовать ограничение на длину строки, если нет обрабатывать строку тщательнее..
const size_t FIRST_POS = 51;
const size_t LEN_NAME = 103 - 51;int main()
{
try
{
vector<string> v;//char intchar; - имя переменной вводит в конфуз.
//string str_t; - суффикc _t означает что это некий тип, так принято (pid_t, size_t).ifstream in("file.txt");
// закидываем строки в массив
char stmp[SIZE_LINE];
while (in.getline(stmp, SIZE_LINE)) v.push_back(stmp);// обходим массив, можно заменить for_each(), но так сейчас нагляднее
for (vector<string>::iterator it = v.begin(), et = v.end(); it != et; ++it)
{
cout << it->substr(FIRST_POS, LEN_NAME) << endl;
}// а вот тут файлег сам закроется када деструктор для in сработает =)
}
catch (exception &e) // общий просто чтобы показать что эксепшены надо обрабатывать
{
cerr << "Опаньки, эксепшен: " << e.what() << endl;
return 1;
}// спасибо за внимание =)
return 0;
}
>[оверквотинг удален]
>что эксепшены надо обрабатывать
> {
> cerr << "Опаньки, эксепшен:
>" << e.what() << endl;
> return 1;
> }
>
> // спасибо за внимание =)
> return 0;
>}Спасибо за ответ, ваша программа не заносила в массив строки (во всяком случае у меня) и попробовав убрать цикл, и получить хотя бы одну строку, и разобрать ее я получил следующее:
�С СПб Телеком 21 1:00То бишь так же как и у меня =(
Есть еще какие идейки.
>
>Спасибо за ответ, ваша программа не заносила в массив строки (во всяком
>случае у меня)это как? система у вас какая?
>одну строку, и разобрать ее я получил следующее:
>�С СПб Телеком 21 1:00Проблема в первом символе как я понимаю? Так это зависит от локали и кодировки текста в файле. Какие они?
>[оверквотинг удален]
>>Спасибо за ответ, ваша программа не заносила в массив строки (во всяком
>>случае у меня)
>
>это как? система у вас какая?
>
>>одну строку, и разобрать ее я получил следующее:
>>�С СПб Телеком 21 1:00
>
>Проблема в первом символе как я понимаю? Так это зависит от локали
>и кодировки текста в файле. Какие они?Похоже у вас utf-8 в файле, а со строкой вы работаете считая что 1 символ = 1 байту, поэтому ваше начало подстроки (51) некорректно. в utf-8 русские буквы занимают 2 байта.
Заменим на работу с вайдами и станет проще:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <locale>
#include <cstdlib>using namespace std;
// эти параметры надо установить правильными исчисляя в символах, не в байтах.
const size_t FIRST_POS = 52; // ?
const size_t LEN_NAME = 103 - FIRST_POS;int main()
{
// устанавливаем локаль
setlocale(LC_ALL, getenv("LANG"));
locale loc(getenv("LANG"));wcout.imbue(loc); // локаль для потока вывода
try
{
wfstream in("file.txt");
in.imbue(loc); // локаль для потока ввода// закидываем в массив
vector<wstring> v;
wstring s;
while (getline(in, s)) v.push_back(s);// выводим
for (vector<wstring>::iterator it = v.begin(), et = v.end(); it != et; ++it)
{
wcout << it->substr(FIRST_POS, LEN_NAME) << endl;
}
}
catch (exception &e)
{
wcerr << L"Опаньки эксепшен: " << e.what() << endl;
return 1;
}return 0;
}
>[оверквотинг удален]
> }
> catch (exception &e)
> {
> wcerr << L"Опаньки эксепшен:
>" << e.what() << endl;
> return 1;
> }
>
> return 0;
>}Спасибо, за помощь. Дальше буду думать уже сам.