My program crashes unexpectedly when I try and output my results to a .txt file.
Basically, I want to store a list of students in a .txt file and retrieve them for later convenience. My program can store the values as variables, however the moment you want to save them to the output file, the program itself crashes.
This is my code
//STUDENTS CLASS
char** studentNames;
int numberOfNames;
void Students::setNumberOfNames(int namenumbers) // Takes in the number of student names to store
{
numberOfNames = namenumbers;
}
void Students::setStudentNames() // Takes a number of student names and stores them.
{
char studentinput[128]
studentNames = new char*[numberOfNames];
for (int i=0; i<=numberOfNames; i++)
{
studentNames[i] = new char[128];
cout << "Student " << i << ": " << "\n";
cin.getline(studentinput, sizeof(studentinput));
strcpy(studentNames[i], studentinput);
}
}
//MAIN CLASS
Student s;
int nums;
int main()
{
cout << "How many names would you like to store? " << endl;
cin >> nums;
s.setNumberOfNames(nums):
s.setStudentNames();
for(int i=0; i<=s.numberOfNames; i++)
{
cout << s.numberOfNames [i] << "\n"; // THIS WORKS FINE! DOES WHAT I SAY :)
}
// THIS IS WHERE IT CRASHES. I TRY AND STORE THE NAMES INTO THE `.txt` FILE.
//IF YOU WANT TO STORE 3 NAMES, IT WORKS FINE, BUT IF YOU WANT TO STORE LIKE
//12 NAMES THE WHOLE THING CRASHES. WHEN I COMMENT OUT THE BOTTOM BLOCK
//OF CODE THE PROGRAM WORKS FINE, BUT I WANT TO STORE THE NAMES.
ofstream outputFiles ("example.txt");
if(outputFiles.is_open())
{
for(int i=0; i<=s.numberOfNames; i++)
{
outputFiles << s.studentNames [i] << "\n";
}
}
}
Change
for (int i=0; i<=numberOfNames; i++)
to
for (int i=0; i < numberOfNames; i++)
everywhere in your program.
Related
So I'm stuck at a point in my code. I need to make a function that can be used to find instances of a list of words in a file.
So, for example, I currently have it to where I can type Breaking-Bad, or Lilo-Stitch; these words are then broken to [breaking, bad] [lilo, stitch] in a vector. The issues arise when I use the function on the bottom.
The function works when it comes to the first index; it will find all instances of the words, like [breaking] or [lilo], but it doesn't output anything else for the other indexes. How can I improve on this section of code?
To further explain, the idea of the code is to find all lines in the file that have one to all of the words typed by the user.
int searchfile(fstream& file, vector<string>& UserSearch, int counter)
{
string input;
int amount = 0;
int line = 0;
for (int i = 0; i < counter; i++) {
while (getline(file, input))
{
line++;
if (input.find(UserSearch[i], 0) != string::npos)
{
cout << "found " << UserSearch[i] << " in line " << line << endl;
amount++;
}
}
}
return amount;
}
I already tried using a for loop in main but it gave the same results.
for (int i = 0; i < list.size; i++) {
searchFile(infile, list, counter);
}
I want to save all the scores of my game (a simple snake game) to a file and then read all the scores. Problem is, i dont know how to save them without knowing how many there will be.
Example:
one person plays it, gets 1200 score, it gets saved;
2nd person plays it, gets 1000 and sees the first person's score;
3rd person plays, gets 1100 and sees the 1st and 2nd scores.
I've done it with an array, but doesnt really work as i want it to.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
ifstream f("score.dat");
ofstream g("score.dat");
int comp(const void* e1, const void* e2){
int f = *((int*)e1);
int s = *((int*)e2);
if(f>s) return 1;
if(f<s) return -1;
return 0;
}
int main()
{
int k=0;
int n, x;
cin >> n;
int* v = new int[n];
for(int i=0; i<n; i++)
cin >> v[i];
for(int i=0; i<n; i++){
qsort(v, n, sizeof(int), comp);
g << v[i] << endl;
}
while(f >> x){
k++;
cout << k << ". " << x << endl;
}
return 0;
}
From what you describe, what you want is:
open the file for writing
write to the file
be done with writing to the file
open the file for reading
read from the file
be done with reading form the file.
So your code should reflect that sequence!
The key point is that you are ever only reading or writing from the file at any given moment, so the ifstream and the ofstream should never exist at the same time!
There's a few ways to go about that, but the simplest is to use functions to isolate them. Here's what that would look like in your case:
void writeScoresToFile(int[] scores, int num_scores) {
// g only starts existing when the function is called
ofstream g("score.dat");
for(int i = 0; i < num_scores; ++i ) {
g<< v[i] << endl;
}
// g is destroyed. This closes the file
}
void readScoresFromFile() {
// f only starts existing when the function is called
ifstream f("score.dat");
int x = 0;
int k = 0;
while(f>> x){
k++;
cout << k << ". " << x << endl;
}
// f is destroyed. This closes the file
}
int main()
{
int n;
cin >> n;
int* v = new int[n];
// ...
// You only need to sort once, not inside the loop.
std::sort(v, v + n);
writeScoresToFile(v, n);
readScoresFromFile()
delete[] n; // <----- if there's a new, there must be a delete.
return 0;
}
Btw, your code could also be better in a number of other ways, but I'm intentionally keeping things as is (apart from objectively broken things), so that you can focus on that specific part:
I've been working on my game and I can easily save my text document, everything works perfectly. My question is, how can I save the text document into a file called "Saves." Here is my code.
Also! I get the input for the char* name from
Save(gets(new char [50]));
Why won't this code work right here?
char* newArray = new char[strlen("PaintAPicture/")+strlen("Saves/")+strlen(name)+strlen(".asciip")+1];
strcpy(newArray,"PaintAPicture/");
strcpy(newArray,"Saves/");
strcpy(newArray,name);
strcat(newArray,".asciip");
I took what you said about using a string, but it's not creating the file and I get the Saving Failed, Main Problem error.
if(saveFile)
{
system("cls");
string prename;
cout << "Enter level's number: ";
cin >> prename;
string name = "Files/" + "Saves/" + prename + ".asciip";
ofstream out(name, ios::binary);
if (!out.is_open()){ MessageBox( 0, "Saving failed! Main problem.", 0, MB_ICONERROR); system("cls"); RedrawMap(); return 0; }
system("cls"); cout << "Saving...";
system("cls");
ShowConsoleCursor(false);
cout << "Saving...";
Sleep(1000);
for(int i = 9; i < SizeY; i++)
{
for(int j = -1; j < SizeX; j++)
{
out << Map[i][j].ch << endl;
out << (int)Map[i][j].color << endl;
}
}
}
cout << '\a';
out.close();
}
Prepend the filename with "Saves/"
char* newArray = new char[strlen("Saves/")+strlen(name)+strlen(".asciip")+1];
strcpy(newArray,"Saves/");
strcat(newArray,name);
strcat(newArray,".asciip");
Also std::string class is designed for storing and manipulating strings. Much easier to use and a lot less error prone than C-strings. Info on string.
EDIT:
Your first piece of code
char* newArray = new char[strlen("PaintAPicture/")+strlen("Saves/")+strlen(name)+strlen(".asciip")+1];
strcpy(newArray,"PaintAPicture/");
strcpy(newArray,"Saves/");
strcpy(newArray,name);
strcat(newArray,".asciip");
doesn't work becouse you're using strcpy where you should use strcat.
strcpy(newArray,"Saves/");
strcpy(newArray,name);
should be
strcat(newArray,"Saves/");
strcat(newArray,name);
As for the problem with creating the file, do those folders exist already? ofstream can create new files to a specified folder, but it cannot create new folders. See https://stackoverflow.com/a/9089919/4761271
Here is the code::
#include <iostream>
using namespace std;
const int MAX = 4;
int main ()
{
char key[20];
char *names[MAX];
for (int i=0; i<MAX; i++)
{
cout << " entr keys\n";
cin >> key;
names[i]=key;
cout<< names[i];
}
for(int i=0; i<MAX;i++)
{
cout << names[i];
}
return 0;
}
When I enter the keys and print them in the 1st for loop they show the right value, but when I print names[i] in the 2nd for loop it keeps showing the last key entered again and again.
Please tell me: where am I going wrong?
When you run names[i]=key; you don't really copy key's string value to names[i].
It just makes name[i] point to where key is (since both name[i] & key are pointers).
so all in all you're overwriting key several times, and making all of names pointers point to key.
You need to copy those strings either by working with std::string instead of char* or by using strcpy. I'd recommend on working with std::string.
Using std::string your code should look like this:
#include <iostream>
#include <string>
using namespace std;
const int MAX = 4;
int main ()
{
string names[4];
for (int i = 0; i < MAX; i++)
{
cout << "entr keys" << endl;
cin >> names[i];
cout << names[i];
}
for(int i=0; i<4;i++)
{
cout << names[i];
}
return 0;
}
Every time you execute the lines
cout << " entr keys\n";
cin >> key;
you're inserting a null-terminated string into key, e.g. "hello\0".
Afterwards you copy key's address and store it into a cell of the names pointers array:
names[i]=key; // Now I point to 'key'
cout<< names[i];
then the cycle starts again. Anyway from the second time on you're inserting null-terminated strings into key and thus overwriting the previous contents. The second time if you had entered "hi\0" the contents of the key array would become
['h', 'i', '\0', 'l', 'l', 'o', '\0']
anyway you're going to only print the first string since the null terminator will prevent the other content from being displayed.
When the program ends you're going to have four pointers to the same key array and that array will only contain the last element inserted which overwrote the previous ones.
In order to solve you can make your array a bidimensional one (or use a string array):
const int MAX = 4;
int main ()
{
char key[4][20]; // <- Now this has two indices
char *names[4];
for (int i = 0; i < MAX; i++)
{
cout << " entr keys\n";
cin >> key[i];
names[i]=key[i];
cout<< names[i];
}
for(int i=0; i<4;i++)
{
cout << names[i];
}
return 0;
}
Live Example
Corrected program:
#include <iostream>
using namespace std;
#include <cstring>
const int MAX = 4;
int main ()
{
char key[20];
char *names[MAX];
for (int i = 0; i < MAX; i++)
{
cout << " entr keys\n";
cin >> key;
names[i] = new char[strlen(key) + 1];//names[i]=key;
strcpy(names[i], key);
cout<< names[i];
}
for(int i=0; i<MAX;i++)
{
cout << names[i];
}
for(int i=0; i<MAX;i++)
{
delete [] names[i];
}
return 0;
}
You need to allocate space for each names[i] and when done, deallocate
also, changed the hardcoded 4 to MAX
something wrong with getline(), taking the words in correct but still the value of size remains 26.
I tried printing each time it takes in a character and all of them do print so itis taking in strings correctly, but not storing them?
I have attached the code below to refer
Ask me for the whole project if you need to refer what is going wrong if someplace else.
void TldPart::PreloadTLDs()
{
ifstream in(TLD_TEST_FILE);
if(in)
{
string tld;
for(int i =0; !in.eof(); i++)
{
getline(in,tld);
String myString = tld.c_str();
//cout << myString.GetLength() << endl;
for(int j=0; j<myString.GetLength();j++)
{
myString[j]=tolower(myString[j]);
}
//cout << myString << endl;
ValidTLDs.insert(pair<String,int>(myString,i));
//ValidTLDs[myString] = true; //if the map was bool
}
in.close();
cout << ValidTLDs.size(); //Printing the size //prints 26
}
}