উত্তর:
প্রথমে একটি করুন 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()
টোকেন-ভিত্তিক নিষ্কাশন করার পরে ব্যবহার করেন তবে স্পুরিয়াস খালি লাইনগুলি শেষ হতে পারে a ইতিমধ্যে লাইন।
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
।
সি ++ এ লাইন দ্বারা একটি ফাইল লাইন পড়া কিছু ভিন্ন উপায়ে করা যেতে পারে।
সবচেয়ে সহজ পন্থাটি হল একটি স্ট্যান্ড :: আইফ্রিমি এবং স্টাডি :: গেটলাইন () কলগুলি ব্যবহার করে লুপ খুলুন। কোডটি পরিষ্কার এবং বুঝতে সহজ।
#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();
}
আরেকটি সম্ভাবনা হ'ল বুস্ট লাইব্রেরিটি ব্যবহার করা, তবে কোডটি আরও কিছুটা ভার্বোস পায়। পারফরম্যান্সটি উপরের কোডটির সাথে বেশ মিল (স্টাডি :: গেটলাইন () এর সাথে লুপ)।
#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();
}
}
}
যদি আপনার সফ্টওয়্যারটির জন্য পারফরম্যান্স সমালোচনা হয় তবে আপনি সি ভাষা ব্যবহারের বিষয়টি বিবেচনা করতে পারেন। এই কোডটি উপরের সি ++ সংস্করণগুলির চেয়ে 4-5 গুণ দ্রুত হতে পারে, নীচে বেনমার্ক দেখুন
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 ফাইলগুলির সাথে কোডটি পরীক্ষা করেছি যাতে ১০,০০,০০০ লাইন, ১,০০,০০০ লাইন এবং ১০,০০,০০০ পাঠ্য পাঠ্য রয়েছে। পাঠ্যের প্রতিটি লাইনে 10 টি করে শব্দ থাকে। প্রোগ্রামটি -O3
অপ্টিমাইজেশনের সাথে সংকলিত /dev/null
হয়েছে এবং পরিমাপ থেকে লগিং সময়ের পরিবর্তনশীল অপসারণের জন্য এর আউটপুটকে ফরোয়ার্ড করা হয়। সর্বশেষে, তবে অন্তত নয়, কোডের প্রতিটি টুকরো printf()
ধারাবাহিকতার জন্য প্রতিটি লাইনে লগ করে ।
ফলাফলগুলি কোডের প্রতিটি টুকরো ফাইলগুলি পড়তে যে সময়টি (এমএসে) দেখায়।
দুটি সি ++ পদ্ধতির মধ্যে পারফরম্যান্সের পার্থক্যটি ন্যূনতম এবং অনুশীলনে কোনও পার্থক্য করা উচিত নয়। সি কোডটির পারফরম্যান্সই বেনমার্কটিকে চিত্তাকর্ষক করে তোলে এবং গতির দিক থেকে গেম চেঞ্জার হতে পারে।
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();
যদিও ম্যানুয়ালি ফাইলটি বন্ধ করার দরকার নেই তবে ফাইলের ভেরিয়েবলের পরিধি আরও বড় হলে এটি করা ভাল idea
ifstream infile(szFilePath);
for (string line = ""; getline(infile, line); )
{
//do something with the line
}
if(infile.is_open())
infile.close();
এই উত্তরটি ভিজ্যুয়াল স্টুডিও 2017 এর জন্য এবং আপনি যদি পাঠ্য ফাইল থেকে পড়তে চান তবে কোন স্থানটি আপনার সংকলিত কনসোল অ্যাপ্লিকেশনের সাথে সম্পর্কিত।
প্রথমে আপনার সমাধান ফোল্ডারে আপনার পাঠ্য ফাইল (এই ক্ষেত্রে test.txt) রাখুন। সংকলনের পরে টেক্সট ফাইলটি একই ফোল্ডারে অ্যাপ্লিকেশননেম.এক্সই দিয়ে রাখুন
সি: \ ব্যবহারকারী \ "USERNAME" \ উৎস \ Repos \ "solutionName" \ "solutionName"
#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();
}
এটি সি ++ প্রোগ্রামে ডেটা লোড করার একটি সাধারণ সমাধান এবং রিডলাইন ফাংশনটি ব্যবহার করে। এটি সিএসভি ফাইলগুলির জন্য পরিবর্তিত হতে পারে তবে ডিলিমিটারটি এখানে একটি স্থান space
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
}