Hi I have a text file which contains some numerical data. Of that text file ONLY the lines
14 to 100 have to be read into my C++ program. Each of these lines contain three numbers corresponding to x,y,z coordinates of a point. Thus, coordinates are given for 87 points in all.
I want to put these numbers into the arrays xp[87] yp[87] and zp[87].
How do I perform this?
Uptil now I have been used to the following
ifstream readin(argv[1])//Name of the text file
for (int i=0; i<=86; ++i)
{
readin>>xp[i]>>yp[i]>>zp[i];
}
But this technique works only for those files which contain 87 lines and the data to be read starts from the first line itself.
In the present case I want to ignore ALL lines before line 14 and ALL lines after line 100
Read line by line, for most flexibility in your format:
#include <fstream>
#include <sstream>
#include <string>
std::ifstream infile("thefile.txt");
std::string line;
unsigned int count = 0;
while (std::getline(infile, line))
{
++count;
if (count > 100) { break; } // done
if (count < 14) { continue; } // too early
std::istringstream iss(line);
if (!(iss >> x[count - 14] >> y[count - 14] >> z[count - 14]))
{
// error
}
}
// all done
In the present case I want to ignore ALL lines before line 14
Since you have to actually read the file to know where a line ends and a new one begins, you will have to then read 13 lines. Use getline() and a dummy string to hold the results from it.
and ALL lines after line 100
Just close the stream and be done with it.
After several years, Range-v3 allows one to write this:
#include <fstream>
#include <iostream>
#include <range/v3/view/drop.hpp>
#include <range/v3/view/getlines.hpp>
#include <range/v3/view/take.hpp>
using namespace ranges;
using namespace ranges::views;
int main() {
std::ifstream ifs{"inputFile"};
auto lines = getlines(ifs) | take(100) | drop(15/* which is 14 - 1 */);
for (auto i : lines) {
std::cout << i << std::endl;
}
}
Requires C++17.
Related
I want to read a txt file and I want to process each number on the line one by one, apply some functions and pass to the other line. When the line is over, I don't know how to apply the same operations to the lines below. Methods will get a different output from each line that is why I have to handle each line separately.
int number;
ifstream readingFile("a.txt");
while(readingFile >> number){
/* Methods will be applied to each number in the line */
}
readingFile.close();
a.txt
23 4 555
2123 44 21 4
1 45 667 2 112
Working C++ Code
To clear doubts Test it in https://www.tutorialspoint.com/compile_cpp11_online.php
Just copy-paste execute
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
int main ()
{
//code create a file with numbers
std::ofstream myfile;
myfile.open ("file.txt");
myfile << "123 12 32323\n 4444 55 535\n";
myfile.close();
std::ifstream input( "file.txt" );
for( std::string eachLine; getline( input, eachLine ); )
{
std::istringstream strm(eachLine);
std::string splitedLines;
// loop for each string and add to the vector
while ( strm >> splitedLines )
{
std::stringstream geek(splitedLines);
int num; // can be int, float or double
geek >>num;
//perform action on all num in each line one by one
std::cout<<num<<std::endl;
}
}
return 0;
}
Edit: PythonCode read numbers one by one in each line
fileName = open('a.txt', 'r')
line = fileName.readline() //reading first line
while(line):
for eachStringNumber in line.split():
number = int(eachStringNumber)
/// Methods will be applied to each number in the line ///
line = fileName.readline() // reading lines one by one in each loop
fileName.close()
I have two text files like these:
11.txt:
1 5.66
2 4.95
3 2.55
4 0.99
5 2.87
NB.txt:
1 2 3 4 5
4 5 3 2 1
3 4 5 1 2
I have written the below code to fine, for example, "1" from File 1, and search it in File 2, then substitute "1" with "5.66". and repeat it for other numbers, i.e. 2,3,4,5. but I don't know why it doesn't work. additionally, it doesn't read the first line of 11.txt.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
string line;
double AtomId, Atom_radius,search ;
ifstream AtomId_file ("11.txt");
string namefile;
if (AtomId_file.is_open()){
for (int linenox = 0; getline (AtomId_file,line) && linenox < 6; linenox++){
if (linenox == 0) AtomId_file>>AtomId>>Atom_radius;
}
cout<<"AtomId: "<<AtomId<<" Atom_radius: "<<Atom_radius<<endl;
cout<<namefile<<"\n";
}
ifstream NB("NB.txt");
size_t pos;
if (NB.is_open())
{
search = AtomId;
getline(NB,line);
pos=line.find(search);
if(pos!=string::npos)
{
search = Atom_radius;
cout <<"Found!";
}
}
ofstream myfile;
myfile.open ("12.txt");
myfile << search << "\n";
}
the output in 12.txt is:
2
instead of :
5.66 4.95 2.55 0.99 2.87
0.99 2.87 2.55 4.95 5.66
2.55 0.99 2.87 5.66 4.95
I understand that your are new to C++.
I analyzed your code and put in tons of comments, where the errors are. You need to change your design. Before starting to type in code, you must first write down, what should be done. Then, and this is most important, you think (without taking any language into consideration) how you can solve the problem. This is most important. Also for you later programming career. The design is most important. So think 3 hours, how it could be done. Search possible design solutions in the internet. Write it on a piece of paper or somewhere.
Then, after hours of thinking, select an apropriate language and check, how it could be implemented.
I show a standard C++ solution below. You will not understand it immediately. So please try to understand the design first. Then lookup all used C++-statements in the internet and try to understand.
Read some good C++ books, before starting to code.
Please see first your commented code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std; // You should not use this line at all. Use qualified names.
int main()
{
string line;
double AtomId, Atom_radius, search; // These variables are not initalized
ifstream AtomId_file("r:\\11.txt");
string namefile;
if (AtomId_file.is_open()) { // You should not use is_open but simply if (AtomId_file)
// Here you have a loop running from 0,1,2,3,4,5. That are 6 loops. But you have only 5 lines in your sourcefile
// The you read one line, each time the loops runs. So in the beginning, this will read the first line
for (int linenox = 0; getline(AtomId_file, line) && linenox < 6; linenox++) {
// And only for the first loop event, when linenox==0, you read then next line "2 4.95"
// So you read already lines. But not more.
// ypu need to read line by line (only one per loop) and then store the result in an appropriate STL Container
if (linenox == 0) AtomId_file >> AtomId >> Atom_radius;
}
// Since you assigned the data only once, the values will be 2, 4.95
// They will never change
cout << "AtomId: " << AtomId << " Atom_radius: " << Atom_radius << endl;
// The variable namefile has never been initailized and is always emtpy, So ""
cout << namefile << "\n";
}
ifstream NB("r:\\NB.txt");
size_t pos; // Not initialized
if (NB.is_open()) // Not recommended. Use "if (NB) instead". In general, use more meaningful variable names
{
search = AtomId; // search is now 2 and never somthing else
getline(NB, line); // Read exactly one (and only this one time) a line containing 1, 5.66
pos = line.find(search); // So, 2 will never be found
if (pos != string::npos) // Always false, can never be true
{
search = Atom_radius; // Will never be executed
cout << "Found!"; // Will never be executed
}
}
ofstream myfile; // You can write directly ofstream myfile("12.txt");
myfile.open("12.txt");
myfile << search << "\n"; // And the output will always be 2.
}
And here is a correct and working example:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <vector>
#include <iterator>
int main() {
// Open the file 11.txt and check, if it could be opened
if (std::ifstream file11("11.txt"); file11) {
// Define variable id and attribute and initialize them to theire default values.
unsigned int id{};
double attribute{};
// Here we will store all values (id, attribute) of all lines that we read in the follwing loop
std::unordered_map<unsigned, double> replacement{};
// Read in a llop ALL lines and extract id and attribute, and, check if this worked
while (file11 >> id >> attribute) {
// Create a new replacement value for id
replacement[id] = attribute;
}
// So, now, all data from file 11.txt is read and stored.
// We will now read the next file and store the data
// Open next input file NB.txt and check, if that worked
if (std::ifstream fileNB("NB.txt"); fileNB) {
// And already now, open output file 12.txt and check, if open worked
if (std::ofstream myfile("12.txt"); myfile) {
// Read a complete line and check, if that worked. Read all lines in a loop
for (std::string line; std::getline(fileNB, line); ) {
// Put the line in a std::istringstream, so that we can extract each single value
std::istringstream iss(line);
// We will store the single values of the just read line into a vector
// This we do, because we do not know, how many values will be in that line
// We use a so called iterator, to iterate over all elements in the just read line
// The result will be stored in a vector
// The istream_iterator will call the ">>"-operator, until the line is empty
// For the vector, we use its range constructor
std::vector values(std::istream_iterator<unsigned>(iss), {});
// Now go through all values, replace them and out the result into the output file
for (const unsigned& u : values) myfile << replacement[u] << " ";
myfile << "\n";
}
}
}
}
return 0;
}
Of course there are many other possible solutions
I have a .txt file that has a sequence of numbers and spaces on the first line that I wish to read into a vector. Then there is a '$' symbol on the next line. On the line after that is another line containing a sequence of numbers and spaces (like the first) that I'd like to read into another vector. For example
1 2 3 4 5
$
4 3 2 1 6
I've tried everything but can't keep reading after the initial while loop reads in integers. How do I move past the second line and read the third? Right now It just outputs the first line. Currently, this is my code:
int main(int argc, const char * argv[]) {
ifstream file(argv[1]);
if (file.is_open() && file.good()){
int addMe;
vector<int> addMeList;
while(file>>addMe){
cout <<addMe<<endl;
addMeList.push_back(addMe);
}
string skip;
while(file >> skip)
cout << skip << endl;
int searchQuery;
vector<int> searchQueries;
while(file>>searchQuery){
searchQueries.push_back(searchQuery);
}
for (int i=0; i<searchQueries.size();i++)
{
cout << searchQueries[i]<<endl;
}
}
return 0;
}
Two problems:
The first loop will cause the streams failbit to be set (when it attempts to read the '$' from the second line). If that bit is set, you can't read more from the stream. You need
to clear the stream state.
Once you've done the above, the second loop will read the rest of the file.
One possible solution is to read lines instead. Use e.g. std::getline to read a line. Put the line into a std::istringstream, and read the values from that.
The program logic seems to be flawed. Using the first while loop you read the entire file word-by-word till the very end (not till the end of line), after that trying to read again fails, which is evaluated as false, thus it never even gets into the other loops. Instead, consider reading line by line using getline and then breaking it into ints using istringstream.
Here's how I'd improve it:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <sstream> // include this header to use istringstream
using namespace std;
int main() {
ifstream file("text.txt"); // my test file; Replace with yours
if (file.is_open() && file.good()) {
string lineIn; // general line to read into
int i; // general int to read into
vector<int> addMeList;
// int addMe; // not needed anymore
getline(file, lineIn); // read a line 1
istringstream istr(lineIn); // string stream we can use to read integers from
while (istr >> i) {
cout << i << endl;
addMeList.push_back(i);
}
// string skip; // not needed anymore
getline(file, lineIn); // skips line 2
// int searchQuery; // not needed anymore
vector<int> searchQueries;
getline(file, lineIn); // read a line 2
istringstream istr2(lineIn); // string stream we can use to read integers from
while (istr2 >> i) {
searchQueries.push_back(i);
}
for (int i = 0; i < searchQueries.size(); i++)
{
cout << searchQueries[i] << endl;
}
}
return 0;
}
Input file:
1 2 3 4 5
$
4 3 2 1 6
Output:
1
2
3
4
5
4
3
2
1
6
The following code is meant to loop through the last ten lines of a file that I have previously opened. I think the seekg function refers to binary files and only go through individual bytes of data, so that may be my issue here.
//Set cursor to 10 places before end
//Read lines of input
input.seekg(10L, ios::end);
getline(input, a);
while (input) {
cout << a << endl;
getline(input, a);
}
input.close();
int b;
cin >> b;
return 0;
}
The other method I was thinking of doing is just counting the number of times the file gets looped through initially, taking that and subtracting ten, then counting through the file that number of times, then outputting the next ten, but that seems extensive for what I want to do.
Is there something like seekg that will go to a specific line in the text file? Or should I use the method I proposed above?
EDIT: I answered my own question: the looping thing was like 6 more lines of code.
Search backwards for the newline character 10 times or until the file cursor is less than or equal to zero.
If you don't care about the order of the last 10 lines, you can do this:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cmath>
int main() {
std::ifstream file("test.txt");
std::vector<std::string> lines(10);
for ( int i = 0; getline(file, lines[i % 10]); ++i );
return 0;
}
A file has contents in format like this
3 3
ABCD
ABCD
ABCD
...
I want to read first number in variable k and another number in another variable say n. Rest of the lines I want to store in a string say seq so that
k = 3
n = 3
seq = ABCDABCDABCD..
I need to do this in c++. I just started learning c++. I know how to read file line by line and word by word but I don't know how to read file in this specific format.
When performing per-line validation, use a std::istringstream to separate the lines, then perform regular stream operations.
For example, given a program taking your input file as the sole argument:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
int main(int argc, char *argv[])
{
if (argc < 2)
return EXIT_FAILURE;
std::ifstream inp(argv[1]);
// first line
std::string line;
if (std::getline(inp, line))
{
// load into string stream for parsing.
std::istringstream iss(line);
int k, n;
if (iss >> k >> n)
{
// remaining lines dumped into seq
std::string seq;
while (std::getline(inp, line))
seq.append(line);
// TODO: use k, n, and seq here
}
else
{
std::cerr << "Failed to parse k and/or n\n";
}
}
else
{
std::cerr << "Failed to read initial line from file\n";
}
}
It may seem overkill to string-stream the first line, but if your input format mandates this:
k n
data1
data2
etc...
you want to detect when something like this happens:
k
n
data1
...
If that detection isn't important, then you can just pull the first two values directly from the input file stream and ignore the rest of the remaining line to start up the line-append loop. Such code would look like this:
#include <iostream>
#include <fstream>
#include <string>
#include <limits>
#include <cstdlib>
int main(int argc, char *argv[])
{
if (argc < 2)
return EXIT_FAILURE;
std::ifstream inp(argv[1]);
// read two integers
int k, n;
if (inp >> k >> n)
{
// ignore the remainder of the current line to position the first
// line for our seq append-loop
inp.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::string line;
std::string seq;
while (std::getline(inp, line))
seq.append(line);
// TODO: use k, n, and seq here
}
else
{
std::cerr << "Failed to parse k and/or n\n";
}
}