How to get input file to go into an array - c++

I'm trying to get information from an input file into an output file, which I have done, but I can't figure out how to get the numbers from the file into an array and only output the numbers divisible by 7. I've been stuck for a few hours, please help.
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;
int main()
{
string ifilename, ofilename, line;
ifstream inFile, checkOutFile;
ofstream outFile;
char response;
// Input file
cout << "Please enter the name of the file you wish to open : ";
cin >> ifilename;
inFile.open(ifilename.c_str());
if (inFile.fail())
{
cout << "The file " << ifilename << " was not successfully opened." << endl;
cout << "Please check the path and name of the file. " << endl;
exit(1);
}
else
{
cout << "The file is successfully opened." << endl;
}
// Output file
char array[10];
int numberz = 0;
cout << "Please enter the name of the file you wish to write : ";
cin >> ofilename;
checkOutFile.open(ofilename.c_str());
if (!checkOutFile.fail())
{
cout << "A file " << ofilename << " exists.\nDo you want to continue and overwrite it? (y/n) : ";
cin >> response;
if (tolower(response) == 'n')
{
cout << "The existing file will not be overwritten. " << endl;
exit(1);
}
}
outFile.open(ofilename.c_str());
if (outFile.fail())
{
cout << "The file " << ofilename << " was not successfully opened." << endl;
cout << "Please check the path and name of the file. " << endl;
exit(1);
}
else
{
cout << "The file is successfully opened." << endl;
}
// Copy file contents from inFile to outFile
while (getline(inFile, line))
{
fscanf(ifilename, &array[numberz]);
cout << line << endl;
outFile << line << endl;
}
// Close files
inFile.close();
outFile.close();
} // main

I'd use boost::filesystem for that task.
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
namespace fs = boost::filesystem;
int main()
{
fs::path ifilename;
std::cout << "Input file: ";
std::cin >> ifilename;
fs::ifstream inFile{ifilename};
if ( inFile.fail() )
throw std::invalid_argument("Could not open file");
fs::path ofilename;
std::cout << "Output file: ";
std::cin >> ofilename;
if ( fs::exists(ofilename) )
{
std::cout << ofilename << " exists. Do you want to overwrite it? (y/n) ";
char response;
std::cin >> response;
if ( ! ( response == 'y' || response == 'Y' ) )
return 1;
}
fs::ofstream outFile{ofilename};
if ( outFile.fail() )
throw std::invalid_argument("Could not open file");
std::vector<std::string> array;
std::string line;
while ( std::getline(inFile, line) )
{
array.push_back( line );
std::cout << line << '\n';
outFile << line << '\n';
}
inFile.close();
outFile.close();
}

Related

Need loop to ask user to re enter the file name until correct

How am I able to fix the loop to ask the user to retype the filename over and over again if they type in the wrong file name?
using namespace std;
void get_input_file(ifstream &in_stream);
int main()
{
ifstream in_stream;
cout << "Welcome to the Test Grader." << endl;
get_input_file(in_stream);
}
void get_input_file(ifstream &in_stream) {
string file_name;
do {
cout << "Enter the file name you would like to import the data from: " << endl;
cin >> file_name;
in_stream.open(file_name.c_str()); //Opens the input file into the stream}
}
while (in_stream.fail()); {
cout << "Error finding file, try again.\n";
}
cout << "Testing: " << endl;
cout << file_name << endl;
}
maybe this:
using namespace std;
void get_input_file(ifstream &in_stream);
int main()
{
ifstream in_stream;
cout << "Welcome to the Test Grader." << endl;
get_input_file(in_stream);
}
void get_input_file(ifstream &in_stream)
{
string file_name;
do
{
cout << "Enter the file name you would like to import the data from: " << endl;
cin >> file_name;
in_stream.open(file_name.c_str()); //Opens the input file into the stream
if(in_stream.fail())
{
cout << "Error finding file, try again.\n";
continue;
}
break;
} while(true);
cout << "Testing: " << endl;
cout << file_name << endl;
}
I don't think your do while loop does what you'd like it to do.
After the semicolon your loop is over, hence the block behind it is not executed within the loop.
What I think you are looking for is something like this:
do {
cout << "Enter the file name you would like to import the data from: " << endl;
cin >> file_name;
in_stream.open(file_name.c_str()); //Opens the input file into the stream}
if(in_stream.fail()){
cout << "Error finding file, try again.\n";
}
} while (in_stream.fail());

Issue with saving an edited infile to an outfile in c++

Im having an issue with the last section of coding on here. The // Copy files from infile to outfile. The program transfers my infile which is simply a an 8 digit number , 20392207,splits it up into individual digits using the .at method; and is supposed to save that output to an outfile. I cant figure out how to save the output to the outfile. Any advice?
infile looks as follows
20392207
program output looks like this
The input number :20392207
The number 1:2
The number 2:0
The number 3:3
The number 4:9
The number 5:2
The number 6:2
The number 7:0
The number 8:7
outfile is supposed to look like the program out put, but instead just looks like an exact copy of the infile.
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
#include<cmath>
using namespace std;
int main()
{
string ifilename, ofilename, line, line2;
ifstream inFile, checkOutFile;
ofstream outFile;
char response;
int i;
// Input file
cout << "Please enter the name of the file you wish to open : ";
cin >> ifilename;
inFile.open(ifilename.c_str());
if (inFile.fail())
{
cout << "The file " << ifilename << " was not successfully opened." << endl;
cout << "Please check the path and name of the file. " << endl;
exit(1);
}
else
{
cout << "The file is successfully opened." << endl;
}
// Output file
cout << "Please enter the name of the file you wish to write : ";
cin >> ofilename;
checkOutFile.open(ofilename.c_str());
if (!checkOutFile.fail())
{
cout << "A file " << ofilename << " exists.\nDo you want to continue and overwrite it? (y/n) : ";
cin >> response;
if (tolower(response) == 'n')
{
cout << "The existing file will not be overwritten. " << endl;
exit(1);
}
}
outFile.open(ofilename.c_str());
if (outFile.fail())
{
cout << "The file " << ofilename << " was not successfully opened." << endl;
cout << "Please check the path and name of the file. " << endl;
exit(1);
}
else
{
cout << "The file is successfully opened." << endl;
}
// Copy file contents from inFile to outFile
while (getline(inFile, line))
{
cout << "The input number :" << line << endl;
for (i = 0; i < 8; i++)
{
cout << "The number " << i + 1 << ":";
cout << line.at(i);
cout << endl;
}
outFile << line << endl;
}
// Close files
inFile.close();
outFile.close();
} // main
Here we can see that outFile is only written to outside of the while loop:
while (getline(inFile, line))
{
cout << "The input number :" << line << endl;
for (i = 0; i < 8; i++)
{
cout << "The number " << i + 1 << ":";
cout << line.at(i);
cout << endl;
}
}
outFile << line << endl;
It has no chance of containing the same output as the console
Solution: Write inside the loop the same stuff that was written to the console:
while (getline(inFile, line))
{
cout << "The input number :" << line << endl;
outFile << "The input number :" << line << endl;
blah blah blah
}
But this looks like crap and a function makes like a better solution by eliminating duplication and upping re-usability.
void output(std::ostream & out,
const std::string & line)
{
out << "The input number :" << line << endl;
for (int i = 0; i < 8; i++)
{
out << "The number " << i + 1 << ":";
out << line.at(i);
out << endl;
}
}
and called:
while (getline(inFile, line))
{
output(cout, line);
output(outFile, line);
}
You need to write to outFile inside the while(getline(inFile, line)) loop.
[edit] see user4581301's answer for a more thorough treatment.

Selecting random words from an generating a sentence from an input file

I need to create a program that has 4 columns of words from an input file.
then randomly selects a word from each column and generates a sentence. The ultimate goal is to have a conversation that gets saved to the output file.
I've already created the code that reads the input file, and opens the output file to write on but i'm not sure how to select a word from a column and create the sentence, i'm guessing using an array would work but i'm not certain how to connect it with the file?
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;
int main()
{
string ifilename, ofilename, line;
ifstream inFile, checkOutFile;
ofstream outFile;
char response;
// Input file
cout << "Please enter the name of the file you wish to open : ";
cin >> ifilename;
inFile.open(ifilename.c_str());
if (inFile.fail())
{
cout << "The file " << ifilename << " was not successfully opened." << endl;
cout << "Please check the path and name of the file. " << endl;
exit(1);
}
else
{
cout << "The file is successfully opened." << endl;
}
// Output file
cout << "Please enter the name of the file you wish to write : ";
cin >> ofilename;
checkOutFile.open(ofilename.c_str());
if (!checkOutFile.fail())
{
cout << "A file " << ofilename << " exists.\nDo you want to continue and overwrite it? (y/n) : ";
cin >> response;
if (tolower(response) == 'n')
{
cout << "The existing file will not be overwritten. " << endl;
exit(1);
}
}
outFile.open(ofilename.c_str());
if (outFile.fail())
{
cout << "The file " << ofilename << " was not successfully opened." << endl;
cout << "Please check the path and name of the file. " << endl;
exit(1);
}
else
{
cout << "The file is successfully opened." << endl;
}
// Copy file contents from inFile to outFile
cout << "Hi, what's up? " << endl; // Pre-set opener
while (getline(inFile, line))
{
cout << line << endl;
outFile << line << endl;
}
// Close files
inFile.close();
outFile.close();
} // main
You can use a 2D vector of strings to store the words of the sentences and use a random number generator like rand to pick a particular row element from every column. Something like the following
vector<vector<string>> myConversationVector;
while (choice != "no")
{
std::cout << myConversationVector[rand() % 5][0] <<" "
<< myConversationVector[rand() % 5][1] <<" "
<< myConversationVector[rand() % 5][2] <<" "
<< myConversationVector[rand() % 5][3];
}

Output file keeps being created even when input file doesn't exist? ****EDIT****

I am trying to write a program that moves the first line of a file into a new file. My goal is for the new file to not be created if the input file does not exist. I get it to read .good() so I get the message that the input failed. However, I cannot get the new file to not be created.
Here is the code:
int main()
{
fstream inFile;
fstream outFile;;
string fileName("");
string destName("");
cout << "Please enter file name: ";
cin >> fileName;
cout << endl;
cout << "Please enter file name of destination: ";
cin >> destName;
cout << endl;
inFile.open(fileName, ios::in);
outFile.open(destName, ios::out);
getline(inFile, fileName);
if (inFile.good() != true) {
cout << "?Unable to input file!\n" << endl;
return 0;
}
else {
outFile << fileName << endl;
return 0;
}
if (outFile.good() == true) {
cout << "?File '" << destName << "' already exists!\n" << endl;
return 0;
}
inFile.close();
outFile.close();
return 0;
}
Can anybody help?
Thank you in advance.
Thank you for the help from earlier,
*****EDIT*****
I am curious now though. If the output file already exists, I want to make an error statement saying so. However, if the file exists or doesn't exist, I am still getting an error. I tried to move the outFile.open to the bottom so that the file is created before the check but it still says it already exists?
int main()
{
fstream inFile;
fstream outFile;;
string fileName("");
string destName("");
cout << "Please enter file name: ";
cin >> fileName;
cout << endl;
inFile.open(fileName, ios::in);
getline(inFile, fileName);
if (inFile.good() != true) {
cout << "?Unable to input file!\n" << endl;
return 0;
}
cout << "Please enter file name of destination: ";
cin >> destName;
cout << endl;
if (outFile.good() == true) {
cout << "?File '" << destName << "' already exists!\n" << endl;
return 0;
}
outFile.open(destName, ios::out);
outFile << fileName << endl;
inFile.close();
outFile.close();
return 0;
}
You need to move the open call of the output file to after the input file check.
Something like this:
int main()
{
fstream inFile;
fstream outFile;;
string fileName("");
string destName("");
cout << "Please enter file name: ";
cin >> fileName;
cout << endl;
cout << "Please enter file name of destination: ";
cin >> destName;
cout << endl;
inFile.open(fileName, ios::in);
getline(inFile, fileName);
if (inFile.good() != true) {
cout << "?Unable to input file!\n" << endl;
return 0;
}
outFile.open(destName, ios::out);
outFile << fileName << endl;`enter code here`
if (outFile.good() == true) {
cout << "?File '" << destName << "' already exists!\n" << endl;
return 0;
}
inFile.close();
outFile.close();
return 0;
}

Iterating through a text file and assigning variables for each line

having a difficult time finding a way to assign each line of the text file being read to a different variable, i commented above the variables displaying how a line from the text file displaying that variable would look. I want to know what way i can use a forloop to be able to iterate through the entire text file and store data to each of the variables I commented above based on the type of data it needs to store. The three sets of variables all have to be stored by species and in a way they can be manipulated. How can i split up a vector into a set of three variables?
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string getInputFileName()
//retrieves the inputfile
{
string fileName;
ifstream inputfile;
//prompting user for filename to be opened
cout << "Enter the file name to be opened: ";
cin >> fileName;
//opening the file for input
inputfile.open(fileName, ios::in);
//checks to see if writing the input file failed
if (inputfile.fail())
{
cout << "Opening file..." << fileName;
cout << "\n";
cout << "The " << fileName << "could not be opened! \n";
cout << "1. Check if file exists. \n";
cout << "2. Check file path. \n;";
}
else
{
cout << "File: " << fileName << " was successfully opened!" << endl;
return fileName;
}
}
string getOutputFileName()
//retrieves the inputfile
{
string fileName;
ofstream outputfile;
//prompting user for filename to be opened
cout << "Enter the file name to be opened: ";
cin >> fileName;
//opening the file for input
outputfile.open(fileName, ios::in);
//checks to see if writing the input file failed
if (outputfile.fail())
{
cout << "Opening file..." << fileName;
cout << "\n";
cout << "The " << fileName << "could not be opened! \n";
cout << "1. Check if file exists. \n";
cout << "2. Check file path. \n;";
}
else
{
cout << "File: " << fileName << " was successfully opened!" << endl;
return fileName;
}
}
int main()
{
//opens clasfication file
ifstream inputFile(getInputFileName());
//declaring year and numberOfSpecies
int year, numberOfSpecies;
string line;
if (inputFile.is_open())
{
//year of file
inputFile >> year;
//echo for year
cout << year << endl;
//number of species of file
inputFile >> numberOfSpecies;
//echo for number of species
cout << numberOfSpecies << endl;
string line;
//variables i need to assign line by line and be able to manipulate
//region of species would look like this in text file: 84
//nameOfspecies would like like this in the text file: Spotted Gecko
//regionSightings would look like this in the text file: 84 95 30 25
vector<string> linesOfData;
for (int i = 0; (!inputFile.eof()) || (i <= numberOfSpecies) ; i++)
{
getline(inputFile, line, '\n');
linesOfData.push_back(line);
//echo vector!
cout << linesOfData[i] << "\n";
}
ofstream outputFile(getOutputFileName());
}
return 0;
}
Pseudo code for your requirements. You will have to fill in the code and do the required testing.
I have used similar logic many times for my requirements. I see this to be more maintainable and scalable.
class spotted_species{
private:
int first_val[];
string species_name;
int locations[];
// Private methods
private:
void assign_species_firstVal (String first_line){
Assign the first line after performing required transformations;
}
int assign_species_name (String Second_Line){
if (the species name exists in predefined array or file) {
assign the name;
}
else {
return -1; // to ignore all 3 lines.
}
}
void assign_species_locations (String third_line){
tokenize by space
convert each token to int and assign. hardly 2 lines code.
}
// Public methods
public:
void show_species(){
std::cout<< "First val";
std::cout<< "Species name";
std::cout<< "Spotted locations";
}
int init(String firstline, String secondline, String ThirdLine){
assign_species_firstVal(firstline);
int status = assign_species_name (secondline);
if (status) {
assign_species_locations (ThirdLine);
}
return status_accordingly;
}
}
int main(int argc, char *argv[])
{
// Create an array of spotted_species to ensure you can hold the required number of
// species from the file.
run a OS command "WC -l" which gives the total number of line in your file.
All file handling could be done here based on the output of the above command.
// Calculate the number of objects you would need based on the number of lines.
// Rough estimate would be fine for these requirements.
int num_species = lines_in_file/3 + 10; // +10 is used to be on safer side.
// Create the objects
spotted_species species_spotted_in_africa[num_species];
int ctr;
while (read file until the last line)
// Read 3 lines at a go,
// store them in 3 variables.
// call init with all 3 arguments.
}
// Now you have all the species information in seperate objects.
// you can access them in a loop or by any other means.
// If you need to perform any additional processing on these objects,
// you always can extend this class or
// you could write another class which can process this class data.
// Flexible, simple, Maintainable and scalable.
return 0;
}
You will have to make some changes as per your exact requirements. I hope this helps.
Based on the fact that you have 3 lines of data per species, eg:
84
Spotted Gecko
84 95 30 25
I would suggest using a vector of struct values instead of string values, where each struct holds the data for a single species. While looping through the input file, read 3 lines at a time, parse them into an instance of the struct, and then push it into* the vector.
Try this:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
struct species
{
int region;
string name;
std::vector<int> regionSightings;
};
bool openInputFile(ifstream &inputfile)
{
string fileName;
//prompting user for filename to be opened
cout << "Enter the input file to be opened: ";
getline(cin, filename);
//opening the file for input
cout << "Opening file: " << filename << endl;
inputfile.open(fileName);
//checks to see if opening the input file failed
if (!inputfile)
{
cout << "File: " << fileName << " could not be opened!" << endl;
cout << "1. Check if file exists." << endl;
cout << "2. Check file path." << endl;
return false;
}
cout << "File: " << fileName << " was successfully opened!" << endl;
return true;
}
bool openOutputFile(ofstream &outputfile)
{
string fileName;
//prompting user for filename to be opened
cout << "Enter the output file to be opened: ";
getline(cin, filename);
//opening the file for input
cout << "Opening file: " << fileName << endl;
outputfile.open(fileName);
//checks to see if opening the output file failed
if (!outputfile)
{
cout << "File: " << fileName << " could not be opened!" << endl;
cout << "1. Check if file exists." << endl;
cout << "2. Check file path." << endl;
return false;
}
cout << "File: " << fileName << " was successfully opened!" << endl;
return true;
}
int main()
{
//opens clasfication file
ifstream inputFile;
if (openInputFile(inputFile))
{
//declaring year and numberOfSpecies
int year, numberOfSpecies;
string line;
//year of file
inputFile >> year;
//echo for year
cout << "Year: " << year << endl;
//number of species in file
inputFile >> numberOfSpecies;
//echo for number of species
cout << "# species: " << numberOfSpecies << endl;
//there are three lines per species
//region of species, eg: 84
//nameOfspecies, eg: Spotted Gecko
//regionSightings, eg: 84 95 30 25
vector<species> speciesData;
for (int i = 0; i < numberOfSpecies; ++i)
{
species s;
if (!getline(inputFile, line))
{
cout << "File: " << fileName << " could not read a species region!" << endl;
break;
}
if (!(istringstream(line) >> s.region))
{
cout << "File: " << fileName << " could not parse a species region!" << endl;
break;
}
if (!getline(inputFile, s.name))
{
cout << "File: " << fileName << " could not read a species name!" << endl;
break;
}
if (!getline(inputFile, line))
{
cout << "File: " << fileName << " could not read a species sightings!" << endl;
break;
}
istringstream iss(line);
int num;
while (iss >> num)
s.regionSightings.push_back(num);
if (!iss.eof())
{
cout << "File: " << fileName << " could not parse a species sightings!" << endl;
break;
}
speciesData.push_back(s);
//echo vector!
cout << s.region << " " << s.name << " " << line << endl;
}
cout << "Closing input file" << endl;
inputFile.close();
ofstream outputFile;
if (openOutputFile(outputFile))
{
for (std::vector<species>::iterator iter = speciesData.begin();
iter != speciesData.end();
++iter)
{
species &s = *iter;
// write species data to outputFile as needed...
}
cout << "Closing output file" << endl;
}
cout << "Finished" << endl;
}
return 0;
}