How to use ifstream - c++

I have a problem with my program which basically is a simple math program. It does some vector multiplication and vector matrix multiplication and it does work fine until i try to read data from a text. I can compile the program but when i try to execute it, I get the fault:" Dataname.exe does not work".
Here's my code. Do not consider the cins and couts
#include<iostream>
#include<cmath>
#include<vector>
#include"header.hpp"
#include<fstream>
using namespace std;
int main()
{
ifstream einlesen ("Zahlen.dat"); //function "einlesen" opens the file "Zahlen.dat".
if (einlesen) // Message if the file has been opend
cout<<"Daten wurden eingelesen"<<endl;
else {
cout<<"Konnte Daten nicht einlesen"<<endl;
return 99;
}
double a;
int n{0};
while ( einlesen >>a>>a>>a>>a>>a>>a>>a) n++;//Loop copys datas on a
einlesen.clear();//stops the loop after the last data is copied.
einlesen.seekg(0, ios_base::beg);//??
vector<double> vecein(n), vecein1(n),Matrixein(n);
for (a = 0;a<n;a++);//copys datas to a vector further calculations
{
einlesen>>vecein.at(a);
einlesen>>vecein1.at(a);
einlesen>>Matrixein.at(a);
}
double Matrix1[9]; //defining my Matrix and the coordinates of my vectors.
double x,y,z,x_1,x_2,x_3;
vector<double> vec(3);
vector<double> vec1(3);
// Old code where I read the data with `cin`:
/*cout<<"Geben Sie die x Koordinaten ein:"<<endl;
cin>>vec[0];
cin>>vec1[0];
cout<<"Geben Sie die y Koordinaten ein:"<<endl;
cin>>vec[1];
cin>>vec1[1];
cout<<"Geben Sie die z Koordinaten ein:"<<endl;
cin>>vec[2];
cin>>vec1[2];
cout<<"Geben Sie eine Matrix ein"<<endl;
cin>>Matrix1[0]>>Matrix1[1]>>Matrix1[2]>>Matrix1[3]>>Matrix1[4]>>Matrix1[5]>>Matrix1[6]>>Matrix1[7]>>Matrix1[8];
cout<<"Vektor1:<"<<vec[0]<<","<<vec[1]<<","<<vec[2]<<">"<<endl;
cout<<"Vektor2:<"<<vec1[0]<<","<<vec1[1]<<","<<vec1[2]<<">"<<endl;
vector<double> Addition(3);
Addition = Vektoraddition(vec,vec1);
cout<<"Addition:"<<"<"<<Addition[0]<<","<<Addition[1]<<","<<Addition[2]<<">"<<endl;
double Skalarprodukt;
Skalarprodukt = Skalarpr(vec,vec1);
cout<<"Skalarprodukt:"<<Skalarprodukt<<endl;
vector<double> kreuzprodukt(3);
kreuzprodukt = Kreuzprodukt (vec,vec1);
cout<<"Kreuzprodukt:"<<"<"<<kreuzprodukt[0]<<","<<kreuzprodukt[1]<<","<<kreuzprodukt[2]<<">"<<endl;
vector<double> MatrixVektor(3);
MatrixVektor = Matrix_vektor (Matrix1, vec);
cout<<"Matrix*Vektor:"<<"<"<<MatrixVektor[0]<<","<<MatrixVektor[1]<<","<<MatrixVektor[2]<<">"<<endl;*/
ofstream ausgabe ("Ausgabe.dat");//write the data on Ausgabe.dat
for (int i = 0; i < a; i++)
{
ausgabe << "(" << vecein[i] << "," << vecein1[i] << "," << Matrixein[i]<<")" << endl;
}
return 0;
}
it's written in German so I don't wonder about the variable names. My problem is that I don't really understand what I'm doing in the while loop. Zahlen.dat is a file similar to 1 2 3 4 5 6 7... and Ausgabe.dat is an empty file. Actually it does write in Ausgabe.dat because it tells me that the content has changed but when I reload the file it's still empty.

I've tried your advice but it still doesn't work. I did not change the way I read my datas because I wanted to see if it works first.
Here is my error message:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 10) >= this->size() (which is 10)
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
My code looks like this right now:
int main()
{
ifstream einlesen ("Zahlen.dat");
if (einlesen)
cout<<"Daten wurden eingelesen"<<endl;
else
{
cout<<"Konnte Daten nicht einlesen"<<endl;
return 99;
}
double a;
int n{0};
while ( einlesen >>a>>a>>a>>a>>a>>a>>a) n++;
{
einlesen.clear();
einlesen.seekg(0, ios_base::beg);
vector<double> vecein(n), vecein1(n),Matrixein(n);
int b;// new variable of type int.
for (b = 0;b<n;b++);
{
einlesen>>vecein.at(b);
einlesen>>vecein1.at(b);
einlesen>>Matrixein.at(b);
}
ofstream ausgabe ("Ausgabe.dat");
for (int i = 0; i < b; i++)
{
ausgabe << "(" << vecein[i] << "," << vecein1[i] << "," << Matrixein[i] <<")" << endl;
}
}
return 0;
So I basically only changed the variable of the loop.
Yes the programm did work when I used to get the Data with cin.
I really have no idea why the programm is not working!

There are several things in the first code sample that should be done differently. The program first opens the file, and counts the number of blocks of 7 numbers in the file in variable n. Then the file pointer is reset, three vectors are created with a size of n, and the first n numbers are read into the vector from the file. But: You don't have to know the number of entries in a vector beforehand, so there is no need to read the file twice. Just use vector::push_back to add the numbers.
Second problem: In the loop to read the numbers, a is used as the loop variable, which is a double. The incrementing of a double could result in a one-off error, thus explaining your crash.
I'm also not sure the logic is correct: It seems you expect the file to have several (n) lines of numbers with 7 numbers each, but you then read the first n numbers. Say you have 10 lines, then you read the first line and three numbers of the second line into your vectors, also you might have wanted to read all numbers or maybe the first of each line (or even a 3d structure).
What about the second code sample, where you read from cin? Did that one work? It might help if you explained what you are trying to do, it seems there are vectors in the file, that you want to take the vector product (Kreuzprodukt) of? What is their layout in the file, are they written in lines or columns?
EDIT: The cause for the crash seems to be this line:
for (a = 0;a<n;a++);
{
einlesen>>vecein.at(a);
...
Notice the ; after the loop. This causes the loop to first run without any statement, and the part within brackets runs afterwards, when the loop condition is no longer fulfilled, i.e. a is already equal to n.

Related

My program doesn't end

I'm new too c++ and I had to design a program that determines the first four triangular square numbers and the output is exactly how I want it to be, but it wont quit after its printed the first four. I can't figure out what it could be. I can't CTRL C because I will get points taken off. What is the issue here?
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
//Prints name line
cout<<"*********** BY: ********"<<endl;
//Initializing
const int HOW_MANY=4;
int num=1;
int tsn=0;
int z=1;
int x=0;
//How many TSN it will find and be printed
while (x<=HOW_MANY)
{
//
int sum=0;
for (int y=0;y<512;y++)
{
sum+=y;
tsn=pow(num,2);
//Tests if the numbers are TSN
if ((sum==tsn) || (num+1)/sqrt(num)==sqrt(num))
{
//Prints 1-HOW_MANY TSN and what they are
cout<<"Square Triangular Number "<< z <<" is: "<< tsn <<endl;
z++;
x++;
}
}
num++;
}
return 0;
}
If x = 0 then instead of while (x<=HOW_MANY) you need write while (x<HOW_MANY).
x begins at 0. Every time you find and print a number it gets incremented. You'll continue this, so long as x<=HOW_MANY.
You say your program finds 4 numbers but keeps running. After 4 hits, x will be 4. Is 4 <= 4? The answer is yes, so your program keeps running.
Either change the condition to x < HOW_MANY, or initialize x to 1.
EDIT
Did a little leg work, it turns out the sum of all the numbers in the range [1,512] is 131328. The 5th square triangle number is 1413721.
This means after you find the fourth triangle number, you will never sum high enough to find the next one. This will result in the infinite loop you're seeing.
The answer above is still the correct fix, but this is the reason you end up with an infinite loop.
for should be used for iteration and while should be used for condition testing.
The problem, as has been noted, is that your x condition variable is never being incremented to get you out of the outer loop. That's a logic error that can be avoided by using the appropriate control structure for the job.

Write/Read struct array data table C++

Im fairly new to c++ and I've spent about six hours on this, sadly with no result.
im trying to do the following. (for my own practice)
Make a navigation menu like in cmd. #done
Create two structs with the concept of "uml aggregation" #done
Make function for input, output, sort by a value, etc. #done
Write everything to a file #Struggling from this point.
Read back from the file.
Use the data later(sort by name, delete last object, add new...etc)
I have a massive code that I think will be silly to post (and a waste of time) so I'll just post a simpler version.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string.h>
using namespace std;
struct man{
char name[20];
int age;
};
struct group{
man* men[3];
};
void fill( man &y);
void show( man &y);
void input(group &x, man &y);
void output(group &x, man &y);
int main(){
man q;
group w;
input(w, q);
cout<<endl;
output(w, q);
ofstream w1file("B.dat");
for (int i=0; i<2; i++){
w1file.write((char*) &w.men[i]->name, 20);
w1file.write((char*) &w.men[i]->age, sizeof(int));
}
w1file.close();
ifstream r1file("B.dat");
while(r1file.good()){
r1file.read((char*) &w.men[0]->name, 20);
r1file.read((char*) &w.men[0]->age, sizeof(int));
r1file.read((char*) &w.men[1]->name, 20);
r1file.read((char*) &w.men[1]->age, sizeof(int));
}
output(w, q);
r1file.close();
system("pause");
return 0;
}
void fill( man &y){
gets(y.name);
cin>>y.age;
cin.ignore();
}
void show( man &y){
cout<<y.name<<endl;
cout<<y.age<<endl;
}
void input(group &x, man &y){
x.men[2]= new man[2];
for (int i=0; i<2;i++){
fill(y);;
x.men[i]= new man(y);
}
}
void output(group &x, man &y){
for (int i=0; i<2;i++){
show(*x.men[i]);
}
}
if i remove the writing part, then the program just crashes as soon as i press run.
ive tried it like this, and with file>>"variable"... ive tried it with only first element...tried to copy the whole thing to an array, write the array and then read it, but nothing works :(
I also want it to output the data in the file like this: (example)
#in the txt, dat, whatever
John 21
Pier 18...etc
So i can edit the data directly from the written file.
but what im getting is this:
John н# А…J { Adam ed н# А…J Х
My initial idea was to make a program that outputs data to files in the form of tables(hope you understand me)
exmpl.
name1 age1 wage1 married/not married1
name2 age2 wage2 married/not married2
name3...age3...etc
Can someone from heaven please help me with this and if possible explain what im doing wrong?
for (int i; i<2; i++){
Looks at this line, until you see the problem. Keep looking at it, until you do.
Hint: what do you expect the first value of i to be, in this loop?
P.S.: Why are you allocating a single instance of man, for men[0] and men[1], and two instances of man, for men[2]?
There are several problems:
The writing for uses an uninitialized variable i, so that it starts with an undetermined value. Try :
for (int i=0; i<2; i++){ //i=0 !!
Then you write binary data in a file open in the default text mode. This can, depending on the binary value and the operating system alter what is effectively written in the file. So:
ofstream w1file("B.dat", ios::binary); // binary mode instead of text mode
The same applies of course to the reading stream.
Note that you could have from 0 to 3 men in the group. It would be wise to write at the beginning of the group the number of items. So when reading the group you could first read the number of items to be expected and loop until you have read them all. Your current reading loop is weird, as it will read the file and constantly overwrite the 2 first mens (if there are more data in the file).
The way you could properly read would be:
const int maxmen=3;
for (int i=0; i<maxmen && r1file.read((char*) &w.men[i]->name, 20)
&& r1file.read((char*) &w.men[0]->age, sizeof(int)); i++)
cout << "Successfuly read item "<<i<<endl;
}
Note also that this code is heavily leaking memory.

Faster File Operations C++

So I am making a renderer in c++ and opengl for a class of mine. I am making an animation program for extra credit that will change values in a text file right before my renderer reads them in each frame. My problem is that this section of code isn't writing fast enough
while (clock() < time_end)
{
timeStep = clock() + fps * CLOCKS_PER_SEC;
for(int k=0; k < currOps.size(); k++)
{
// increase/decrease each set once for the current timestep
// a case for each operation
int pos = currAxis[k];
if(currOps[k] == "loc")
{
opsFile[8+pos] = patch::to_string(atof(opsFile[8+pos].c_str()) + locScale[pos-1]*timeAdjust);
//edit this value by loc adjust
}
else if(currOps[k] == "rot")
{
opsFile[4+pos] = patch::to_string(atof(opsFile[4+pos].c_str()) + rotScale[pos-1]*timeAdjust);
//edit this value by rot adjust
}
else if(currOps[k] == "scl")
{
opsFile[pos] = patch::to_string(atof(opsFile[pos].c_str()) + sclScale[pos-1]*timeAdjust);
//edit this value by scl adjust
}
}
currFile.close(); //save file and restart so we don't append multiple times
currFile.open(files[location[0]].c_str(), ofstream::out); // so we can write to the file after closing
for(int j=0; j <opsFile.size(); j++)
{
// update the file
currFile << opsFile.at(j);
currFile << "\n";
}
while(clock() < timeStep)
{
//wait for the next time steps
}
}
Specifically currFile operations at the end. If I take the currFile operations out it will run at the desired fps. FPS is set to .033 so that it does 30 fps. Also it will run fast enough when fps = 0.1. Any optimizations would be great. If need to see any other part of my code let me know and I will upload. The whole thing is around 170 lines.
currOps, files, and opsFile are vectors of strings
sclScale, rotScale, and locScale are vectors of doubles
currAxis is vectors of ints
Here are some general changes which may help:
I would convert the curOps to an enum rather than a string (save you the string comparisons.) Looks like you should pre-process that container and build a sequence of enums (then your code in the loop becomes a switch)
Don't use vector<string> for curOps, simply read the floats from the file and write the floats out - this will save you all those pointless conversions to and from string. If you wanted to take it further, convert the file to binary (if you are allowed by the exercise), and store a simple structure which contains the floats you need and use memory mapped files (you don't need boost for that, it's straight forward just using mmap!)
Before going down the mmap route - try the float read/write from file. For example, let's say that each "row" in your file corresponds to something like the following:
struct transform {
double x, y, z;
};
struct op {
transform scale, rot, loc;
};
Declare a bunch of stream in/out operators for these (for example:
std::ostream& operator<<(std::ostream& os, const transform& tx) {
return os << tx.x << ' ' << tx.y << ' ' << tx.z;
}
std::istream& operator>>(std::istream& is, transform& tx) {
return is >> tx.x >> tx.y >> tx.z;
}
(a similiar set will be required for op)
Now your vector is std::vector<op>, which you can easily stream in and out from your file, for example, to read:
op i;
while(file >> i) { curOps.push_back(i); }
To write:
for (auto o : curOps) file << o << '\n';
If this is still not enough, then mmap (btw - it's possible on windows too: Is there a memory mapping api on windows platform, just like mmap() on linux?)
Try using the functions in stdio.h instead. iostreams are terribly inefficient.
In your case all you will need is fseek() ... fputs(). Avoiding reopening the file each time should actually help quite a lot.

grabbing data sets from a file with an arbitrary amount of spaces

**No direct answers or code examples please, this is my homework which i need to learn from. I'm looking for help concerning the algorithm i need to develop.
I seem to be having a logic error in coming up with a solution for a portion of my class work, the program involves multiple files, but here is the only relevant portion:
I have a file PlayerStats that holds the stats for a basketball player in:
rebounds
points
assists
uniform #
my initial reaction would be to create a while loop and read these into a temporary struct that holds these values, then create a merge function that merges the values of the temp struct with the inital array of records, simple enough?
struct Baller
{
//other information on baller
int rebounds;
int assists;
int uniform;
int points;
void merge(Baller tmp); //merge the data with the array of records
}
//in my read function..
Baller tmp;
int j = 0;
inFile << tmp.uniform << tmp.assists << tmp.points << tmp.rebounds
while(inFile){
ArrayRecords[j].merge(tmp);
j++;
//read in from infile again
}
The catch:
The file can have an arbitrary number of spaces between the identifiers, and the information can be in any order(leaving out the uniform number, that is always first). e.g.
PlayerStats could be
11 p3 a12 r5 //uniform 11, 3 points 12 assists 5 rebounds
//other info
OR
11 p 3 r 5 a 12 //same exact values
What I've come up with
can't seem to think of an algorithm to grab these values from the file in the correct order, i was thinking of something along these lines:
inFile << tmp.uniform; //uniform is ALWAYS first
getline(inFile,str); //get the remaining line
int i = 0;
while(str[i] == " ") //keep going until i find something that isnt space
i++;
if(str[i] == 'p') //heres where i get stuck, how do i find that number now?
else if(str[i] == 'a')
eles if(str[i] = 'r'
If you're only going to check one letter, you could use a switch statement instead of if / else, that would make it easier to read.
You know where the number starts at that point, (hint: str[i+1]), so depending on what type your str[] is, you can either use atoi if its a char array, or std::stringstream if it's an std::string.
I'm tempted to give you some code, but you said not too. If you do want some, let me know and I'll edit the answer with some code.
Instead of using a 'merge' function, try using an std::vector so you can just push_back your structure instead of doing any 'merging'. Besides, your merge function is basically a copy assignment operator, which is created by the compiler by default (you don't need to create a 'merge' function), you just need to use = to copy the data across. If you wanted to do something special in your 'merge' function, then you should overload the copy assignment operator instead of a 'merge' function. Simples.
Do something like that:
int readNumber () {
while isdigit (nextchar) -> collect in numberstring or directly build number
return that number;
}
lineEater () {
Read line
skip over spaces
uniform=readNumber ();
haveNum=false;
haveWhat=false;
Loop until eol {
skip over spaces
if (isdigit)
number=readNumber ();
skip over spaces
haveNum=true;
else
char=nextChar;
haveWhat=true;
if (haveChar and haveNum) {
switch (char) {
case 'p' : points=number; break;
...
}
haveNum=false;
haveWhat=false;
}
}
or, if you are more ambitous, write a grammar for your input and use lex/yacc.

Program Crashes when I try to compare two strings in c++?

int removeContact(Contact *newPtr, int runningTotal)
{
//define variables
string remove;
int next;
//prompt user for name they wish to remove
cout << "Enter the name you would like to delete (Last name first): ";
cin.ignore();
getline(cin, remove);
for (int t=0; t<=runningTotal; t++)
{
if (remove.compare(newPtr[t].name) == 0)
{
//calls function moveArrayElements function
moveArrayElements(newPtr, runningTotal, t);
//decrement runningTotal
runningTotal--;
//prompt user contact was found
cout << "Contact was found and deleted!";
next=1;
}
}
if(next!=1)
{
cout<< "ERROR: Contact was not found!";
}
return runningTotal;
}
This function is apart of a larger c++ program that is designed to manage a persons contact information. This function is suppose to remove a contact.
The problem I'm have is with the if (remove.compare(newPtr[t].name) == 0) statement. When my program gets to this part of the code it will crash without giving any errors. I tried straight up comparing both the stings with == operator, but this still results in a crash of my program...
Also, what make this so strange is that this code works perfectly when the function is called while my program is running with the contact that I'm trying to remove not stored in a text file.
However, when I close my program, and load my contact information from the text file, my program will crash... I know that my program is reading the file into the proper string array because I have a print function, so I know that all of my contacts are being transferred into the proper structure arrays...
Any ideas on how I can fix this? Any help would be appreciated! Thanks
UPDATE: I took the suggestions in the comments and changed my for loop to
t<runningTotal;
However, when I do this my program doesn't crash, but it wont's compare the strings...
If runningTotal is the size of your array, then the range of valid elements is [0, runningTotal). In the below code, you're looping up to runningTotal inclusive, when there isn't a valid Contact object there:
for (int t=0; t<=runningTotal; t++)
{
if (remove.compare(newPtr[t].name) == 0)
Therefore when you go and dereference newPtr[t], for t = runningTotal and then try and get the name element, you'll be causing undefined behaviour and may cause a crash.
Try changing t<=runningTotal to t < runningTotal to see if the problem goes away.
Also, is there a reason why you're using arrays as opposed to an std::vector?
i guess the for statement should be:
for (int t=0; t<runningTotal; t++)