Reading numbers from a chosen line in a file C++ - c++

I want to know if I can read numbers from a chosen line in a file in c++.For example if I have .txt file like :
2 3
1 2 3 4
4 5 6 7
There are 3 lines, how can I read only the numbers on line 2 without having to read anything else?

Unless you know the exact file offset of the second line from a previous call to std::istream::tellg, then you will have to read the first line in order to get to the position of the second line. You can use the function std::getline for reading the first line as a std::string, or you can use std::istream::ignore to read and discard the first line, like this:
input.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
If you do happen to know the exact offset of the second line, then you can call std::istream::seekg in order to directly jump to that offset.
Note, howevever, that a file offset does not necessarily correspond to the number of characters that you see when reading the file in text mode. For example, on different platforms, line endings may consist of a different number of characters, which get translated to the single character \n when reading the file in text mode. However, the file offset required by std::istream::seekg is the offset in binary mode. Therefore, you should generally not attempt to calculate such an offset yourself (unless you opened the stream in binary mode, which you should not do for text files). You should only use the function std::istream::tellg for obtaining such an offset.

You can read the file line by line in C++ using
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(){
fstream newfile;
newfile.open("file.txt",ios::in);
if (newfile.is_open()){
string tp;
int i=0;
while(getline(newfile, tp)){
if (i==1) {
cout << tp << endl; // this will only print the second line
}
i+=1;
}
newfile.close();
}
}

Related

Replacing the data in a specific row in the txt file

I'm building a TCP Server application. Two different types of requests come from the client. In the first request type, the client requests a certain number of line information starting from a certain line. For example, the client throws a request like I want to read 3 lines starting at line 5.It's okay so far, I've completed this part, but now let's come to the part where I have difficulty.In the second type of request, the client wants to change the characters in a certain number of lines starting from a certain line.For example change 4 rows starting at row 6.txt file consists of 1s and 0s.txt file is as follows.
1
0
1
0
1
The txt file should be as follows when two line change requests are received, starting from the fourth line.
1
0
1
1
0
I don't use index numbers to identify line numbers, instead I first read the entire file with a loop and push the read data into a vector at each iteration. Thus, when I want to read a particular line, I call the desired index of that vector.
The parts of the code that interest us are shown below.
std::fstream myfile("fc3-4.txt", std::ios_base::in);
int reg;
std::vector<int> registers_vec;
while (myfile >> reg)
{
registers_vec.push_back(reg);
}
As a result of my research, I found to delete a specific data, but this does not work for me because for example, if I write 1 to the value to be deleted, it deletes all the 1s in the txt file.How can I replace a certain number of rows starting from a certain row as I mentioned above.Thanks in advance
First read the complete file into memory. Then close the file.
Make the modifications in memory.
Then, after modifications have been done, write the complete vector to the file.
E.g.:
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
int main() {
// Open the file and check, if it could be opened
if (std::ifstream dataStream{ "fc3-4.txt" }; dataStream) {
// Read all vallues in vector data
std::vector data(std::istream_iterator<int>(dataStream), {});
// And close the file
dataStream.close();
// Do any modification. Example flip bits for line 6 to 8
for (size_t line{ 6 }; data.size() > 8 and line < 8; ++line)
data[line] = 1 - data[line];
// Write all file to file
{
if (std::ofstream dataStream{ "fc3-4.txt" }; dataStream) {
// Write all data to file
std::copy(data.begin(), data.end(), std::ostream_iterator<int>(dataStream, "\n"));
}
else std::cerr << "\nError, Cannot open file for writing\n";
}
}
else std::cerr << "\nError, Cannot open file for reading\n";
}

Reading a specific line from a .txt file

I have a text file full of names:
smartgem
marshbraid
seamore
stagstriker
meadowbreath
hydrabrow
startrack
wheatrage
caskreaver
seaash
I want to code a random name generator that will copy a specific line from the.txt file and return it.
While reading in from a file you must start from the beginning and continue on. My best advice would be to read in all of the names, store them in a set, and randomly access them that way if you don't have stringent concerns over efficiency.
You cannot pick a random string from the end of the file without first reading up that name in the file.
You may also want to look at fseek() which will allow you to "jump" to a location within the input stream. You could randomly generate an offset and then provide that as an argument to fseek().
http://www.cplusplus.com/reference/cstdio/fseek/
You cannot do that unless you do one of two things:
Generate an index for that file, containing the address of each line, then you can go straight to that address and read it. This index can be stored in many different ways, the easiest one being on a separate file, this way the original file can still be considered a text file, or;
Structure the file so that each line starts at a fixed distance in bytes of each other, so you can just go to the line you want by multiplying (desired index * size). This does not mean the texts on each line need to have the same length, you can pad the end of the line with null-terminators (character '\0'). In this case it is not recommended to work this file as a text file anymore, but a binary file instead.
You can write a separate program that will generate this index or generate the structured file for your main program to use.
All this of course, considering you want the program to run and read the line without having to load the entire file in memory first. If your program will constantly read lines from the file, you should probably just load the entire file into a std::vector<std::string> and then read the lines at will from there.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
string filePath = "test.txt";
vector<std::string> qNames;
ifstream openFile(filePath.data());
if (openFile.is_open())
{
string line;
while (getline(openFile, line))
{
qNames.push_back(line.c_str());
}
openFile.close();
}
if (!qNames.empty())
{
srand((unsigned int)time(NULL));
for (int i = 0; i < 10; i++)
{
int num = rand();
int linePos = num % qNames.size();
cout << qNames.at(linePos).c_str() << endl;
}
}
return 0;
}

to find a word from a text file and then also display the line number in which the word lies using C++

I am absolutely a beginner at programming. No this is not a homework either. I am trying to learn it by myself. As stated in the titel itself I would like to input a .txt file and find out a particular word from the file. But thats not exactly what I want. I rather want the line number in which the word lies, so that i can use this line number and print out all the lines in the .txt file after this particular line. I found this code on youtube where it showed me how to find the word. I modified it a bit and its now giving me the line in which the searched word states (NOT THE LINE NUMBER). I am attaching the code.
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
using namespace std;
string find_word(string file, string word)
{
int offset;
string line1;
ifstream Myfile;
Myfile.open(open);
if (Myfile.is_open())
{
while (!Myfile.eof())
{
getline(Myfile, line1);
if ((offset = line1.find(word,o)) != string::npos)
{
return line1;
}
}
Myfile.close();
}
else
cout << "couldn't open...." << endl;
}
int main ()
{
string c = find_word("test.txt", "$COOR");
cout << c;
cin.get();
return 0;
}
right now the text file contains just 8 lines and "$COOR" lies in line 4. the program just gives me the entire line. But I want the line number so that I can print out the lines after line number 4.
I would later like to test it for a file having many lines i.e. more than 50000000 or so.
Think logically. You don't know whether a given line contains the word you're looking for until you read it. Therefore, you always need to know the number of the current line in the text file that you've read, so if the line contains the word, you then print the line number.
You need another variable int, initialized to zero, and incremented every time your code reads a line of text. So, when your code reads the first line of text, it gets incremented to 1. Then, when the code reads the next line of text, the new variable gets incremented to 2, and so on. So, when you find the word, you know where to look to find the line number.
Your code already has a loop for reading each line of text. Don't you think it's now obvious where you will need to increment the line counter?

Go to a specific line in file and read it

Problem description
I have a file containing a set of lines. A
File 1:
"Hello How are you"
"The cat ate the mouse"
Based on the the beginning and ending of the lines given by the user as input. I want to go to each line in the file and Extract it.
For examples if user types 1 , 17 then I have to go to line 1 that has a size of 17 characters. He can give any line number in the file.
I read the following Answer Read from a specific spot in a file C++. But I didn't really understand. Why do the lines have to be the same size? If i have the information concerning the beginning and ending of every line in the file. Why can't I access it directly?
Source code
I tried to use the following code which was inspired by Read Data From Specified Position in File Using Seekg But I couldn't extract the lines why?
#include <fstream>
#include <iostream>
using namespace std::
void getline(int, int, const ifstream & );
int main()
{
//open file1 containing the sentences
ifstream file1("file1.txt");
int beg = 1;
int end = 17;
getline(beg,end, file1);
beg = 2;
end = 20;
getline(beg,end, file1);
return 0;
}
void getline(int beg, int end, const ifstream & file)
{
file.seekg(beg, ios::beg);
int length = end;
char * buffer = new char [length];
file.read (buffer,length);
buffer [length - 1] = '\0';
cout.write (buffer,length);
delete[] buffer;
}
This code appears to be using line numbers as byte offsets. If you seek to offset "1" the file seeks forward 1 byte, not 1 line. If you seek to offset 2, the file seeks forward 2 bytes, not 2 lines.
To seek to a specific line you need to read the file and count the number of line breaks until you get to the line you want. There is code that already does this, for example std::getline(). If you don't already know the exact byte offset of the line you want, you can call std::getline() the number of times equal to the line number you want.
Also remember that the first byte of a file is at offset 0 not offset 1, and that different platforms use different bytes to indicate the end of a line (E.g. on Windows it's "\r\n", on Unix it's "\n"). If you're using a library function to read lines, the line ending should be taken care of for you.

Error reading and printing a text file with C++

I have a bug with my code (the code at the end of the question). The purpose of my C++ executable is to read a file that contains numbers, copy it in a std::vector and
then just print the contents in the stdout? Where is the problem? (atoi?)
I have a simple text file that contains the following numbers (each line has one number)
mini01:algorithms ios$ cat numbers.txt
1
2
3
4
5
When I execute the program I receive one more line:
mini01:algorithms ios$ ./a.out
1
2
3
4
5
0
Why I get the 6th line in the stdout?
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
void algorithm(std::vector<int>& v) {
for(int i=0; i < v.size(); i++) {
cout << v[i] << endl;
}
}
int main(int argc, char **argv) {
string line;
std::vector<int> vector1;
ifstream myfile("numbers.txt");
if ( myfile.is_open()) {
while( myfile.good() )
{
getline(myfile, line);
vector1.push_back(atoi(line.c_str()));
}
myfile.close();
}
else {
cout << "Unable to open file" << endl;
}
algorithm(vector1);
return 0;
}
You should not use while (myfile.good()), as it will loop once to many.
Instead use
while (getline(...))
The reason you can't use the flags to check for looping, is that they don't get set until after an input/output operation notices the problem (error or end-of-file).
Don't use good() as the condition of your extraction loop. It does not accurately indicate whether the next read will succeed or not. Move your call to getline into the condition:
while(getline(myfile, line))
{
vector1.push_back(atoi(line.c_str()));
}
The reason it is failing in this particular case is because text files typically have an \n at the end of the file (that is not shown by text editors). When the last line is read, this \n is extracted from the stream. Yes, that may be the very last character in the file, but getline doesn't care to look any further than the \n it has extracted. It's done. It does not set the EOF flag or do anything else to cause good() to return false.
So at the next iteration, good() is still true, the loop continues and getline attempts to extract from the file. However, now there's nothing left to extract and you just get line set to an empty string. This then gets converted to an int and pushed into the vector1, giving you the extra value.
In fact, the only robust way to check if there is a problem with extraction is to check the stream's status bits after extracting. The easiest way to do this is to make the extraction itself the condition.
You read one too many lines, since the condition while is false AFTER you had a "bad read".
Welcome to the wonderful world of C++. Before we go to the bug first, I would advise you to drop the std:: namespace resolution before defining or declaring a vector as you already have
using namespace::std;
A second advise would be to use the pre increment operator ++i instead of i++ wherever feasible. You can see more details on that here.
Coming to your problem in itself, the issue is an empty new line being read at the end of file. A simple way to avoid this would be to check the length of line before using it.
getline(myfile, line);
if (line.size()) {
vector1.push_back(atoi(line.c_str()));
}
This would enable your program now to read a file interspersed with empty lines. To be further foolproof you can check the line read for presence of any non numeric characters before using atoi on it. However the best solution as mentioned would be use to read the line read to the loop evaluation.