Extracting a specific line from a file

Pages: 12
Stupid mistake.

Should be:
1
2
    long double alpha = calcAlphaYield(tempmaterialmap);
    long double Y = calcYield(alpha, tempmaterialmap);


instead of
1
2
    long double alpha = calcAlphaYield(const Element &tempmaterialmap);
    long double Y = calcYield(const Element &tempmaterialmap);


Still running into a problem. Now of scope :|
Last edited on
The whole code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <iostream>
#include <math.h>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <fstream>
#include <ostream>
#include <conio.h>
#include <limits>
#include <string>
#include <windows.h>
#include <stdio.h>
#include <ctime>
#include <map>

const std::string currentDateTime()
{
    time_t     now = time(0);
    struct tm  tstruct;
    char       buf[80];
    tstruct = *localtime(&now);
    strftime(buf, sizeof(buf), "%d-%m-%Y.%X", &tstruct);

    return buf;
}

long double calcAlphaYield(const Element &tempmaterialmap)
{
    long double M1;
    long double M2;
    long double alpha;

    alpha = 0.249*pow(M2/M1,0.56)+0.0035*pow(M2/M1,1.5);

    return alpha;
}

long double calcYield(const Element &tempmaterialmap)
{
    long double M1;
    long double M2;
    long double E;
    long double Us;
    long double alpha = calcAlphaYield(tempmaterialmap);
    long double Y;

    Y = (3/(4*pow(M_PI,2)))*alpha*((4*M1*M2)/(pow(M1+M2,2)))*(E/Us);

    return Y;
}



int main()
{
    Element tempmaterialmap;
        std::map<std::string, Element> Properties_Map;
        std::map<std::string, Element>::iterator it;
        std::string key = " ";

    std::ifstream myfile ("elements.txt");
    if (myfile.is_open())
    {
        while ( myfile >> tempmaterialmap.name >> tempmaterialmap.M1 >> tempmaterialmap.M2 >> tempmaterialmap.E >> tempmaterialmap.Us)
        {
            Properties_Map.insert ( std::pair<std::string, Element>(tempmaterialmap.name, tempmaterialmap) );
            std::cout << tempmaterialmap.name << '\n';
        }
        myfile.close();
    }

    else
    {
        std::cout << "Unable to open file";
    }

    std::cout << "Please enter abbreviated element name: ";
    std::cin >> key;

    it = Properties_Map.find( key );

    if (it != Properties_Map.end())
    long double alpha = calcAlphaYield(tempmaterialmap);
    long double Y = calcYield(alpha, tempmaterialmap);

    std::cout << "Y=" << Y;
    std::ofstream o("Yield.txt", std::ios::app);
    o << currentDateTime() << "\t" << Y << "\n" << std::endl;
}
Last edited on
closed account (48T7M4Gy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <math.h>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <fstream>
#include <ostream>
//#include <conio.h>
#include <limits>
#include <string>
//#include <windows.h>
//#include <stdio.h>
#include <ctime>
#include <map>
#include <iostream>

struct Element
{
    std::string name;
    int M1 = 0;
    double M2 = 0; //<--
    double E = 0;
    double Us = 0;
    double dummy = 0; // <--
    
    double calcYield()
    {
        double alpha = 0.249*pow(M2/M1,0.56)+0.0035*pow(M2/M1,1.5);
        return (3/(4*pow(M_PI,2)))*alpha*((4*M1*M2)/(pow(M1+M2,2)))*(E/Us);
    }
}; // <--

int main() // <--
{
    Element tempmaterialmap;
    std::map<std::string, Element> Properties_Map;
    std::map<std::string, Element>::iterator it;
    std::string key = " ";
    
    std::ifstream myfile ("elements.txt");
    if (myfile.is_open())
    {
        while ( myfile >>
               tempmaterialmap.name >>
               tempmaterialmap.M1 >>
               tempmaterialmap.M2 >>
               tempmaterialmap.E >>
               tempmaterialmap.Us >>
               tempmaterialmap.dummy // <--
               )
        {
            Properties_Map.insert ( std::pair<std::string, Element>(tempmaterialmap.name, tempmaterialmap) );
            std::cout << tempmaterialmap.name << '\n';
        }
        myfile.close();
    }
    
    else
    {
        std::cout << "Unable to open file";
    }
    
    std::cout << "Please enter abbreviated element name: ";
    std::cin >> key;
    
    it = Properties_Map.find( key );
    
    double Y = 0;
    
    if (it != Properties_Map.end())
        Y = it -> second.calcYield();
    
    std::cout << "Y=" << Y << '\n';
    
    //std::ofstream out("Yield.txt", std::ios::app);// <-- o is bad name
    //out << currentDateTime() << "\t" << Y << std::endl; // <-- currentdatetime ???
    
    return 0; // <--
}
closed account (48T7M4Gy)
This now works but there were a lot of changes I made so you need to look at it very closely. I have just about run about of time here so I will be quick.

1. I can't see why you need long doubles.
2. You only need one function
3. Look at how I included the function in the structure. That's important because you don't have to pass parameters. Look at my display() function if you aren't sure.
4. I added a few things with the data structure so I didn't have to change my file. You can delete to suit you data but remember the data and struct definitions must be compatible otherwise the input fails.
5. Also pow as a function is crap for squaring numbers x^2 = x*x is better.

let me know if you have any questions but recognise time is pressing. Good luck with it :)





Sorry, couldn't respond sooner, had to go back home from work.

1. Don't really know why i have them (long double)
2. I see that you combined the two calculations and put them inside a struct, which 'till now i though possible only with classes :|
2.1 I'd rather have them outside as i might use them with fixed values in some cases, but maybe that for later.
3. I am using pow(), because most of my exponents are not nice round numbers ;P and also this actually is easier for me to read.


As for currentDateTime() i simply need it for sorting the results.
closed account (48T7M4Gy)
That's OK by me, they are choices you have to make as the designer and all make sense. The one about time was just me being lazy.

One small point about the functions is to avoid having functions within functions if you can. In this case it was easy to combine alpha into the single function because it wasn't currently being used. Obviously you have other plans for it. :)
Point is to avoid ? Damn, i really like combining them. As in having many little functions (mostly calculations in my case) and then have a function that combines the results, prints them and saves to a file (the deepest burrowed function is like 4-5 functions deep :P).

Maybe you or someone can have a quick look at my main() and tell me if it's the proper way of doing thing or did i get i ass backwards.

But nevertheless i am extremely thankful for the help you offered me. Cheers!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include "crystal_header.h"

int main() //specific functions are in seperate files like 'preface.cpp' or 'datainput.cpp' 
{
    hello();
    int prefaceChoice = preface();
        switch (prefaceChoice)
        {
            case 1:
                {
                int calcChoice = mainCrystalSystemPreface();
                switch (calcChoice)
                {
                case 1: calcCubic(); break;
                case 2: calcTetragonal(); break;
                case 3: calcHexagonal(); break;
                case 4: calcRhombohedral(); break;
                case 5: calcOrthorhombic(); break;
                case 6: calcMonoclinic(); break;
                case 7: calcTriclinic(); break;
                }
                break;
                }
            case 2:
                {
                int lattParamChoice = mainLatticeParamPreface();
                    switch (lattParamChoice)
                    {
                        case 1: calcLatticeParamManual(); break;
                        case 2: calcFromFile(); break;
                    }
                    break;
                    }
            case 3:
                {
                int paschenChoice = mainPaschenPreface();
                switch (paschenChoice)
                    {
                    case 1: calcPaschenFull(); break;
                    case 2: calcPaschenDerivP(); break;
                    case 3: calcPaschenDerivD(); break;
                    }
                break;
                }
            case 4:
                {
                   calcYieldFromDatabase();
                   break;
                }
        }
    std::cout << "\n\nCalculate another (y) or shut the program down (any) ?";
    char rerun;
    std::cin >> rerun;
	if (rerun == 'y' || rerun == 'Y')
    {
        return main();
    }
    else
    {
        std::cout << "Press any key to exit" << std::endl;
    }
}


Probably should make a do-loop instead of return main();
Last edited on
closed account (48T7M4Gy)
Damn, i really like combining them.
Then that's OK, some of these things boil down to personal preferences. Keeping them as separate as possible (decoupling) makes the code easier to maintain and test when changes are made. Have no fear it's not the end of the world because sometimes there is little choice.

return main() is not on! BAD!

What you can do as one common solution is have a nested while loop, based on the outer loop relying on a bool keep_going or some other meaningfully named boolean to manage staying in the inner loop or quitting.

Or here's an unrelated sample of another way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>

void menu()
{
    std::cout << "1. Case 1\n";
    std::cout << "2. Case 2\n";
    std::cout << "q to quit\n";
}

int main()
{
    char selection = '0';
    
    menu();
    while (std::cin >> selection && tolower(selection) != 'q')
    {
        switch (selection)
        {
            case '1':
                std::cout << "Case 1\n";
                break;
                
            case '2':
                std::cout << "Case 2\n";
                break;
                
            default:
                std::cout << "Invalid choice\n";
                break;
        }
        menu();
    }
    
    std::cout << "Closing ...\n";
    
    return 0;
}



Last edited on
Closed it in a do-while loop as another switch would be too much i think. But thank you for that example.

1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
    //hello code//
    char rerun;
    do
        {
        //main body//
        std::cout << "\n\nCalculate another (y) or shut the program down (any) ?";
        std::cin >> rerun;
        }
    while(rerun == 'y' || rerun == 'Y');
}
Last edited on
closed account (48T7M4Gy)
That's the way. Maybe instead of || you can take the char one step further and convert the input to upper (or lower) case and have only one test?
I'll try doing that. Thanks for the suggestion. Will post my attempts, but not today. Have some pressing work to do. Cheers!
closed account (48T7M4Gy)
:)
I know I'm late to the party, but as a matter of suggestion, if your file is particularly large you can save a lot of time by deferring the line parsing to when you need it.

Read in the name and then the rest of line as-is.
When you look-up the name, check to see whether it has been parsed or not, and parse if necessary.

Hope this helps.
closed account (48T7M4Gy)
Maybe parse later, maybe sooner. It raises the question whether the <map> is any use. It would be if multiple element searches and calculations need to be done.

Of course and also, if the elements (without isotopes being considered) are only mentioned once then the maximum file length will only be about 118 lines so access time considerations might be easy going whatever methods are used and use of a map can be put down to good training. Only OP knows.
1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
    //hello code//
    char rerun;
    do
        {
        //main body//
        std::cout << "\n\nCalculate another (y) or shut the program down (any) ?";
        std::cin >> rerun;
        }
    while(rerun == 'y' || rerun == 'Y');
}


changed to

1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
    //hello code//
    char rerun;
    do
        {
        //main body//
        std::cout << "\n\nCalculate another (y) or shut the program down (any) ?";
        std::cin >> rerun;
        rerun = toupper(rerun);
        }
    while(rerun == 'Y');
}


As for parsing, max of two seperate elements (mostly metals) might be used (technological constraints, though alloys would present an interesing challenge). But the idea to load the whole data base into memory and then look up in RAM and not a file (HDD/SSD) will totally be faster, if i understand you, Duoas. But i doubt that will be a factor in this case. Or any case in the forseeable future :P

Edit. I should point out that the data base is incomplete (technological reasons). Some of the parameters will be loaded from a diffrent file, but that is for later (function arguments from structs (file1->struct1, file2->struct2 or struct1 if possible), everything decoupled, if possible, maybe few globals for physical constants,).

Edit2. Now to learn Qt and move the whole program there XD Mostly it's just for shiny, but will be useful for diagrams and plots.

aaaaaand the installer crashes on my work PC. Guess i'll have to wait for an upgrade.
Last edited on
closed account (48T7M4Gy)
All good by the sound of it.

Qt is quite a learning curve but appears to me so far a great way to go.

FWIW for plotting stuff, gnuplot is worth considering for plotting. It can be driven in a c++ environment AFAIK.
https://www.youtube.com/watch?v=GgO55NzBBgs

Cheers
Topic archived. No new replies allowed.
Pages: 12