I read some threads about importing and displaying data from files, but didnt find a case of actually using imported data as function arguments. Especially not with a case of mixed variables.
As i'd like to add that functionality to my learning program, i have a these questions:
//Data format is "int int int double double" per line, with multiple lines, but i'd start with just a single line and then i guess i'll use loop that looks for end of line or file
- is std::vector the best choice for it ? (as per advice on learncpp)
- unions are the only way to handle mixed types ?
- sub: two vectors/arrays/structs ?
- did i miss something ?
Thinking about it make me wonder if a class wouldnt be best as a "container", as there are several functions that need thoes variables.
is std::vector the best choice for it ? (as per advice on learncpp)
That depends on what you want to do with the data. You haven't specified what you want to do with the data once you've read it. If you don't need to accumulate the data while reading the file, there is no need for a vector.
unions are the only way to handle mixed types ?
What do you mean by "mixed types"? Is your file not a consistent format?
sub: two vectors/arrays/structs ?
??? - What are you trying to say?
it make me wonder if a class wouldn't be best as a "container"
Or a struct. I'd use a class if the data in a row represents some "object" that has member functions. I'd use a struct if it's just Plain Old Data (POD). This only difference between a class and a struct is the default visibility of members.
What i want it is to use the imported numbers in some calculations:
1 2 3 4 5 6 7 8 9 10 11 12 13
longdouble lattConstant(int h, int k, int l, longdouble d)
{
longdouble a;
a = sqrt((pow(h,2) + pow(k,2) + pow(l,2))*(pow(d,2)));
return a;
}
longdouble lattSpacCubic(int h, int k, int l, longdouble a)
{
longdouble d;
d = a/sqrt(pow(h,2)+pow(k,2)+pow(l,2));
return d;
}
and save the results to a file:
1 2 3 4 5 6 7 8 9 10 11
void calcLatticeParamManual()
{
int h = millerIndex('h');
int k = millerIndex('k');
int l = millerIndex('l');
longdouble d = lattSpacing();
longdouble a = lattConstant(h, k, l, d);
std::cout << "(" << h << k << l << ")" << "\t" << a << "\t" << d << std::endl; //shows result
std::ofstream o( "Lattice Parameters.txt", std::ios::app ); //create txt file with name and append
o << "hkl(" << h << k << l << ")\t a=" << a <<"A\t d_hkl " << d << "A" << std::endl;
}
That's the manual way (with some of input functions skipped). With a file, it'd be all automatic (at least that's the idea).
By mixed types i understand (int+double+char) for instance. I guess a struct can hold them, but i read that a vector needs something called a union and that i do not know yet.
That's sub: blah blah was broken, sorry. What i meant was should i maybe try two separate vectors (one for int, other for double).
If i didnt describe correctly my problem, i'll try again:
1. import data from file (format: int int int double double)
2. data goes into a table (struct, vector, something else)
Said variables will be used in some combinations in calculations.
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
usingnamespace std;
struct Data
{
int h,
k,
l;
double d,
a;
};
int main ()
{
vector<Data> data;
ifstream src ("YourFilename");
if (!src)
{
perror ("File error: ");
system ("pause");
exit (EXIT_FAILURE);
}
Data tmp;
while (src >> tmp.h >> tmp.k >> tmp.l >> tmp.a >> tmp.d)
{
data.push_back (tmp);
}
// process your vector here
system ("pause"); // remove if you don't use Visual Studio
return 0;
}
Hmmmm...
I have two equations using these parameters. Even better, second equation is using the result of the first and both values are needed. (i also noticed i pasted the wrong function above making you use 'a' and 'd' instead of 'wl' and 't')
First is:
1 2 3 4 5 6 7 8
longdouble lattSpacing()
{
longdouble wl = defineWaveLength();
longdouble t = doubleTheta();
longdouble d;
d =(wl/(2*sin(t)));
return d;
}
Second is:
1 2 3 4 5 6
longdouble lattConstant(int h, int k, int l, longdouble d)
{
longdouble a;
a = sqrt((pow(h,2) + pow(k,2) + pow(l,2))*(pow(d,2)));
return a;
}
The above functions should be called by another function, to save the results to a file.
Here's the manual version:
1 2 3 4 5 6 7 8 9 10 11
void calcLatticeParamManual()
{
int h = millerIndex('h');
int k = millerIndex('k');
int l = millerIndex('l');
longdouble d = lattSpacing();
longdouble a = lattConstant(h, k, l, d);
std::cout << "d_" << h << k << l << "=" << d << "[nm]\ta=" << a << "[nm]\t" << std::endl;
std::ofstream o( "Lattice Parameters.txt", std::ios::app );
o << "d_" << h << k << l << "=" << d << "[nm]\ta=" << a << "[nm]\t" << std::endl;
}
So i tried doing a version of the above for an automatic file input.
I made your function into a separate ().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
void getData()
{
vector<Data> data;
ifstream src ("YourFilename");
if (!src)
{
perror ("File error: ");
system ("pause");
exit (EXIT_FAILURE);
}
Data tmp;
while (src >> tmp.h >> tmp.k >> tmp.l >> tmp.a >> tmp.d)
{
data.push_back (tmp);
}
And placed it inside:
1 2 3 4 5 6 7 8 9
void calcLatticeParamAuto()
{
getData(); //this is the function you provided, Thomas1965
longdouble d = lattSpacing(); //this () and below call functions that calculate values that i want to know
longdouble a = lattConstant(Data.tmp.h, Data.tmp.k, Data.tmp.l, d);
std::cout << "(" << Data.tmp.h << Data.tmp.k << Data.tmp.l << ")" << "\t" << a << "\t" << d << std::endl; //shows result
std::ofstream o( "Lattice Parameters.txt", std::ios::app ); //create txt file with name and append
o << "hkl(" << Data.tmp.h << Data.tmp.k << Data.tmp.l << ")\t a=" << a <<"A\t d_hkl " << d << "A" << std::endl; //this saves to a file
}
Doesnt want to work.
(...)crystal_functions.cpp|220|error: expected primary-expression before '.' token|
Line 220 corresponds with long double a = lattConstant(Data.tmp.h, Data.tmp.k, Data.tmp.l, d);(line 5 in last code block).
As a side note, the struct is defined separately and everything is in the header.
All of it compiled. Now i need to figure out what does what and how to properly use it to import and calculate.
Thank you for this.
BTW. Where can i find a "c++ step by step guide to fill a struct from a file". Because i kinda sorta would like to understand what i'm doing here :P
// Function returns a vector of Data objects
std::vector<Data> LoadData(std::string file)
{
std::ifstream ifs(file.c_str()); // Open file with the filename given from the parameters
// May want to check for errors, did it actually open?
std::vector<Data> result; // Create an empty vector ready to fill with Data objects
Data d;
while(ifs) // While data can still be read
{
ifs >> d; // Thanks to overloading the fstream operators (std::istream& operator>>) we can skip the chaining (a >> b >> c >> d etc)
result.push_back(d); // Now the Data object is filled add it to the vector
}
return result; // Return the vector of Data objects ready for processing
}
bool SaveData(std::vector<Data>& data, std::string filename)
{
if(data.size() < 1) return 0; // No data
std::ifstream ifs(filename.c_str());
if(ifs) return 0; // Filename already exists
ifs.close();
std::ofstream ofs(filename.c_str());
// I can't give you the exact name for this it does have one, but basically "i" will equal each Data object in the vector as it loops through
for(auto i : data) ofs << i; // Again thanks to operating overloading no need to chain the output
return 1; // Success
}
I did do a post years back showing how to load and save data from files, it's a very common question. :]
EDIT: To use this, whenever you want to load a series of Data objects, just call LoadData("FileNameHere.txt");
Whenever you want to save a vector of data objects, call SaveData(DataVectorHere,"FileNameHere.txt");
Thank you. I will read into it. Especially that i need to know and feel the way around filling from file and moving that data around before i can head towards classes and what-not.