Иногда может понадобиться прочитать текстовый файл с множеством строк посимвольно. Если острой необходимости в посимвольном чтении нет, то следует использовать чтение блоками символов, а не по символам. Если при чтении блоками нужно сохранять переносы строк в многострочных файлах, то в качестве блоков удобно использовать строки, т. е. удобно использовать построчное чтение. Только с чтением каждой новой строки нужно добавлять символ или символы переноса строк.
Первый код, который будет показан, это не код посимвольного чтения в вектор строк, а более выгодный в подавляющем числе случаев код построчного чтения и записи считанных строк в строки вектора строк.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//С++ Листинг #0 Чтение строк файла в вектор строк
#include <iostream>
#include <vector>
#include <fstream>
usingnamespacestd;
intmain(){
conststringFNAME="1.txt";//Либо имя файла (если файл, где и программа), либо полный путь к файлу
vector<string>v;//Вектор для сохранённых строк
stringS;
ifstreamf(FNAME);
while(getline(f,S)){
S=S+"\n";
v.push_back(S);
}
f.close();
for(constauto&i: v){
cout << i;//Переносы строк были убраны в строки вектора, текс выводится многострочный
}
}
Я в любом случае не знаю, кому может понадобиться считывать в вектор строк данные посимвольно. Но если вы пришли сюда из поиска, зачем-то, значит, вам понадобилось такое извращение.
STL — это не библиотека работы с файлами, поэтому файлы обрабатываются не на уровне STL, а на уровне С++. Из STL в этой статье только вектор в качестве хранилища значений.
Для считывания символа из файла можно использовать функцию get(), определённую для файловых объектов в качестве функции считывания символа. Вообще файловые объекты — это так называемые потоковые объекты и для них функция get() — это чтение символа.
C++
1
2
3
cin.get();//прочитать символ клавиатуры
f.get();//прочитать символ какого-то файла. (если f — это файловая переменная)
ss.get()//прочитать символ объекта типа stringstream (если ss — это объект типа stringstream)
Файловыми переменными я называю переменные, объявленные для чтения файлов. Вообще это потоковые объекты, но мне удобно для статьи называть их файловыми переменными. Такие переменные — это объекты файловых смещений, а не сами файлы. Если написать вот так:
C++
1
2
3
while(!(f.eof())){
cout<<char(ch);
}
то получится проверка, находится ли уже сейчас файловая переменная f в состоянии достижения конца файла (выполнять цикл, если не находится). Но! Скорее, всего, она ещё не перемещалась по файлу. Чтобы условие было корректным, необходимо файловую переменную f сдвинуть на такой адрес дискового пространства, где операционная система начнёт сигналить, что это место — это не часть этого файла. Т. е. сначала нужно смещать файловую переменную (либо напрямую, либо чтением данных) и только потом проверять её на факт достижения конца файла.
Проблема с записью в многомерный вектор у неопытных любителей написать код может возникать из-за того, что вектор не умеет управлять памятью внутри своего содержимого. Если вектор многомерный, то работает такой же принцип, как для выделения памяти многомерным массивом. Единственное отличие — это что если для массивов используют прямое обращение к памяти, а для вектора используют функции, встроенные в используемый вектор.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//C++ Листинг #1
#include <iostream>
#include <vector>
#include <fstream>
usingnamespacestd;
intmain(){
setlocale(LC_ALL,"");
conststringFNAME="2.txt";//Либо имя файла (если файл, где и программа), либо полный путь к файлу
vector<string>v;
charch;//символ, считываемый из файла
intpos=0;//позиция последнего символа в собранной строке
intnumber=0;//номер строки вектора
ifstreamf(FNAME);
while(f.get(ch)){
if(!pos){//Если началась новая строка
v.push_back(string());//То добавляем в вектор пустую строку
number++;//то переходим на следующий элемент вектора
pos=0;//обнуляем позицию текущего символа в строке
}
v[number].append(pos+1,ch);//добавляем символ ch в конец собранной строки в v[number]
}
f.close();
for(constauto&i:v){
cout << i;//поскольку переносы строк доавились к строкам, мы видим текст в таком же виде, как файле
}
/*
cout << "\n\n";
cout << v[0]; //каждая строка в векторе уже хранит перенос строки,
cout << v[1]; //поэтому переносы происходят без указания '\n';
cout << v[2];
*/
}
По идее, эта публикация должна помочь понять, что вектор выделяет память только на одном уровне, а на любых уровнях вложенности память нужно подавать собственноручно. Так, например, из-за того, что вектор изначально пустой, у него нет даже первого элемента. А если нет первого элемента, то как же что-то записать в несуществующий элемент вектора? Поскольку у нас вектор строк, то первым элементом должна быть строка. Поэтому для собирания каждой новой строки в вектор добавляется пустая строка. Дальше к этой пустой строке постепенно добавляются выходящие из файла символы. Делать добавление символа к строке можно не только с помощью append, но и с помощью операции +=, использование которой может быть кому-то удобнее. Основа кода при этом не поменяется: учитывать позицию последнего пришедшего символа в очередной строке всё равно будет нужно.
C++
1
v[number]+=ch;//добавляем символ ch в конец собранной строки в v[number]
10 комментариев на «“(C++ STL) Посимвольное считывание многострочного текстового файла в вектор строк”»
Скажите пожалуйста, как можно записать подстроку вектора в переменную?
Я нашла такой метод: v.at(1).substr(1, 1); где v- это вектор типа char(все как в вашей программе), я хочу считать первый символ второй строки в переменную, можно ли это как то реализовать?
Построчно читать. Завести счетчик. На каждой итерации увеличивать счетчик. Цикл выполнять пока счетчик не достигнет нужного числа или файл не закончится.
Ваша программа не будет работать, если в файле будут русские буквы. Если не изменять кодировку ввода-вывода, то русские буквы будут кодироваться отрицательными числами. Среди них есть такая буковка «я», у которой код -1. К справке EOF это тоже -1. Так что на первой букве «я» все остановится.
P.S. Да, я знаю, что год прошел. Просто у меня немножечко подгорает.
Вы можете предложить решение?
Чтобы буквы не получали значение меньше нуля, нужно использовать unsigned char.
А вот, чтобы с кодировками проблему решить — это вопрос неприятный.
Скажите пожалуйста, а как мне реализовать чтение нескольких символов. Я читаю файл формата JPEG и сохраняю его в TEMP.txt. Но я тут подумал и решил, что мне нужен массив строк, так как файл хранит шеснадцатиричную «ffd8 ffe0 0010 4a46» информацию по четыре символа в четыре пары на строку. Так вот как мне считать все эти пары в двумерный массив строк. Я конечно понял как решить из выше описанного, но думаю это будет пахнуть говнокодом. Может вы предложите какой действующий вариант решения. Можно как-то читать по четыре символа? И я не против юзать векторы. Мне в дальнейшем как раз с матрицами векторов работать.
P.S. Хоть пост и древний, но надеюсь вы ответите мне. Заранее спасибо.
Тобиш я хочу знать сколько в файле строк и сколько в каждой строке таких пар по 4 символа, а затем их поместить в массив строк с помощью цикла. Как реализовать подобное зарание спасибо.
Я покажу в течение недели. Я сейчас немного занят, устаю.
Я покажу то, что Вы показываете, но не особо уверен, что это то, что Вам нужно.
Если сроки поджимают, то лучше просить не меня. Меня надо немного подождать.
Можно гораздо проще и изящней!
http://www.cyberforum.ru/cpp-beginners/thread641025.html – источник
Скажите пожалуйста, как можно записать подстроку вектора в переменную?
Я нашла такой метод: v.at(1).substr(1, 1); где v- это вектор типа char(все как в вашей программе), я хочу считать первый символ второй строки в переменную, можно ли это как то реализовать?
ПОдскажите пожалуйста, а как выводить по 10, 20 или 30 строк на экран???
Построчно читать. Завести счетчик. На каждой итерации увеличивать счетчик. Цикл выполнять пока счетчик не достигнет нужного числа или файл не закончится.
Ваша программа не будет работать, если в файле будут русские буквы. Если не изменять кодировку ввода-вывода, то русские буквы будут кодироваться отрицательными числами. Среди них есть такая буковка «я», у которой код -1. К справке EOF это тоже -1. Так что на первой букве «я» все остановится.
P.S. Да, я знаю, что год прошел. Просто у меня немножечко подгорает.
Вы можете предложить решение?
Чтобы буквы не получали значение меньше нуля, нужно использовать unsigned char.
А вот, чтобы с кодировками проблему решить — это вопрос неприятный.
Скажите пожалуйста, а как мне реализовать чтение нескольких символов. Я читаю файл формата JPEG и сохраняю его в TEMP.txt. Но я тут подумал и решил, что мне нужен массив строк, так как файл хранит шеснадцатиричную «ffd8 ffe0 0010 4a46» информацию по четыре символа в четыре пары на строку. Так вот как мне считать все эти пары в двумерный массив строк. Я конечно понял как решить из выше описанного, но думаю это будет пахнуть говнокодом. Может вы предложите какой действующий вариант решения. Можно как-то читать по четыре символа? И я не против юзать векторы. Мне в дальнейшем как раз с матрицами векторов работать.
P.S. Хоть пост и древний, но надеюсь вы ответите мне. Заранее спасибо.
А как считать несколько символов до пробела и поместить в массив. Вот что я хотел бы сделать на примере абстрактного кода:
<php>
string msg = «FFDD C05D BBFF 0000 C409 1111 1010 1100»;
string str[5][7] = {
{«FFDD», »C05D», ….. ….. ….. },
{ другая строка файла },
}
</php>
Тобиш я хочу знать сколько в файле строк и сколько в каждой строке таких пар по 4 символа, а затем их поместить в массив строк с помощью цикла. Как реализовать подобное зарание спасибо.
Я покажу в течение недели. Я сейчас немного занят, устаю.
Я покажу то, что Вы показываете, но не особо уверен, что это то, что Вам нужно.
Если сроки поджимают, то лучше просить не меня. Меня надо немного подождать.