Відповіді:
Спочатку зробіть ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
Два стандартні методи:
Припустимо, що кожен рядок складається з двох чисел і читається лексемою за лексемою:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
Рядок на основі рядків з використанням потокових потоків:
#include <sstream>
#include <string>
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
int a, b;
if (!(iss >> a >> b)) { break; } // error
// process pair (a,b)
}
Вам не слід змішувати (1) і (2), оскільки аналіз на основі лексеми не піднімає нові рядки, тому ви можете виявити помилкові порожні рядки, якщо використання getline()
після вилучення на основі лексеми призведе до кінця лінія вже.
int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
while(getline(f, line)) { }
конструкції та щодо поводження з помилками, будь ласка, подивіться цю (мою) статтю: gehrcke.de/2011/06/… (я думаю, мені не потрібно, щоб сумнівна сумління розміщувала це тут, це навіть трохи попередньо датує цю відповідь).
Використовуйте ifstream
для читання даних з файлу:
std::ifstream input( "filename.ext" );
Якщо вам справді потрібно читати рядок за рядком, то зробіть це:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
Але вам, мабуть, просто потрібно витягнути координатні пари:
int x, y;
input >> x >> y;
Оновлення:
У своєму коді ви використовуєте ofstream myfile;
, проте o
в ofstream
стендах для output
. Якщо ви хочете прочитати з файлу (вводу), використовуйте ifstream
. Якщо ви хочете як читати, так і писати, використовуйте fstream
.
Читання файлів по рядку в C ++ може бути здійснено різними способами.
Найпростіший підхід - відкрити std :: ifstream та циклічно за допомогою викликів std :: getline (). Код чистий і легкий для розуміння.
#include <fstream>
std::ifstream file(FILENAME);
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
// using printf() in all tests for consistency
printf("%s", line.c_str());
}
file.close();
}
Інша можливість полягає у використанні бібліотеки Boost, але код стає дещо докладнішим. Продуктивність досить схожа на код вище (Loop with std :: getline ()).
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>
namespace io = boost::iostreams;
void readLineByLineBoost() {
int fdr = open(FILENAME, O_RDONLY);
if (fdr >= 0) {
io::file_descriptor_source fdDevice(fdr, io::file_descriptor_flags::close_handle);
io::stream <io::file_descriptor_source> in(fdDevice);
if (fdDevice.is_open()) {
std::string line;
while (std::getline(in, line)) {
// using printf() in all tests for consistency
printf("%s", line.c_str());
}
fdDevice.close();
}
}
}
Якщо продуктивність є критичною для вашого програмного забезпечення, ви можете розглянути можливість використання мови C. Цей код може бути в 4-5 разів швидшим, ніж версії C ++, наведені вище, див. Орієнтир нижче
FILE* fp = fopen(FILENAME, "r");
if (fp == NULL)
exit(EXIT_FAILURE);
char* line = NULL;
size_t len = 0;
while ((getline(&line, &len, fp)) != -1) {
// using printf() in all tests for consistency
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
Я зробив декілька показників ефективності з кодом вище, і результати цікаві. Я перевірив код з файлами ASCII, що містять 100 000 рядків, 1 000 000 рядків і 10 000 000 рядків тексту. Кожен рядок тексту в середньому містить 10 слів. Програма складена з -O3
оптимізацією, і її вихід передається /dev/null
, щоб видалити змінну часу реєстрації з вимірювання. І останнє, але не менш важливе, кожен фрагмент коду записує кожен рядок з printf()
функцією для узгодженості.
Результати показують час (у мс), який кожен фрагмент коду потребував для читання файлів.
Різниця в ефективності між двома підходами C ++ мінімальна і не повинна змінювати практику. Продуктивність коду С - це те, що робить тест вражаючим і може бути зміною гри з точки зору швидкості.
10K lines 100K lines 1000K lines
Loop with std::getline() 105ms 894ms 9773ms
Boost code 106ms 968ms 9561ms
C code 23ms 243ms 2397ms
std::cout
проти printf
.
printf()
функцію у всіх випадках для узгодженості. Я також намагався використовувати std::cout
у всіх випадках, і це абсолютно не мало значення. Як я нещодавно описав у тексті, вихід програми виходить на те, /dev/null
щоб час на друк рядків не вимірювався.
cstdio
. Ви повинні спробувати з налаштуванням std::ios_base::sync_with_stdio(false)
. Я думаю, ви отримали б набагато кращі показники (Це не гарантується, хоча це визначено реалізацією при відключенні синхронізації).
Оскільки ваші координати належать разом як пари, чому б не написати структуру для них?
struct CoordinatePair
{
int x;
int y;
};
Потім ви можете написати перевантажений оператор вилучення для istreams:
std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
is >> coordinates.x >> coordinates.y;
return is;
}
А потім ви можете прочитати файл координат прямо у такий вектор:
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
char filename[] = "coordinates.txt";
std::vector<CoordinatePair> v;
std::ifstream ifs(filename);
if (ifs) {
std::copy(std::istream_iterator<CoordinatePair>(ifs),
std::istream_iterator<CoordinatePair>(),
std::back_inserter(v));
}
else {
std::cerr << "Couldn't open " << filename << " for reading\n";
}
// Now you can work with the contents of v
}
int
в потоці неможливо прочитати два лексеми operator>>
? Як можна змусити його працювати з аналізатором зворотного відстеження (тобто, коли operator>>
не вдалося, повернути потік до попереднього кінця позиції, повернути помилкове чи щось подібне)?
int
лексеми, то is
потік оцінюватиметься, false
і цикл читання закінчується в цій точці. Ви можете виявити це всередині operator>>
, перевіривши повернене значення окремих прочитаних. Якщо ви хочете відкати потік, ви б зателефонували is.clear()
.
operator>>
цьому правильніше сказати, is >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
оскільки в іншому випадку ви припускаєте, що вхідний потік знаходиться в режимі пропуску пробілів.
Розширення на прийняту відповідь, якщо вхідний:
1,NYC
2,ABQ
...
ви все одно зможете застосувати таку ж логіку, як ця:
#include <fstream>
std::ifstream infile("thefile.txt");
if (infile.is_open()) {
int number;
std::string str;
char c;
while (infile >> number >> c >> str && c == ',')
std::cout << number << " " << str << "\n";
}
infile.close();
Хоча не потрібно закривати файл вручну, але це добре зробити, якщо область застосування змінної файлу більша:
ifstream infile(szFilePath);
for (string line = ""; getline(infile, line); )
{
//do something with the line
}
if(infile.is_open())
infile.close();
Ця відповідь призначена для візуальної студії 2017, і якщо ви хочете прочитати з текстового файлу, яке розташування є відносно вашої компільованої консольної програми.
спочатку помістіть свій текстовий файл (test.txt у цьому випадку) у папку з рішеннями. Після компіляції зберігайте текстовий файл у одній папці з applicationName.exe
C: \ Користувачі \ "ім'я користувача" \ джерело \ репос \ "рішенняНазви" \ "рішенняНазви"
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream inFile;
// open the file stream
inFile.open(".\\test.txt");
// check if opening a file failed
if (inFile.fail()) {
cerr << "Error opeing a file" << endl;
inFile.close();
exit(1);
}
string line;
while (getline(inFile, line))
{
cout << line << endl;
}
// close the file stream
inFile.close();
}
Це загальне рішення для завантаження даних у програму C ++ і використовує функцію readline. Це можна змінити для файлів CSV, але роздільник - це пробіл.
int n = 5, p = 2;
int X[n][p];
ifstream myfile;
myfile.open("data.txt");
string line;
string temp = "";
int a = 0; // row index
while (getline(myfile, line)) { //while there is a line
int b = 0; // column index
for (int i = 0; i < line.size(); i++) { // for each character in rowstring
if (!isblank(line[i])) { // if it is not blank, do this
string d(1, line[i]); // convert character to string
temp.append(d); // append the two strings
} else {
X[a][b] = stod(temp); // convert string to double
temp = ""; // reset the capture
b++; // increment b cause we have a new number
}
}
X[a][b] = stod(temp);
temp = "";
a++; // onto next row
}