to find a word from a text file and then also display the line number in which the word lies using C++ - 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?

Related

Reading numbers from a chosen line in a file 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();
}
}

Filling a cstring using <cstring> with text from a textfile using File I/O C++

I began learning strings yesterday and wanted to manipulate it around by filling it with a text from a text file. However, upon filling it the cstring array only prints out the last word of the text file. I am a complete beginner, so I hope you can keep this beginner friendly. The lines I want to print from the file are:
"Hello World from UAE" - First line
"I like to program" - Second line
Now I did look around and eventually found a way and that is to use std::skipary or something like that but that did not print it the way I had envisioned, it prints letter by letter and skips each line in doing so.
here is my code:
#include <fstream>
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
int main() {
ifstream myfile;
myfile.open("output.txt");
int vowels = 0, spaces = 0, upper = 0, lower = 0;
//check for error
if (myfile.fail()) {
cout << "Error opening file: ";
exit(1);
}
char statement[100];
while (!myfile.eof()) {
myfile >> statement;
}
for (int i = 0; i < 30; ++i) {
cout << statement << " ";
}
I'm not exactly sure what you try to do with output.txt's contents, but a clean way to read through a file's contents using C++ Strings goes like this:
if (std::ifstream in("output.txt"); in.good()) {
for (std::string line; std::getline(in, line); ) {
// do something with line
std::cout << line << '\n';
}
}
You wouldn't want to use char[] for that, in fact raw char arrays are hardly ever useful in modern C++.
Also - As you can see, it's much more concise to check if the stream is good than checking for std::ifstream::fail() and std::ifstream::eof(). Be optimistic! :)
Whenever you encounter output issues - either wrong or no output, the best practise is to add print (cout) statements wherever data change is occurring.
So I first modified your code as follows:
while (!myfile.eof()) {
myfile >> statement;
std::cout<<statement;
}
This way, the output I got was - all lines are printed but the last line gets printed twice.
So,
We understood that data is being read correctly and stored in statement.
This raises 2 questions. One is your question, other is why last line is printed twice.
To answer your question exactly, in every loop iteration, you're reading the text completely into statement. You're overwriting existing value. So whatever value you read last is only stored.
Once you fix that, you might come across the second question. It's very common and I myself came across that issue long back. So I'm gonna answer that as well.
Let's say your file has 3 lines:
line1
line2
line3
Initially your file control (pointer) is at the beginning, exactly where line 1 starts. After iterations when it comes to line3, we know it's last line as we input the data. But the loop control doesn't know that. For all it knows, there could be a million more lines. Only after it enters the loop condition THE NEXT TIME will it come to know that the file has ended. So the final value will be printed twice.

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;
}

searching a name in the csv file on C++

I am a young programmer who is trying to learn c++. i have a working csv.file. but i want to search for a specific number assigned to the name and then displays the name of what i'm looking for. i have the file here:
1,Bulbasaur,grass
2,Ivysaur, grass
3,Venusaur, grass
4,Charmander, fire
5,Charmeleon, fire
6,Charizard, fire
7,Squirtle, water
8,Wartortle, water
9,Blastoise, water
Code
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream ip("pokedex.csv");
string pokedexnum[9];
string pokemonName[9];
string pokemonType[9];
cout<<"please enter a pokemon number:"<<" ";
cin>>pokemonType[0];
while (ip.good()){
getline( ip, pokedexnum[0]);
getline( ip, pokemonName[0]);
getline( ip, pokemonType[0]);
}
cout<<"the pokemon that is:"<< " "<<pokedexnum[0]<< "is the pokemon called:"<< pokemonName[0];
ifstream close("pokedex.csv");
return 0;
}
when it runs
please enter a pokemon number: 1
the pokemon that is: is the pokemon called:8,Wartortle, water
could you please point out what i am doing wrong?
Among the issues in this code:
You're not using std::getline correctly for comma-separated data. The result is each pass is consuming three lines from your input file; not three values from each line.
You're also not using ip.good() correctly as a while-condition.
You're retaining your test value in the array, which will be overwritten on the first iteration pass, so it is lost.
You're ignoring potential IO failures with each std::getline invoke.
You're overwriting slot-0 in your arrays with each loop iteration.
Minor, ifstream close("pokedex.csv"); clearly isn't doing what you think it is. That just creates another fstream object called close on the given file name.
The later may be intentional for now, but clearly broken in the near future.
In reality, you don't need arrays for any of this. All you're doing is reading lines, and seem to want to test the input number against that of the CSV data first column, reporting the line that you find, then ending this.
So do that:
Read the input value to search for.
Open the file for scanning.
Enumerate the file one line at a time.
For each line from (3), use a string stream to break the line into the comma separated values.
Test the id value against the input from (1). If the same, report the result and break the loop; you're done.
The result is something like this:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
int main()
{
std::cout<<"please enter a pokemon number: ";
long num;
if (std::cin >> num && num > 0)
{
std::ifstream ip("pokedex.csv");
std::string line;
while (std::getline(ip, line))
{
std::istringstream iss(line);
std::string id, name, skill;
if (std::getline(iss, id, ',') &&
std::getline(iss, name, ',') &&
std::getline(iss, skill))
{
char *endp = nullptr;
long n = std::strtol(id.c_str(), &endp, 10);
if (id.c_str() != endp && n == num)
{
std::cout << "The pokemon that is: " << num << " is called: " << name << '\n';
break;
}
}
}
}
}
Admittedly untested, but it should work.
Whether you want to store the items in arrays at this point is entirely up to you, but it isn't needed to solve the somewhat abstract problem you seem to be attempting, namely finding the matching line and reporting the name from said-same. If you still want to store them in arrays, I suggest you craft a structure to do so, something like:
struct Pokemon
{
int id;
std::string name;
std::string skill;
};
and have a single array of those, rather than three arbitrary arrays that must be kept in sync.
Four issues jump out at me:
You store the user's input into pokemonType, but then also use pokemonType for reading data from your CSV file. The file input is going to overwrite the user input.
Your file input loop always references index 0. All of the lines from your data file are going into element 0. That's the main reason that even if the user inputs 1, the output is from the last line of the data file.
Your file reading loop is structured like you want to put one part of each data line into a different array, but what you've written actually reads three lines on every iteration, storing those lines into the three different arrays.
This isn't affecting your output, but the code ifstream close("pokedex.csv"); is written like you want to close the file stream you opened, but I do believe what this line actually does is create a new ifstream called close, and opens pokedex.csv attached to it. In other words, it's just like your other line ifstream ip("pokedex.csv"); but with close as the variable name instead of ip.
You are going to want to look into something called "string tokenization". Start with some web searches, apply what you read about to your code, and of course if you hit another snag, post a new question here to Stack Overflow, showing (as you did here) what you tried and in what way it isn't working.
Elaborating on #3, here's what how your data file is being read:
at the end of the 1st iteration of the file-reading loop, ...
pokedexnum[0] is "1,Bulbasaur,grass"
pokemonName[0] is "2,Ivysaur, grass"
pokemonType[0] is "3,Venusaur, grass"
at the end of the 2nd iteration of the file-reading loop, ...
pokedexnum[0] is "4,Charmander, fire"
pokemonName[0] is "5,Charmeleon, fire"
pokemonType[0] is "6,Charizard, fire"
at the end of the 3rd iteration of the file-reading loop, ...
pokedexnum[0] is "7,Squirtle, water"
pokemonName[0] is "8,Wartortle, water"
pokemonType[0] is "9,Blastoise, water"
And that's why
<< "is the pokemon called:"<< pokemonName[0];
outputs
is the pokemon called:8,Wartortle, water

Editing a text file

I want to edit a text file, but I'm stuck in finding the correct functions or methods to do so.
So far I'm able to open a text file and look for a certain string, but I have no idea on how to move the cursor, add or replace information, steps 4 - 7 in my pseudocode shown below.
Can you provide some guidance? Which functions should I use (in case they already exist)?
A sample 'easy' code would be appreciated as well.
Pseudocode:
1. Open file.
2. While not eof
3. Read file until string "someString" is found.
4. Position the cursor at the next line (to where the someString was found).
5. If "someString" = A go to step 6. Else go to step 7.
6. Replace the information in whole line with "newString". Go to step 8.
7. Add new information "newString_2", without deleting the existing.
8. Save and close the text file.
Thanks.
I would recommend to put the getline command into the while loop because then it won't stop only because of EOF but when getline is not able to read anymore.
Like when the error bad occurs (which happens when someone deleted the file while your program was reading it).
It seems like you want to search inside a string, so "find" might be quite helpful.
#include <iostream>
#include <fstream>
#include <string>
int main (){
std::fstream yourfile;
std::string line, someString;
yourfile.open("file.txt", ios::in | ios::app); //The path to your file goes here
if (yourfile.is_open()){ //You don't have to ask if the file is open but it's more secure
while (getline(line)){
if(line.find(someString) != string::npos){ //the find() documentation might be helpful if you don't understand
if(someString == "A"){
//code for replacing the line
}
else{
yourfile << "newString_2" << endl;
}
} //end if
} //end while
} //end if
else cerr << "Your file couldn't be opened";
yourfile.close();
return 0;
}
I can't tell you how to replace a single line in a text file but I hope you can work with that little I can give you.
This should be a good start:
// basic file operations
#include <string>
#include <fstream>
int main ()
{
std::fstream myfile;
std::string line;
while (!myfile.eof())
{
std::getline(myfile,line); // Check getline() doc, you can retrieve a line before/after a given string etc.
//if (line == something)
//{
// do stuff with line, like checking for content etc.
//}
}
myfile.close();
return 0;
}
More informations here