so the write elm and getfileID functions require the cursor pos in the file
(write elm appends to the end, getFileID prints lines first to last)
#ifndef file_operations_header
#define file_operations_header
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include "First_classes_header.h"
class fileOPerations
{
private:
string line;
fstream f_myFileOut;
public:
fileOPerations();
void closeFile()
{
f_myFileOut.close();
}
int getFileID()
{
int counter = 0;
if (f_myFileOut.is_open())
{
while(f_myFileOut.good()){
getline(f_myFileOut,line);
++counter;
cout << line << endl;
}
}f_myFileOut.close();
return counter;
}
int writeElm(makeVector& mV,int i)
{
f_myFileOut.open("file.txt",ios::out|ios::app|ios::ate);
if (f_myFileOut.is_open())
{
f_myFileOut << mV.str_vector[i].counter << "\t";
f_myFileOut << mV.str_vector[i].name << endl;
}
else{
cout << "can't open file." << endl;
}
return 0;
}
friend class makeVector;
};
fileOPerations::fileOPerations():f_myFileOut("file.txt",ios::out|ios::app|ios::in){}
#endif // file_operations_header
and the call to getFileID in my main doesn't print anything because writeElm()
set the cursor pos to the end of the file.
#include <iostream>
#include <string.h>
#include <vector>
#include "First_classes_header.h"
#include "file_operations.h"
using namespace std;
int main()
{
fileOPerations fpObject;
makeVector vecObject;
int fileID = fpObject.getFileID();
while(true){
IDgenerator();
int genID = IDgenerator::GetID();
int currentID = fileID + genID;
string workingName = nameGetter::setName();
vecObject.vecSetter(currentID,workingName);
fpObject.writeElm(vecObject, currentID); // error within this function
fpObject.getFileID();
}fpObject.closeFile();
return 0;
}
Is it safe/effecient/effective to call f_myFileOut.open() with different parameters
in each separate function?
int getFileID()
{
f_myFileOut.open(("file.txt",ios::out|ios::app|ios::in)
int counter = 0;
...
...
int writeElm(makeVector& mV,int i)
{
f_myFileOut.open("file.txt",ios::out|ios::app|ios::ate);
Or should I set the cursor pos manually?
While it is certainly not efficient, to open/close the same file over and over again, it would be safe, and I'd even call it better coding style, because currently you are opening a file in one method and closing it in another, and in both cases it is not obvious from the function name that this is one of their side effects (contratry to e.g. closeFile()). Also you are already opening/closing the file in every iteration, so this would "only" double the open/close operations.
In general however, I'd definitively recommend to open the file once at the beginning of your program, close it at the end and e.g. use f_myFileOut.seekg (0,f_myFileOut.beg) and f_myFileOut.seekg (0,f_myFileOut.end) in between, to move your iterator around.
Related
I'm trying to write a program that first checks if a name is in a vector and if not then adds it to the vector. My code seems to have difficulties with parsing, at least that's what I get out of it. I tried changing the string to a char but it did not help me much.
#include <iostream>
#include <vector>
#include <string>
bool isinVector(std::string uElement, std::vector<std::string> uArray)
{
for (unsigned int i = 0; i <= sizeof(uArray); i++) {
if (uArray[i] == uElement) {
return true;
}
else {
return false;
}
}
}
int main()
{
bool trigger = false;
while (!trigger) {
std::vector<std::string> names;
names.push_back("Bart");
std::string newName;
getline(std::cin, newName);
if (isinVector(newName, names))
{
std::cout << "true" << std::endl;
trigger = true;
}
else
{
std::cout << "false" << std::endl;
names.push_back(newName);
for (int i = 0; i <= sizeof(names); i++) {
std::cout << names[i] << std::endl;
}
}
}
}
I made some adjustments to your code, removing your isinVector function and using a lambda inside the main function instead. In the future please provide a concise question and example.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::vector;
using std::string;
using std::cout;
using std::cin;
using std::endl;
using std::find_if;
int main(){
bool trigger = false;
while (!trigger) {
vector<string> names;
names.push_back("Bart");
string newName;
getline(cin, newName);
if(find_if(names.begin(), names.end(), [newName] (const string& name){
return !name.compare(newName);
}) != names.end()){
cout << "true" << endl;
trigger = true;
}
else{
cout << "false" << endl;
names.push_back(newName);
for (size_t i = 0; i < names.size(); i++) {
cout << names.at(i) << endl;
}
}
}
return 0;
}
The code uses std::find_if to check if the element exists in the vector. If std::find_f does not return the iterator to uArray.end() Then the element exists. Also your for loop used sizeof which is incorrect, use the vector.size method. And you were looping until <= , it should be < uArray.size() And it's safer to access elements in the vector through the .at method rather than an index [] since the .at will throw an out_of_range exception.
Among the things wrong in the updated post.
Improper use of sizeof
Reinventing a standard algorithm
Lack of error checking
Consider the tasks you're trying to accomplish. You want to:
Initialize a starting vector containing the name Bart
Continuously read new names. For each new name read:
a. Check to see if it is already in the vector.
if it is present terminate the read loop
else add it to the vector, and print the entire vector
This sequence of operations can be accomplished with stepwise refinement.
Step 1. Read names
First, you need to be able to continuously read names:
#include <iostream>
#include <string>
int main()
{
std::string name;
while (std::getline(std::cin, name))
std::cout << name << '\n';
}
Simple enough. Running this will echo any strings you type, one at a time, separated by newlines.
Step 2. Accumulate names in a vector
Next, we need to add a vector to hold the strings we're reading, with an initial population of the name "Bart". For this pass we'll be just putting every string we read into the vector
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> names = { "Bart" };
std::string name;
while (std::getline(std::cin, name))
{
names.emplace_back(name);
for (auto const& s : names)
std::cout << s << ' ';
std::cout.put('\n');
}
}
In addition to what was done prior, we're now accumulating strings in the vector, including duplicates, and reporting the vector content after each name read. This gets us closer to our stated goal.
Step 3: Conditional loop exit based on duplicate detection
Now we need to check for duplicates, and terminate the loop once it happens. We can do this using std::find. The final code is below:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> names = { "Bart" };
std::string name;
while (std::getline(std::cin, name))
{
if (std::find(names.begin(), names.end(), name) != names.end())
break;
names.emplace_back(name);
for (auto const& s : names)
std::cout << s << ' ';
std::cout.put('\n');
}
}
That's it. This is a simple task, but it lends itself nicely to an example of how you break a multi-part task down to manageable objectives , then build it in pieces.
Hope you found it useful.
Now my code looks like this:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
bool isinVector (std::string uElement, std::vector<std::string> uArray) {
bool invector = false;
std::vector<std::string>::iterator it = std::find(uArray.begin(),
uArray.end(),uElement);
if(it != uArray.end()){
invector = true;
}
return invector;
}
int main(){
bool trigger = false;
std::string name;
std::vector<std::string> names = { "Bart" };
while (std::getline(std::cin, name)){
if (isinVector(name, names)) {
std::cout << "true" << std::endl;
break;
}
else
{
std::cout << "false" << std::endl;
names.emplace_back(name);
}
}
return 0;
}
and it works, thanks a lot guys!
So I am creating an hangman game and want to add a char into a string. I want to add a char of guess to the gatherguess string until the gatherguess matches hangman. Feel free to add some helpful tips to my code that will make me better. Also if it would be more then nice if you can also give me some sample code with dynamic memory allocation.
#include <stdio.h>
#include <string.h>
#include <iostream> // std::cout
#include <stdio.h>
#include <string.h>
#include <iostream> // std::cout
#include <algorithm> // std::for_each
#include <vector>
#include <set>
#include <string>
bool isitdone(std::string foo, std::string hang){
return foo == hang ? true : false ;
}
int main(){
std::string hangman;
char guess;
std::string gatherguess; //Get the letters guessed.
std::cin >> hangman; //Player enter the word to guess.
bool checkstatement; // Check to see if game is over.
for(int i =0; i < 10; ++i) {
std::cin >> guess; //Individual characters to guess
std::string doo;
int wordsin;
doo = hangman;
int y;
if(doo.rfind(guess) != std::string::npos) {
std::cout << "Right " << guess << " Is in the word" << std::endl;
std::cout << std::endl;
checkstatement = isitdone(gatherguess,doo);// I want to add guess char into gatherguess
//then check to see if gatherguess is equal to the word then the game will be complete
if(checkstatement == true) {
return 0;
}
} else {
std::cout << "Wrong" << std::endl;
}
}
return 0;
}
First of all, you should initialize gatherguess with enough placeholder characters:
auto hangman = std::string{};
std::cin >> hangman;
auto gatherguess = std::string{hangman.size(), '_'};
Now you can simply overwrite the '_' characters.
auto pos = hangman.find(guess)
if(pos != std::string::npos) {
// ...
do {
gatherguess[pos] = guess; // overwrite
pos = hangman.find(guess, pos); // find next ocurrence
} while(pos != std::string::npos)
// ...
}
I made some changes on your code. It contains some pieces of advice as comment.
//#include <stdio.h> // Do not include a library if you don not use it, because it makes the performance worse.
//#include <string> // Do not include a library if you don not use it, because it makes the performance worse.
#include <iostream> // std::cout
//#include <stdio.h> // It is pointless to include a library twice.
//#include <string.h>
//#include <iostream> // std::cout
//#include <algorithm> // std::for_each
//#include <vector> // Do not include a library if you don not use it, because it makes the performance worse.
//#include <set> // Do not include a library if you don not use it, because it makes the performance worse.
#include <string>
bool isitdone(const std::string& foo, const std::string& hang){ // Passing argument by const reference makes performance much better.
return foo == hang ? true : false ; // Indenting makes the code much more readable.
}
int main(){
const int N=10; // Store constant number in constant variable, because you can change its' value later easily.
std::string hangman;
char guess;
std::string gatherguess; //Get the letters guessed.
std::cin >> hangman; //Player enter the word to guess.
bool checkstatement; // Check to see if game is over.
for(int i =0; i < N; ++i)
{
std::cin >> guess; //Individual characters to guess
std::string doo;
int wordsin;
doo = hangman;
int y;
if(doo.rfind(guess) != std::string::npos)
{
std::cout << "Right " << guess << " Is in the word" << std::endl;
std::cout << std::endl;
checkstatement = isitdone(gatherguess,doo);// I want to add guess char into gatherguess
//then check to see if gatherguess is equal to the word then the game will be complete
if(checkstatement == true)
{
return 0;
}
} else
{
std::cout << "Wrong" << std::endl;
}
}
return 0;
}
I think there is a logical mistake in your program. What happens if a word contains more than 10 different characters? Do not count if the tipp is right.
You can add a char to a string this way:
#include <iostream>
#include <string>
int main(){
std::string str="123";
str+='4';
std::cout<<str<<std::endl;
return 0;
}
I am attempting to write to a file using functions that are not a part of main, but whenever I call fout in a function that is not main I get an error stating that fout is not declared in this scope. Here is my header for the file, followed by an example of one of the functions I am attempting to use fout in.
header:
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cctype>
using namespace std;
function:
void isCorrectStartingLetter(string currentLine, bool &truthValue)
{
if(isalpha(currentLine.at(0)))
{
truthValue = true;
}
else
{
truthValue = false;
fout << " Error- Must start with a letter" << endl;
}
}
Define the function the following way
bool isCorrectStartingLetter( const std::string ¤tLine, std::ostream &fout = std::cout )
{
bool truthValue = isalpha(currentLine[0] );
if ( !truthValue )
{
fout << " Error- Must start with a letter" << endl;
}
return truthValue;
}
Hoping you ain't thinking fout is a magical keyword, you should be able to pass it as refernce and accordingly returning true or false, something like following :-
//std::ofstream fout("file_name");
bool isCorrectStartingLetter(string currentLine, std::ostream& fout)
{
if(isalpha(currentLine.at(0)))
{
return true;
}
else
{
fout << " Error- Must start with a letter" << endl;
return false;
}
}
Example ABC.txt
10.f 30.2f 20.f
I want to retrieve those information and store inside my array. However i am unsure how to do it.
I dont understand what is
Then (if good), it calls num_get::get (using the stream's selected locale) to perform both the extraction and the parsing operations, adjusting the stream's internal state flags accordingly. Finally, it destroys the sentry object before returning.
std::fstream filestr("ABC.txt", std::fstream::in);
if(!filestr.good()) //Logical error on i/o operation
{
//Unable to process
filestr.close();
return;
}
unsigned index= 0;
unsigned count= 0;
while(filestr.good())
{
float buffer= 0.f;
filestr >> std::skipws >> buffer;
score[index]= buffer;
++index;
}
filestr.close();
There are a number of ways to do this. One way is using stringstreams, in combination with vectors and strings:
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
#include <vector>
using namespace std;
int main() {
std::ifstream filestr("C:\\nums.txt", std::fstream::in);
std::vector<double> numbers;
if (!(filestr.good())) {
std::cout << "BAD FILE" << std::endl;
exit(0);
}
else {
std::string temp;
double d = 0.0;
while(std::getline(filestr, temp)) {
std::istringstream iss(temp);
while(std::getline(iss, temp, ' ')) {
std::istringstream ist(temp);
ist >> f;
numbers.push_back(f);
}
}
}
//see that the vector has information in it
for (int i = 0; i < numbers.size(); i++) {
std::cout << numbers[i] << std::endl;
}
filestr.close();
return 0;
}
One thing to note is that you could also use iterators here, but that's something you could implement for yourself.
Super simple with istream_iterator. There is only one tricky bit in the code below. The vector constructor call needs an extra set of parens around the first argument to avoid the Most Vexing Parse.
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
int
main (int argc, char** argv)
{
for (int i = 1; i < argc; ++i) {
ifstream in (argv[i]);
if (!in) {
cerr << "Failed to open " << argv[i] << endl;
continue;
}
vector<double> nums ((istream_iterator<double> (in)), istream_iterator<double> ());
copy (nums.begin (), nums.end (), ostream_iterator<double> (cout, "\n"));
}
return 0;
}
I can get getline() to work with cin (getline(cin,line)), but when I open a stream, it won't read the line from the file. The file contains a list of elements from the periodic table.
for Example:
H
He
O
etc...
EDIT:
However, when I try to cout the newly read line, it doesn't put it into var symbol at the line:
cout << "symbol: " << symbol << endl;
It doesn't give me anything out, but it should return the first element (H).
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void print(vector <string> x)
{
cout << "list of elements:" << endl;
for (int i = 0; i < x.size(); ++i)
{
cout << x[i] << endl;
}
}
int main(int argc, char** argv)
{
string symbol;
vector <string> elementlist;
ifstream readin;
readin.open("Elements.txt");
getline(readin,symbol);
cout << "symbol: " << symbol << endl;
while (!readin.good())
{
elementlist.push_back(symbol);
getline(readin,symbol);
}
print (elementlist);
return 0;
}
I'd do it something like this:
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
class line {
std::string data;
public:
friend std::istream &operator>>(std::istream &is, line &l) {
std::getline(is, l.data);
return is;
}
operator std::string() const { return data; }
};
int main() {
std::ifstream readin("Elements.txt");
// Initialize vector from data in stream:
//
std::vector<std::string>
element_list((std::istream_iterator<line>(readin)),
std::istream_iterator<line>());
// write data from vector to cout:
//
std::copy(element_list.begin(), element_list.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
As I stated in my comment, your loop condition is wrong.
while (!readin.good())
{
elementlist.push_back(symbol);
getline(readin,symbol);
}
As it turns out, you want to loop using the condition readin.good(). Since !readin.good() will evaluate to false, you never actually enter the loop.