The following code is supposed to get a text file and read all its lines and print them put on console but although it properly saves the fname, it won't do anything after that. I appreciate if you could let me know what the problem is.
EDIT: To be more accurate, I will eventually want to call a few functions inside the else block but I first need to figure out why my program doesn't get to that point.
int main()
{
string fname = "", line, content;
ifstream ifs; // input file stream
string command = "";
int k;
cout << "---- Enter your command and the file name : ";
while (getline(cin, line)){
int i = 0;
for (i = 0; i<line.length(); i++) {
command += line[i];
if (line[i] == ' ')
{
break;
}
}
for (int j = i + 1; j<line.length(); j++)
{
fname += line[j];
}
cout << command;
}
if (command == "exit ")
{
exit(EXIT_SUCCESS);
}
// tries to open the file whose name is in string fname
ifs.open(fname.c_str());
if (ifs.fail()) {
cerr << "ERROR: Failed to open file " << fname << endl;
ifs.clear();
}
else { //do getline here to read content
while (getline(ifs, content))
{
cout << "Content " << k++ << " : " << content << endl;
//Call functions here later
}
}
ifs.close(); // always remember to close it
cout << "---- Enter another file and command name : ";
}
Got it sorted out myself. I was closing the while loop too early. It has to be closed after ifs.close(); instead.
Related
i was trying to find a way to check two different files and get, from the second, all lines that aren't in the first.. but does all the opposite.
I tried the possible to solve this but nothing...
This is the code:
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
stringstream buffer;
buffer << "C:\\Users\\" << username << "\\Desktop\\";
stringstream buffer2;
buffer2 << "C:\\Users\\" << username << "\\Desktop\\Legit.txt";
stringstream buffer3;
buffer3 << "C:\\Users\\" << username << "\\Desktop\\Unlegit.txt";
stringstream buffer4;
buffer4 << "C:\\Users\\" << username << "\\Desktop\\result.txt";
string results = buffer4.str();
int offset;
int num;
num = 1;
string search;
string linea;
string legit;
string unlegit;
string line;
cout << "Is the Legit.txt file at '" << buffer.str() << "'? [Y/N]: ";
cin >> legit;
if (legit == "Y" || legit == "y"){
}else if(legit == "N" || legit == "n"){
return 0;
}else{
cout << "\n.";
return 0;
}
string legitfile = buffer2.str();
cout << "\nIs the Unlegit.txt file at '" << buffer.str() << "'? [Y/N]: ";
cin >> unlegit;
if (unlegit == "Y" || unlegit == "y"){
}else if(unlegit == "N" || unlegit == "n"){
return 0;
}else{
cout << "\n";
return 0;
}
string unlegitfile = buffer3.str();
ifstream file(legitfile.c_str());
if(file.is_open()){
while(getline(file, line)){
ifstream MyFile(unlegitfile.c_str());
if(MyFile.is_open()){
while(!MyFile.eof()){
getline(MyFile,linea);
if((offset = linea.find(line, 0)) != string::npos) {
cout << "\n[" << num << "]" << " Word Found: " << line << "\n";
num++;
fstream result(results.c_str());
result << line << "\n";
result.close();
}
}
MyFile.close();
}
}
file.close();
return 0;
}else{
cout << "\nThe file '" << legitfile << "' does not exist.";
cout << "\nThe file '" << unlegitfile << "' does not exist.";
}
}
As i said, This code checks which words are equals in both (first & second) files and, once found, writes them to a third file, there is a way to do the opposite (check the two files and get the words that aren't equals)? Thank you so much!
I'm new, both in the forum and in C++, sorry if I make any mistakes. (sorry for my bad english too).
The classic solution to this sort of problem is to use a hash table collection to represent all the words in the first file. Then while iterating items from the second file, consult the set constructed of the first file. In C++, the std::unordered_set will do fine.
#include <unordered_set>
using namespace std;
unordered_set<string> firstFileSet;
unordered_set<string> missingFromSecondFileSet;
string line;
while(!firstfile.eof())
{
getline(firstfile,line);
firstFileSet.insert(line);
}
Then for each word in the second file, use a second set collection to keep track of what words are missing.
while(!secondfile.eof())
{
getline(secondfile,line);
if (firstFileSet.find(line) != firstFileSet.end())
{
missingFromSecondFileSet.insert(line);
}
else
{
firstFileSet.erase(line);
}
}
After the above runs, firstFileSet contains all the lines in the first file that were not present in the second. missingFromSecondFileSet contains all the lines in the second file that were not in the first:
for (auto &s : firstFileSet)
{
cout << s << " was in the first file, but not the second" << endl;
}
for (auto &s : missingFromSecondFileSet)
{
cout << s << " was in the second file, but not the first" << endl;
}
There is a program called diff on linux which does just what you are looking to do in C++.
It is written in C so you can just copy its source code =P
for (;; cmp->file[0].buffered = cmp->file[1].buffered = 0)
{
/* Read a buffer's worth from both files. */
for (f = 0; f < 2; f++)
if (0 <= cmp->file[f].desc)
file_block_read (&cmp->file[f],
buffer_size - cmp->file[f].buffered);
/* If the buffers differ, the files differ. */
if (cmp->file[0].buffered != cmp->file[1].buffered
|| memcmp (cmp->file[0].buffer,
cmp->file[1].buffer,
cmp->file[0].buffered))
{
changes = 1;
break;
}
/* If we reach end of file, the files are the same. */
if (cmp->file[0].buffered != buffer_size)
{
changes = 0;
break;
}
}
Taken from ftp://mirrors.kernel.org/gnu/diffutils/diffutils-3.0.tar.gz > src/analyze.c
I am a university student and recently started programming on C++, I am currently having an issue reading in a string using a stringstream.
I am reading information from a .csv file and storing the information in a class, what is puzzling me the most is that my code works perfectly for the first line of my .csv file but not for the second.
This is my class:
class Player {
public:
string name;
int points = 0;
int gamesPlayed = 0;
int todaysPoints = 0;
int timesPresident = 0;
int timesScum = 0;
char playing = 'n';
};
This is how my .csv file is formatted:
Name;Points;Games Played;Times President;Times Scum
Grace;0;0;0;0
Gabriel;0;0;0;0
And this is how I am reading it:
int readInPlayersList(Player playersList[], string filename) {
listIn.open(filename);
string line;
istringstream fixedLine;
int i = 0;
int j;
getline(listIn, line); //first line doesn't matter
while (getline(listIn, line)) {
if (listIn.eof()) { break; }
j = 0;
while (line[j]) {
if (line[j] == ';') { //swapping ; by space to read in easily
line[j] = ' ';
}
++j;
}
fixedLine.str(line);
cout << "Before reading, line = " << line << endl;
fixedLine >> playersList[i].name >> playersList[i].points >> playersList[i].gamesPlayed >> playersList[i].timesPresident >> playersList[i].timesScum;
cout << "After readng -> " << playersList[i].name << " " << playersList[i].points << " " << playersList[i].gamesPlayed << " " << playersList[i].timesPresident << " " << playersList[i].timesScum << endl; //testing output
++i;
}
return i;
listIn.close();
}
As you can see, in order to find out what's wrong, I output what's in the line before reading into the class, and then I output the class members, for the first line, it reads it perfectly but not for the second and any other thereafter... See output below:
I really want to know what I am doing wrong here, appreciate any help, cheers!
Gabriel Groff
I'm working on a C++ project where I need to backup a data file after creating it within the same program. I have already created the data file and have successfully written text to it, however, when I've tried to backup the same file using the function I've written, it won't work.
Here is some context followed by the function:
The filename I created is named contactList.ext (.ext so it's created in the current directory). When prompted for the filename in this program I type in contactList and it opens successfully, however, the only problem I'm having is that it won't backup the file. I'm trying to back it up this way: newFileName = (fileName + ".bak");
I don't know what other way there is to backup a file using c++. Any help is greatly appreciated!
void backupDataFile() {
string fileName;
string newFileName;
string line;
int contactListSize = 10, i = 0;
string contacts[contactListSize];
char userResponse;
fstream inFile, outFile;
cout << "\nEnter the name of the file you want to backup: ";
cin >> fileName;
inFile.open(fileName.c_str()); //attempts to open file
//file fails to open
if (inFile.fail()) {
cout << "\nThe file " << fileName << " was not opened successfully."
<< "\n Please check that the file currently exists.\n";
exit(1);
}
//read and display contents of file & assign each line to an array
cout << "\nThe following is the contents of " << fileName << ":\n\n";
while(getline(inFile, line)) {
cout << line << endl;
contacts[i] = line; //assigns each line to an array position
i++;
}
inFile.close(); //closes existing file allowing the opening of a new file
//verify user wishes to backup file
cout << "\nWould you like to backup this file? <y/n>: ";
cin >> userResponse;
if (userResponse == 'y') {
newFileName = (fileName + ".bak"); //assigns name of backup file
outFile.open(newFileName.c_str()); //attempts to open backup file
//file fails to create
if (outFile.fail()) {
cout << "\nThe file " << fileName << " did not backup successfully.";
exit(1);
}
///fix hereafter
else { //writes contents from contactList.ext to contactList.bak
while (i < 10) {
cout << contacts[i] << endl; //writes each contact into new file
i++;
}
//for (int j = 0; j < 10; j++) {
// outFile << contacts[j] << endl;
}
outFile.close(); //closes file
cout << "\nThe file " << fileName << " has been backed-up successfully."
<< "\nThe backup file is named " << newFileName;
}//end outer-if
else
cout << "\nYou will be directed back to the Main Menu.";
}
Your problem lies within these two sections.
while (i < 10) {
cout << contacts[i] << endl; //writes each contact into new file
i++;
}
//for (int j = 0; j < 10; j++) {
// outFile << contacts[j] << endl;
That for loop should not be commented out, you're only writing to the console (with cout), when you need to be writing to the outfile.
You also need to specify ios::out when calling outFile.out().
outFile.open(newFileName.c_str(),ios::out)
As stated by the other poster, you aren't actually running the code that outputs to the file
//outFile << contacts[j] << endl;
However another problem I see is that you output in a loop so long as i is less than 10. This is fine, but you didn't set i back to 0 after counting the number of lines when reading the file! That means that your
while(i < 10) {
loop never runs :)
I need to assign values to variables in C file by reading an excel sheet. I have written a code but only the last variable has been assigned a value since I have used for loop.It is overwriting the values assigned to the previous variables as I am creating a different output file after assigning values.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string s1, s2, s3,s4;
string filename, text, line;
string cfilename,funcname, signal, value;
int i , k , m;
cout << "Enter excel filename" << endl;
cin >> filename;
cout << "How many lines of text are in the file?" << endl;
cin >> m;
fstream file(filename);
if (!file) {
cerr << "No such file exists." << endl;
exit(1);
}
if (file.is_open()) {
while (file.eof()==0){
for (k = 0; k < m; k++) { //Loops for as many lines as there are in the file
for (i = 0; i < 4; i++) { //Loops for each comma-separated word in the line
if (i == 0){
getline(file, text, ',');
cfilename=text;
cout << cfilename << '\t';}
else if (i == 1){
getline(file, text, ',');
funcname=text;
cout << funcname << '\t';}
else if (i == 2){
getline(file, text, ',');
signal=text;
cout << signal << '\t';}
else if (i == 3){
getline(file, text, '\n');
value=text;
cout << value << '\n';}
}
string s1=signal,s2=value;
s2 = s2 + "; //";
int offset, inset;
string line;
string search=s1;
fstream cfile(cfilename);
fstream fileOutput;
fileOutput.open("output.c");
if(cfile.is_open() && fileOutput.is_open()) {
while(!cfile.eof()) {
getline(cfile, line);
if ((offset = line.find(funcname)) != string::npos){
cout << "found: " << funcname << endl;
string line1;
fileOutput << line << '\n';
skip:
while(getline(cfile,line1)){
if((inset=line1.find(search, 0)) !=string::npos){
cout<<"found: " << search << endl;
string s3 = s1+ "=" +s2;
//cout<<s3;
line1.replace( inset, inset+s1.size(), s3 );}
fileOutput << line1 << '\n';
goto skip;
}
getchar(); }
fileOutput << line << '\n'; }
cfile.close();
fileOutput.close();
}
}
}
}
file.close();
getchar();
return 0;
}
I am trying to search a function first and then variables inside that function.
Need some help here.
I'm not sure it's this the problem but... I thing the while () is too much.
when you have readed the m lines of the file, your
while (file.eof()==0)
result true because you haven't read nothing past the end of file.
So you read other m lines (failing but without controls about the success of the reading).
EDIT: I think you should write something like
cout << "Enter excel filename" << endl;
cin >> filename;
fstream file(filename);
if (!file) {
cerr << "No such file exists." << endl;
exit(1);
}
while ( getline(file, cfilename, ',') && getline(file, funcname, ',')
&& getline(file, signal, ',') && getline(file, value, '\n')) {
cout << cfilename << '\t' << funcname << '\t' << signal << '\t'
<< value << '\n';
string s1=signal,s2=value;
[...]
The program does exactly what you asked it to do:
you read a CSV file (excel format is binary!) line by line
for each line in csv:
you erase the output file because you open a fstream without specifying ios::ate
search something in a source file and write to the output file.
As you erase the output file at every new line from the input CSV file, you cannot get more than the last operation.
It would be much simpler if you opened the output file once outside of the loop.
And... while (file.eof() == 0) is an anti-pattern. You look whether you have reached end of file before trying to read a line, and then read 4 values when the first getline have set the eof flag. You must test for eof immediately after a read and not before...
Something is definitely wrong with my loop because after reading and executing the first line the programs ends.
if (infile.is_open())
{
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
cout<< "Output filename: ";
cin>>filename;
outfile.open(filename.c_str());
while(getline(infile,input))
{
string output = "";
for(int x = 0; x < input.length(); x++)
output += cipher(input[x]);
cout<<output<<endl;
outfile<<output;
}
}
Any suggestions on how to make this work?
EDIT
Followed the suggestions and got this:
if (infile.is_open()) {
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
if (!infile.is_open())
{
std::cout << "Failed to open the input file." << std::endl;
return -1;
}
cout<< "Output filename: ";
cin>>filename;
outfile.open(ofilename.c_str());
if (!outfile.is_open())
{
std::cout << "Failed to open the output file." << std::endl;
return -1;
}
while(getline(infile,line)){
string output = "";
for(int x = 0; x < input.length(); x++) {
output += cipher(input[x]);
}
}
BUT it still reads only the first line...everything else is working perfectly fine....just can't read anything beyond the first line..
It seems that you misunderstood the point of the fstream's is_open() method, since this code:
if (infile.is_open())
{
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
...
}
checks whether the infile has been successfully opened (i.e. if either a previous call to member open succeeded or if the object was successfully constructed using the parameterized constructor,
and close has not been called since) and in case it is open it retrieves the name of the input file from cin and opens the file.
Good start would be the program that reads from the input file line by line and writes these lines to the output file without processing them:
// retrieve the name of the input file and open it:
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
if (!infile.is_open())
{
std::cout << "Failed to open the input file." << std::endl;
return -1;
}
// retrieve the name of the output file and open it:
cout << "Output filename: ";
cin >> filename;
outfile.open(filename.c_str());
if (!outfile.is_open())
{
std::cout << "Failed to open the output file." << std::endl;
return -1;
}
std::string line;
while(getline(infile,line))
{
std::cout << line << std::endl;
outfile << line;
}
So I suggest this.
Write char cipher(char ch) to return enciphered input for anything. if you don't want to encipher whitespace, then don't. But always return the enciphered character or unmodifed character.
Use std::transform , std::istream_iterator , and std::ostream_iterator to transform your input and output files.
Check your file states at the correct times.
An example appears below:
#include <iostream>
#include <fstream>
#include <iteraor>
#include <string>
using namespace std;
char cipher(char ch)
{
if (std::isalpha(ch))
{
// TODO: change ch to whatever you want here.
}
// but always return it, whether you changed it or not.
return ch;
}
int main()
{
int res = EXIT_SUCCESS;
string in_filename, out_filename;
cout << "Input filename: ";
cin >> in_filename;
cout << "Output filename: ";
cin >> out_filename;
// don't skip whitespace
ifstream infile(in_filename);
ofstream outfile(out_filename);
if ((infile >> noskipws) && outfile)
{
std::transform(istream_iterator<char>(infile),
istream_iterator<char>(),
ostream_iterator<char>(outfile),
cipher);
}
else
{
perror("Failed to open files.");
res = EXIT_FAILURE;
}
return res;
}