i want to receive an input from user and search a file for that input. when i found a line that includes that specific word, i want to print it and get another input to change a part of that line based on second user input with third user input. (I'm writing a hospital management app and this is a part of project that patients and edit their document).
i completed 90 percent of the project but i don't know how to replace it. check out following code:
#include <iostream>
#include <stream>
#include <string.h>
#include <string>
using namespace std;
int main(){
string srch;
string line;
fstream Myfile;
string word, replacement, name;
int counter;
Myfile.open("Patientlist.txt", ios::in|ios::out);
cout << "\nEnter your Name: ";
cin.ignore();
getline(cin, srch);
if(Myfile.is_open())
{
while(getline(Myfile, line)){
if (line.find(srch) != string::npos){
cout << "\nYour details are: \n" << line << endl << "What do you want to change? *type it's word and then type the replacement!*" << endl;
cin >> word >> replacement;
}
// i want to change in here
}
}else
{
cout << "\nSearch Failed... Patient not found!" << endl;
}
Myfile.close();
}
for example my file contains this line ( David , ha , 2002 ) and user wants to change 2002 to 2003
You cannot replace the string directly in the file. You have to:
Write to a temporary file what you read & changed.
Rename the original one (or delete it if you are sure everything went fine).
Rename the temporary file to the original one.
Ideally, the rename part should be done in one step. For instance, you do not want to end up with no file because the original file was deleted but the temporary one was not renamed due to some error - see your OS documentation for this.
Here's an idea:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
using namespace std;
void replace(string& s, const string& old_str, const string& new_str)
{
for (size_t off = 0, found_idx = s.find(old_str, off); found_idx != string::npos; off += new_str.length(), found_idx = s.find(old_str, off))
s.replace(found_idx, old_str.length(), new_str);
}
int main()
{
const char* in_fn = "c:/temp/in.txt";
const char* bak_fn = "c:/temp/in.bak";
const char* tmp_fn = "c:/temp/tmp.txt";
const char* out_fn = "c:/temp/out.txt";
string old_str{ "2002" };
string new_str{ "2003" };
// read, rename, write
{
ifstream in{ in_fn };
if (!in)
return -1; // could not open
ofstream tmp{ tmp_fn };
if (!tmp)
return -2; // could not open
string line;
while (getline(in, line))
{
replace(line, old_str, new_str);
tmp << line << endl;
}
} // in & tmp are closed here
// this should be done in one step
{
remove(bak_fn);
rename(in_fn, bak_fn);
remove(out_fn);
rename(tmp_fn, in_fn);
remove(tmp_fn);
}
return 0;
}
One possible way:
Close the file after you read it into "line" variable, then:
std::replace(0, line.length(), "2002", "2003")
Then overwrite the old file.
Note that std::replace is different from string::replace!!
The header is supposed to be <fstream> rather than <stream>
you can't read and write to a file simultaneously so I have closed the file after reading before reopening the file for writing.
instead of updating text inside the file, your line can be updated and then written to file.
#include <iostream>
#include <fstream>
#include <string.h>
#include <string>
using namespace std;
int main(){
string srch;
string line, line2;
fstream Myfile;
string word, replacement, name;
int counter;
Myfile.open("Patientlist.txt", ios::in);
cout << "\nEnter your Name: ";
cin.ignore();
getline(cin, srch);
if(Myfile.is_open())
{
while(getline(Myfile, line)){
if (line.find(srch) != string::npos){
cout << "\nYour details are: \n" << line << endl << "What do you want to change? *type it's word and then type the replacement!*" << endl;
cin >> word >> replacement;
int index = line.find(word);
if (index != string::npos){
Myfile.close();
Myfile.open("Patientlist.txt", ios::out);
line.replace(index, word.length(), replacement);
Myfile.write(line.data(), line.size());
Myfile.close();
}
}
// i want to change in here
}
}else
{
cout << "\nSearch Failed... Patient not found!" << endl;
}
}
Related
This question already has answers here:
How can I read and parse CSV files in C++?
(39 answers)
Closed 5 years ago.
I need a help with my code. I am trying to read txt file and then I want to put each line into difference vector. For example, I have a file like this.
123, 123, 431, 5123, 12312
25316, 64234, 1231, 124123
I want to put the first line to the first vector. 123|123|431|
and the second vector. 25316|64234|
I already tried seekg. But, it doesn't work. What is the best way to do it? Later, I will use these vector with Linkedlist.
Here is my code.
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;
int main()
{
string fname;
cout << "Please enter file name!" << endl;
cin >> fname;
string line;
fstream myfile;
myfile.open(fname);
if (myfile.is_open())
{
myfile.seekg(0, ios_base::end);
int length = myfile.tellg();
cout << length <<endl;
}
else
{
cout << "Unable to open your file!" << endl;
}
}
First, on handling the lines separately:
As explained by others you should not use std::basic_istream::seekg(). It works with absolute positions in the streambuf and would require way more code for your use-case than necessary (you would have to find newlines in the stream, split and so on).
Use getline().
Example:
if (myfile.is_open())
{
short line_num = 1;
for (std::string line; std::getline(myfile, line); ) {
cout << "Line number: " << line_num << " Value: " << line << std::endl;
line_num++;
}
}
Output:
mindaugasb#c_cpp:~/workspace/StackOverflow/ReadingAFileLineByLine $ ./r2v.exe
Please enter file name!
f
Line number: 1 Value: 123, 123, 431, 5123, 12312
Line number: 2 Value: 25316, 64234, 1231, 124123
Second on pushing the lines, item at a time, to a vector:
I will assume there will be two vectors, for the two lines in the input file. If there are more lines, you will need to create more vectors, possibly by implementing a function that will accept as string (obtained from the input file) and return a vector in the form you want it. Example:
vector<string> line2Vec(string line)
{
char * tokens;
char * line_chararr = const_cast< char *>(line.c_str());
tokens = strtok(line_chararr, ", ");
vector<string> vs;
while (tokens != NULL)
{
vs.push_back(tokens);
tokens = strtok (NULL, ", ");
}
return vs;
}
Attention - I do not say that this is perfect Cpp code or a perfect solution to your problem. However it is A solution to how I understood the problem based on what was written. Here is the full version to play around with:
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <sstream>
#include <vector>
#include <string.h>
using namespace std;
vector<string> line2Vec(string line)
{
cout << line << endl;
char * tokens;
char * line_chararr = const_cast< char *>(line.c_str());
tokens = strtok(line_chararr, ", ");
vector<string> vs;
while (tokens != NULL)
{
vs.push_back(tokens);
tokens = strtok (NULL, ", ");
}
return vs;
}
int main()
{
string fname;
cout << "Please enter file name!" << endl;
cin >> fname;
fstream myfile;
myfile.open(fname);
if (myfile.is_open())
{
for (std::string line; std::getline(myfile, line); ) {
line2Vec(line);
}
}
else
{
cout << "Unable to open your file!" << endl;
}
}
I want to read from a file.txt that looks like this:
process_id run_time
T1 23
T2 75
Read each line and store integers of run time (tab separation)in an array
My problem now is to read the content of the file .. and how to get the integer after the tab separation?
thanks
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main ()
{
int process_id[100];
int run_time[100];
int arrival_time[100];
char quantum[50];
int switching;
char filename[50];
ifstream ManageFile; //object to open,read,write files
cout<< "Please enter your input file";
cin.getline(filename, 50);
ManageFile.open(filename); //open file using our file object
if(! ManageFile.is_open())
{
cout<< "File does not exist! Please enter a valid path";
cin.getline(filename, 50);
ManageFile.open(filename);
}
while (!ManageFile.eof())
{
ManageFile>>quantum;
cout << quantum;
}
//ManageFile.close();
return 0;
}
use C++, not C
don't use std::cin.getline, use std::getline (it works with std::string and is safer)
use a vector instead of hard-dimensioned arrays
use a vector of struct instead of "corresponding arrays"
don't use while (!stream.eof())
Here's a sample that might be helpful:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
struct Record {
int process_id;
int run_time;
int arrival_time;
};
int main() {
std::vector<Record> records;
int switching;
std::string filename;
ifstream infile;
while (!infile.is_open()) {
cout << "Please enter your input file: ";
std::getline(std::cin, filename);
infile.open(filename); // open file using our file object
cout << "File cannot be opened.\n";
}
std::string quantum;
std::getline (infile, quantum); // skip header row
while (std::getline(infile, quantum)) {
// e.g.
Record current;
std::istringstream iss(quantum);
if (iss >> current.process_id >> current.run_time >> current.arrival_time)
records.push_back(current);
else
std::cout << "Invalid line ignored: '" << quantum << "'\n";
}
}
You can try something like this:
while (!ManageFile.eof())
{
quantum[0] = 0;
ManageFile>>quantum;
if (strcmp(quantum, "0") == 0 || atoi(quantum) != 0)
cout << quantum << endl;
}
Of course, you need to include in the head
Use function ignore from istream [http://www.cplusplus.com/reference/istream/istream/ignore/]
while (!ManageFile.eof())
{
std::string process_id;
int run_time;
ManageFile >> process_id;
ManageFile.ignore (256, '\t');
ManageFile >> run_time;
}
Using fscanf instead of ifstream can make the job a lot easier.
char str[100];
int n;
....
fscanf(FILE * stream,"%s %d", str, &n);
You will get the string in str and integer in n.
I wrote a quick C++ program that asks the user for a input text file and an output text file. The program is then supposed to number the lines in the file on the left margin. However, I cannot seem to get it working properly, it compiles fine but does not number the lines like it is supposed to. I believe it is a logical error on my part. I am also not too familiar with file i/o in C++ as I am just learning it now using old school textbooks.
Here is the file:
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include <cstdio>
using namespace std;
int main(void)
{int i = 0 , num = 1;
string inputFileName;
string outputFileName;
string s;
ifstream fileIn;
ofstream fileOut;
char ch;
cout<<"Enter name of input file: ";
cin>>inputFileName;
cout<<"Enter name of output file: ";
cin>>outputFileName;
fileIn.open(inputFileName.data());
fileOut.open(outputFileName.data());
assert(fileIn.is_open() );
assert(fileOut.is_open() );
while (!(fileIn.eof()))
{ch=fileIn.get();
if (ch=='\n') num++;
fileOut << num << "\n";
s.insert(i,1,ch); //insert character at position i
i++;
}
fileOut << s;
fileIn.close();
fileOut.close();
return 0;
}
If anyone could point me in thr right direction or give me some tips I would be eternally grateful.
int i = 0;
string line;
while (getline(infile, line))
{
outfile << (i++) << " " << line << "\n";
}
So I've been playing with code and I'm stuck with finding how to replace the line found. I'm able to find the name and add the 'new_gpa' to the section but it outputs the final result in the same file but without replacing the original score and name.
how could I remove the original line found along with the gpa? and also store the new values to the file.
cristian 2.1
rachel 3.0
name search: cristian
new file:
cristian 2.1
rachel 3.0
cristian 4.1
The code is below.
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <fstream>
#include <sstream>
#include <cstring>
using namespace std;
int main()
{
string name;
int offset;
string line;
ifstream read_file;
read_file.open("alpha.dat", std::ios_base::app);
cout << "Please enter your name: \n";
cin>> name;
if (read_file.is_open())
{
while(!read_file.eof())
{
getline(read_file,line);
if((offset = line.find(name)) != string::npos)
{
cout <<"the word has been found: \n";
//cout << line //example to display
//new code
istringstream iss ( line );
string thisname;
double gpa;
double new_gpa = 2.1;
if( iss >> thisname >> gpa)
{
if (thisname == name)
{
cout << name <<endl;
cout << gpa <<endl;
ofstream myfile;
myfile.open("alpha.dat",std::ios_base::app);
myfile << " \n" << name << " " << gpa+ new_gpa;
myfile.close();
read_file.close();
}
}
}
}
}
return 0;
}
You open file with std::ios_base::app, which means all you output operations are performed at the end of file, appending the content to the current file. But what you want to do is modify the data at the original place. So you should open file with std::ios_base::in, and function seekp can help you in the next step.
So I'm really stuck trying to figured this bug on the program that is preventing me from displaying the text of my program..
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <stdio.h>
using namespace std;
int main ()
{
ifstream infile;
ofstream offile;
char text[1024];
cout <<"Please enter the name of the file: \n";
cin >> text;
infile.open(text);
string scores; // this lines...
getline(infile, scores, '\0'); // is what I'm using...
cout << scores << endl; // to display the file...
string name1;
int name2;
string name3;
int name4;
infile >> name1;
infile >> name2;
infile >> name3;
infile >> name4;
cout << "these two individual with their age add are" << name2 + name4 <<endl;
// 23 + 27
//the result I get is a bunch of numbers...
return 0;
}
Is there any way cleaner or simple method i can used to display the file ?
All the method in the internet are difficult to understand or keep track due to
the file is open in loop..
I want a program that you type the name of the file and displays the file
the file will contain the following...
jack 23
smith 27
Also I need to obtain data from the file now I'm using the above code to obtain that information from the file...
loop is probably the best thing you can do.
so if you know the format you could simply do it like this
#include <iostream>
#include <fstream>
using namespace std;
int printParsedFile(string fileName) { // declaration of a function that reads from file passed as argument
fstream f; // file stream
f.open(fileName.c_str(), ios_base::in); // open file for reading
if (f.good()) { // check if the file can be read
string tmp; // temp variable we will use for getting chunked data
while(!f.eof()) { // read data until the end of file is reached
f >> tmp; // get first chunk of data
cout << tmp << "\t"; // and print it to the console
f >> tmp; // get another chunk
cout << tmp << endl; // and print it as well
} else {
return -1; // failed to open the file
}
return 0; // file opened and read successfully
}
you can call then this function for example in your main() function to read and display file passed as argument
int main(int argc, char** argv) {
string file;
cout << "enter name of the file to read from: "
cin >> file;
printParsedFile(file);
return 0;
}
I personally use stringstreams for reading one line at a time and parsing it:
For example:
#include <fstream>
#include <stringstream>
#include <string>
std::string filename;
// Get name of your file
std::cout << "Enter the name of your file ";
std::cin >> filename;
// Open it
std::ifstream infs( filename );
std::string line;
getline( infs, line );
while( infs.good() ) {
std::istringstream lineStream( line );
std::string name;
int age;
lineStream >> name >> age;
std::cout << "Name = " << name << " age = " << age << std::endl;
getline( infs, line );
}