Відповіді:
Спочатку зробіть 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
}