c++ ofstream keeps failing member function - c++

I have made a program, where I want to write some things on a file. When I do it directly from my main-function it works fine, but when i make this class member function, it fails to do that. std::cout works without a problem, and I don't receive any error message. It just doesn't write on the file. This is my code:
#include <fstream>
... // not relevant
template <class T>
void Grid <T>::write() const {
int printcount = 0;
ofstream outputFile;
outputFile.open("data.txt", ios::app);
for (vector<T>::const_iterator iter = matrix.begin(); iter != matrix.end(); ++iter) {
++printcount;
cout << setw(12) << *iter;
outputFile << setw(12) << *iter;
if (printcount % Columns == 0) {
cout << endl;
outputFile << endl;
}
}
cout << endl;
outputFile << endl;
outputFile.close();
}

Related

I am trying to create a scrolling function and I was hoping someone could give some advice on a certain problem I am having

I am working on a text editor project for the 3ds and I am working on adding a scrolling function I have found a way for the text to scroll up by doing this
if (kHeld & KEY_UP)
{
cout << endl;
}
but for a basic implementation of the text scrolling down I need to insert a white space at the top of the imputed text I have tried using the insert() function but it needs to output the text again to show the inserted whitespace this is a large problem I have been stuck on for days and any suggestions you are willing to provide would be great here is my full source code if it will help thanks
// T3XTPAD-V1.0
#include <iostream>
#include <fstream>
#include <string>
#include <3ds.h>
using namespace std;
string Output = "";
int main()
{
gfxInitDefault();
PrintConsole topScreen, bottomScreen;
consoleInit(GFX_TOP, &topScreen);
consoleInit(GFX_BOTTOM, &bottomScreen);
consoleSelect(&bottomScreen);
cout << endl;
cout << "T3XTPAD-V1.0" << endl;
cout << endl;
cout << "[A] Edit:" << endl;
cout << endl;
cout << "[B] Save:" << endl;
cout << endl;
cout << "[Y] Open:" << endl;
cout << endl;
cout << "[UP/DOWN] Scroll:" << endl;
cout << endl;
consoleSelect(&topScreen);
while (aptMainLoop())
{
hidScanInput();
u32 kHeld = hidKeysHeld();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
{
break;
}
static SwkbdState swkbd;
static char Edit[999999];
static char Save[999999];
static char Open[999999];
SwkbdButton button = SWKBD_BUTTON_NONE;
if (kDown & KEY_A)
{
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, -1);
swkbdSetHintText(&swkbd, "Edit:");
button = swkbdInputText(&swkbd, Edit, sizeof(Edit));
cout << Edit << endl;
}
if (kDown & KEY_B)
{
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, -1);
swkbdSetHintText(&swkbd, "Save:");
button = swkbdInputText(&swkbd, Save, sizeof(Save));
ofstream MyFile (Save);
if (MyFile.is_open())
{
MyFile << Edit << endl;
MyFile.close();
}
}
if (kDown & KEY_Y)
{
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, -1);
swkbdSetHintText(&swkbd, "Open:");
button = swkbdInputText(&swkbd, Open, sizeof(Open));
ifstream MyFile (Open);
if (MyFile.is_open())
{
while (getline (MyFile, Output))
{
cout << Output << endl;
}
MyFile.close();
}
}
if (kHeld & KEY_UP)
{
cout << endl;
}
if (kHeld & KEY_DOWN)
{
cout << endl;
}
gfxFlushBuffers();
gfxSwapBuffers();
gspWaitForVBlank();
}
gfxExit();
return 0;
}

vector<string> in a struct doesn't work properly

I declared a vector<string> and I cannot even compile it. I tried many ways but none of them worked.
I'm trying to write out the x.surname.push_back(word)[i] but it's definetly written wrongly and I have no idea how to write it properly and make it possible to compile.
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int number, i = 0;
string word;
struct donators {
vector<string> surname;
vector<int> amount;
} x;
cout << "How many donators do you want to register? " << endl;
cin >> number;
for (i = 0; i < number; i++) {
cout << "Surname: ";
cin >> word;
x.surname.push_back(word)[i];
cout << "Amount: ";
x.amount.push_back(i);
cin >> x.amount[i];
}
cout << "OUR GORGEUS DONATORS: " << endl;
for (i = 0; i < number; i++) {
if (x.amount[i] >= 10000) {
cout << "Surname: " << x.surname(word)[i];
cout << "Amount: " << x.amount[i] << endl;
}
else if (x.amount[i] < 10000) {
cout << "Lack of surnames!" << endl;
}
}
cout << "OUR CASUAL DONATORS: " << endl;
for (i = 0; i < number; i++) {
if (x.amount[i] < 10000) {
cout << "Surname: " << x.surname(word)[i];
cout << "Amount: " << x.amount[i] << endl;
} else if (x.amount[i] >= 10000) {
cout << "Lack of surnames!" << endl;
}
}
return 0;
}
And one more thing. How to make sentence "Lack of surnames!" to be written out once? In some cases, it is written out twice or more times what is redundant.
You are putting [i] at seemingly random places in your code. Such as in x.surname.push_back(word)[i];. Don't add things like this to your code if you're unsure about what they're doing.
The x.surname(word)[i] construct are also wrong. What's x.surname(word) supposed to be? This syntax is for function calls. surname, however, is not a function. It's a std::vector<std::string>. Just put x.surname[i] instead.
And one more thing. How to make sentence "Lack of surnames!" to be
written out once? In some cases, it is written out twice or more times
what is redundant.
That's because you write it for every donor that doesn't fit the criterion. Instead, keep track if any donor fits the criterion and only print it when none ends up fitting. You can do it like this:
bool HasGorgeousDonators = false;
And then in the loop:
if (x.amount[i] >= 10000)
{
cout << "Surname: " << x.surname[i];
cout << "Amount: " << x.amount[i] << endl;
HasGorgeousDonators = true;
}
And after the loop:
if (!HasGorgeousDonators)
cout << "Lack of surnames!" << endl;
Likewise for the other loop. Also, please consider the following Q&A:
Why is "using namespace std;" considered bad practice?
It seems like you are writing C with some C++ help functions. However C++ is a different language. Sure, it supports some C structures, but there's so much more.
Take a look at some of my suggestions for implementation and compare it to your code:
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
template<typename T>
T ReadCin(std::string_view const& sv = "") {
T retVal;
if (!sv.empty()) std::cout << sv;
std::cin >> retVal;
return retVal;
}
class Donator {
private:
std::string surname{};
int amount{};
public:
constexpr bool IsGenerous() const noexcept { return amount >= 10000; }
void Read() noexcept {
surname = ReadCin<decltype(surname)>("Surname: ");
amount = ReadCin<decltype(amount)>("Amount: ");
}
friend std::ostream& operator<<(std::ostream& out, Donator const& donator) noexcept {
out << "Surname: " << donator.surname << ", " << "Amount: " << donator.amount;
return out;
}
};
int main() {
std::vector<Donator> donators(ReadCin<int>("How many donators do you want to register?\n"));
for (auto& donator : donators) donator.Read();
std::cout << "OUR GENEROUS DONATORS:\n";
std::copy_if(std::cbegin(donators), std::cend(donators), std::ostream_iterator<Donator>(std::cout, "\n"),
[](Donator const& donator) { return donator.IsGenerous(); });
std::cout << "OUR CASUAL DONATORS:\n";
for (auto const& donator : donators) if (!donator.IsGenerous()) std::cout << donator << '\n'; //alternative
}
I tried to include some of the possibilities using C++. I would really advise you to get a good book on C++.

Member function will not execute its whole code

I have made a "computer". My conctructor looks like this:
PC::PC()
{
cout << "Would you like to turn the pc on? type y for yes." << endl;
a = getchar();
while (a != 'y')
{
cout << "If you dont turn it on, then nothing will happen. Loser." << endl;
a = getchar();
}
}
Then if you press y you will be sent to the next step which is the function PC::pcOn which looks like this:
void PC::pcOn()
{
for (auto i = 0; i < 3; i++)
{
cout << "----------------------------------------" << endl;
}
cout << "--------- What is your name? -----------" << endl;
changeName();
for (auto i = 0; i < 3; i++)
{
cout << "----------------------------------------" << endl;
}
for (auto i = 0; i < 5; i++)
{
cout << "**" << endl;
Sleep(100);
}
cout << "Welcome " << name << " to the future of computing." << endl << endl;
cout << "This computer program can do a lot of things for you" << endl << "it is a good calculator, try to type \"calculater\"" << endl;
}
However when i have the while loop in the contructor to get the y to go on, the changeName(); wont work, but if i remove that, the changeName function works just fine, and it takes my input just fine.
The code for the changeName() looks like this:
void PC::changeName()
{
string _name;
getline(cin, _name);
name = _name;
}
I have tried using the Visual Studio's debugger to see why i wont call it correctly, but alas to no hope.
The weird thing is, that the function works fine if the while loop in the constructor is not there.
It is because in getline(cin, _name), it always inputs the "/n" character as it is feeded when you type enter.
To correct it, put a getchar();
void PC::changeName()
{
string _name;
getchar();
getline(cin, _name);
name = _name;
}
You need to flush cin before calling changeName(), this can be done using
int c;
while ((c = getchar()) != '\n' && c != EOF);

testing "Try and Catch"

In this program, I am using template class, I have a header file and this is my main file. I am having trouble displaying the (".....") IndexOutOfBounds and displaying it on the screen.
#include "XArray.h"
#include <iomanip>
#include <string>
using namespace std;
template<class T>
void afriend ( XArray<T> );
int main()
{
XArray<double> myAD(18);
myAD.randGen(15, 100);
cout << myAD.getType() << endl;
cout << setprecision(1) << fixed << "\n\n Unsorted: " << myAD;
myAD.sort();
cout << "\n Now Sorted: " << myAD;
cout << "\n\n";
**try
{
cout << "A[-5] = " << setw(6) << myAD[-5] << endl;
}
catch(XArray<double>::IndexOutOfBound e)
{
e.print();
}
try
{
cout << "A[8] = " << setw(6) << myAD[8] << endl;
}
catch(XArray<double>::IndexOutOfBound e)
{
e.print();
}**
cout << "\n\n" << setprecision(2) << fixed;
cout << "Size = " << setw(6) << myAD.getSize() << endl;
cout << "Mean = " << setw(6) << myAD.mean() << endl;
cout << "Median = " << setw(6) << myAD.median() << endl;
cout << "STD = " << setw(6) << myAD.std() << endl;
cout << "Min # = " << setw(6) << myAD.min() << endl;
cout << "Max # = " << setw(6) << myAD.max() << endl;
return 0;
}
There is the Array.h file posted as a dropbox link
Array.h
The code for operator[] in Array.h is:
template <class T>
T XArray<T>::operator[] (int idx)
{
if( (idx = 0) && (idx < size) )
{
return Array[idx];
}
else
{
throw IndexOutOfBound();
return numeric_limits<T>::epsilon();
}
}
Although the question is somewhat obscure, give a try to these suggestions.
Firstly, it can happen that XArray<>::IndexOutOfBounds have no proper copy ctor. You can try catching by const reference to workaround that:
try
{
...
}
catch(const XArray<double>::IndexOutOfBound& e)
{
e.print();
}
Index operator in standard library containers does not check for bounds, there is a special getter that does the check called at(). If the XArray class is designed with standard library in mind, it could behave similarly.
However to get more adequate response you need to be more specific describing the trouble you are having.
I'm still wondering what exact question is.
However, I'm understanding the question is that how I can use 'catch' by using 'IndexOutOfBound'.
#include <exception>
#include <iostream>
using namespace std;
template <typename T>
class Array
{
private:
int m_nLength;
T *m_ptData;
public:
...
...
T& operator[](int nIndex)
{
//assert(nIndex >= 0 && nIndex < m_nLength);
if(nIndex < 0 || nIndex > m_nLength)
{
throw myex;
}
else
{
return m_ptData[nIndex];
}
}
//class definition for 'IndexOutOfBound'
class IndexOutOfBound: public exception
{
public:
virtual const char* print() const throw()
{
return "Exception occured 'Index Out Of Bound'";
}
}myex;
};
int main()
{
Array<double> arr(3);
try
{
arr[0] = 1;
//exception will occur here.
arr[4] = 2;
}
catch(Array<double>::IndexOutOfBound &e)
{
cout << e.print() << '\n';
}
return 0;
}
Here is no 'XArray.h', so I've written a sample array class for example.
The problem is in the operator[] function. The code idx = 0 sets idx to 0. So all of your calls to operator[] will return the first element, and therefore there is no out-of-bounds error unless the array is empty.
You probably meant to write if ( idx >= 0 && idx < size ).
BTW the throw aborts the function, it makes no sense to return after throw.

Data doesn't load into c++ vector correctly

I am trying to load a text file and import the contents into a vector of structs.
Here are my definitions
typedef struct
{
string pcName, pcUsername, pcPassword, pcMessage, pcAdvertisement; //I know that
//this is incorrect convention. It was originally a char*
}
ENTRY;
vector<ENTRY> entries;
fstream data;
Here is my display data function
void DisplayData()
{
std::cout << (int)(entries.size() / 5) <<" entries" << endl;
for(int i = 1; i <=(int)entries.size()/5; i++)
{
cout << endl << "Entry " << i << ":" << endl
<< "Name: " << entries[i].pcName << endl
<< "Username: " << entries[i].pcUsername << endl
<< "Password: " << entries[i].pcPassword << endl
<< "Message: " << entries[i].pcMessage << endl
<< "Advertisement: " << entries[i].pcAdvertisement << endl;
}
}
and here is my Load Data function
bool LoadData(const char* filepath)
{
std::string lineData ;
int linenumber = 1 ;
data.open(filepath, ios::in);
ENTRY entry_temp;
if(!data.is_open())
{
cerr << "Error loading file" << endl;
return false;
}
while(getline(data, lineData))
{
if(linenumber==1) {entry_temp.pcName = lineData;}
else if(linenumber==2) {entry_temp.pcUsername = lineData;}
else if(linenumber==3) {entry_temp.pcPassword = lineData;}
else if(linenumber==4) {entry_temp.pcMessage = lineData;}
else if(linenumber==5) {entry_temp.pcAdvertisement = lineData;}
entries.push_back(entry_temp);
if(linenumber == 5)
{
linenumber = 0;
}
linenumber++;
}
data.close();
puts("Database Loaded");
return true;
}
Here is the text file I am loading:
Name1
Username1
Password1
Message1
Ad1
And here is the result of the display data function after calling load data:
1 entries
Entry 1:
Name: Name1
Username Username1
Password:
Message:
Advertisement:
As you can see, the first two load but the last three don't. When I did this with an array instead of a vector, it worked fine so I don't know what I'm doing wrong. Thanks.
I suggest that you read each line directly into the data field where it goes:
getline(data, entry_temp.pcName);
getline(data, entry_temp.pcUsername);
getline(data, entry_temp.pcPassword);
getline(data, entry_temp.pcMessage);
getline(data, entry_temp.pcAdvertisement);
entries.push_back(entry_temp);
This makes your intent much clearer than your current while loop. It also creates a single entry for all 4 input lines rather than one for each input line (with the other three blank). Now you can read several "entries" by using a while loop that checks if you have reached the end of the file.
Doing this will also make printing out the data much easier since the vector will have exactly the number of entries rather than five times as many as you expect (which also eats up a lot more memory than you need to).
Your DisplayData function is a little weird, and so is your LoadData.
Your LoadData pushes back a new copy of the current ENTRIES entry with every line. Your DisplayData starts at 1 (which is not the beginning of any vector or array), and iterates only up to the 1/5th entry of the entire vector.
This needs a heavy rework.
First, the size() member of any standard container returns the number of elements that it contains, and will not take the number of fields in a contained struct into account.
For future reference, you'll want to post your question in a complete, standalone example that we can immediately compile to help. (see http://sscce.org/)
Try this modified data, which runs correctly, and see if you can tell what is being done differently:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
typedef struct
{
string pcName, pcUsername, pcPassword, pcMessage, pcAdvertisement;
}
ENTRY;
vector<ENTRY> entries;
fstream data;
bool LoadData(const char* filepath)
{
std::string lineData ;
int linenumber = 1 ;
data.open(filepath, ios::in);
ENTRY entry_temp;
if(!data.is_open())
{
cerr << "Error loading file" << endl;
return false;
}
while(getline(data, lineData))
{
if(linenumber==1) {entry_temp.pcName = lineData;}
else if(linenumber==2) {entry_temp.pcUsername = lineData;}
else if(linenumber==3) {entry_temp.pcPassword = lineData;}
else if(linenumber==4) {entry_temp.pcMessage = lineData;}
else if(linenumber==5) {entry_temp.pcAdvertisement = lineData;}
if(linenumber == 5)
{
entries.push_back(entry_temp);
linenumber = 0;
}
linenumber++;
}
data.close();
puts("Database Loaded");
return true;
}
void DisplayData()
{
std::cout << entries.size() <<" entries" << endl;
for(int i = 0; i < entries.size(); i++)
{
cout << endl << "Entry " << i << ":" << endl
<< "Name: " << entries[i].pcName << endl
<< "Username: " << entries[i].pcUsername << endl
<< "Password: " << entries[i].pcPassword << endl
<< "Message: " << entries[i].pcMessage << endl
<< "Advertisement: " << entries[i].pcAdvertisement << endl;
}
}
int main()
{
LoadData("/tmp/testdata");
DisplayData();
return (0);
}
While I think #code-guru has the right idea, I'd take the same idea just a little further, and make your code work a little more closely with the standard library. I'd do that by reading a data item with a stream extractor, and displaying it with stream inserter. So, the extractor would look something like this:
std::istream &operator>>(std::istream &is, ENTRY &e) {
getline(is, e.pcName);
getline(is, e.pcUsername);
getline(is, e.pcPassword);
getline(is, e.pcMessage);
getline(is, e.pcAdvertisement);
return is;
}
..and the inserter would look something like this:
std::ostream &operator<<(std::ostream &os, ENTRY const &e) {
os << e.pcName << "\n";
os << e.pcUsername << "\n";
os << e.pcPassword << "\n";
os << e.pcMessage << "\n";
os << e.pcAdvertisement << "\n";
return os;
}
With those in place, loading and displaying the data becomes fairly straightforward.
Load the data:
std::ifstream in("yourfile.txt");
std::vector<ENTRY> data((std::istream_iterator<ENTRY>(in)),
std::istream_iterator<ENTRY>());
Display the data:
for (auto const & e: data)
std::cout << e << "\n";
For the moment, I haven't tried to duplicate the format you were using to display the data -- presumably the modifications for that should be fairly obvious.