Import from file, calculate and repeat

Pages: 12
I'm looking for a way of getting to automatically make some calculations. The set of input variables is:
- constant in their number (5)
- in a txt file
- has the following format (whitespace is SPACE but can be TAB):

1
2
double double int int int
//ad infinitum, each in a new line 


I have tried doing research, but most cases relate to single line. In my case the number of lines will be => 1. I think the problem description is like this:


- open file //left open untill end of data (check by cin.fail, i think)
- get line_1 (string, but not sure how to move each parameter from file into the program (into vector?))//with added function to skip a line if it is not in proper format
- do calculations_1 (there are diffrent equations using diffrent variables, so i'm thinking that maybe filling a vector with said variables is best and then simply construct equations that use vector_name[variable_name]
- save results and input into a file (or just the results), each line starting with date and time
- results must have a precise date/time
- clear vector (no clue how to do it)
- get line_2
- repeat untill end of lines
- integrate into main program
- make it graphic XD


I'd like someone to weigh in on if this approach is reasonable or perhaps to point me towards a tutorial with stuff like that. 13.6 on LearnCpp.com is great and all but i think my problem is too specific and/or convoluted or plain badly thought out.
Last edited on
closed account (48T7M4Gy)
Give it a go. You have a plan which is more you can modify it as you go.
Last edited on
Thank you. I failed, of course.

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
#include <iostream>
#include <fstream>
#include <ostream>
#include <stdio.h>

int main()
{
    long double wl,a;
    int h,k,l;
    std::string line; //can be commented out, but i still won't work
    std::ifstream file ("params.txt", std::ios::in); //added std::ios::in just in case; thought it'd help, but nope
    if (file.is_open())
    {
    while (file >> wl >> a >> h >> k >> l) //having 'line' here produces an error (below)
        {
        std::cout << line << '\n';
//alternatively std::cout << wl << a << h << k << l << '\n'; so 'line' isn't used
        }
    file.close();
    }

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

  return 0;
}


I put the params.txt within every folder (main, bin and with exe; using Code::Blocks) and i get cannot open file from else.

Error with 'line' in line 14:

[...]\main.cpp|14|error: could not convert '(((void)(&(&(&(& file.std::basic_ifstream<char>::<anonymous>.std::basic_istream<_CharT, _Traits>::operator>><char, std::char_traits<char> >((* & wl)))->std::basic_istream<_CharT, _Traits>::operator>><char, std::char_traits<char> >((* & a)))->std::basic_istream<_CharT, _Traits>::operator>><char, std::char_traits<char> >((* & h)))->std::basic_istream<_CharT, _Traits>::operator>><char, std::char_traits<char> >((* & k)))->std::basic_istream<_CharT, _Traits>::operator>><char, std::char|
Last edited on
closed account (48T7M4Gy)
line 6 std::cout << 1s .
Last edited on
Crap. Made a mistake in data within the file. It was 9 8 1 2 3, whereas it should have been 9.0 8.0 1 2 3 (just for testing). Nice catch.
Strange things are now happening. The program works but only if i run it independently from CodeBlocks. Anyway, with this mistake i will have to figure out a way of weeding out such mistakes in the future with some kind of validating function, but that's for later.

So now off to trying to figure out what kind of 'thing' to use to store these numbers. One that can be cleared and reused.
Last edited on
closed account (48T7M4Gy)
The data will function in future.
Last edited on
Shame this won't work :P

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "header2.h"

int main()
{
    struct Vars
    {
        double wl, a;
        int h, k, l;
    };

    std::ifstream file ("params.txt");
    Vars set1 {file >> Vars.wl >> Vars.a >> Vars.h >> Vars.k >> Vars.l};

return 0
}


I think i'll have to find a book or something, because though i found many great examples on how to fill a struct, none explain what each symbol or name mean.
Back to google.
closed account (48T7M4Gy)
Slightly off topic but you should use longer variable names.
closed account (48T7M4Gy)
Should declare a variable Vars vbl; then it is vbl :)
Last edited on
What is vbl ?

Edit: Why longer ?
Last edited on
closed account (48T7M4Gy)
short or long
Last edited on
Ok. Made it to reading numerous lines.

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
#include <iostream>
#include <fstream>

int main()
{
    struct Vars
    {
        double wl = 0, a = 0;
        int h = 0, k = 0, l = 0;
    };

    std::ifstream file ("params.txt");
    Vars vbl;

    do
        {
            if (file.is_open())
            {
            while (file >> vbl.wl >> vbl.a >> vbl.h >> vbl.k >> vbl.l )
            {
                std::cout << vbl.wl << ' ' << vbl.a << ' ' <<  vbl.h << ' ' << vbl.k << ' ' << vbl.l << ' ' << '\n';
            }
            }
            else std::cout << "Unable to open file";
        }
    while (std::cin.eof());

    file.close();
    std::cin.sync();
    std::cin.get();

    return 0;
}


In some places i read that EOF can give an out-of-bounds error. Didn't happen in my test case, but is using while (!std::cin.fail()); a better idea ?
And i guess i will have to move every calculations related function inside of the do-while loop.
Hmmm. This isn't working out so well. Pointers would be better ?

1
2
3
4
5
6
7
8
9
10
#ifndef H2_H_INCLUDED
#define H2_H_INCLUDED

#include <iostream>
#include <fstream>

struct Vars;
double testCalc(&sample);

#endif // H2_H_INCLUDED 


1
2
3
4
5
6
7
8
#include "h2.h"

double testCalc(&sample)
{
    double x;
    x = vbl.wl*vbl.a;
    return x
}


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
#include "h2.h"

int main()
{
    struct Vars (&sample)
    {
        double wl = 0, a = 0;
        int h = 0, k = 0, l = 0;
    };


    std::ifstream file ("params.txt");
    Vars vbl;

    do
        {
            if (file.is_open())
            {
            while (file >> vbl.wl >> vbl.a >> vbl.h >> vbl.k >> vbl.l )
            {
                std::cout << vbl.wl << ' ' << vbl.a << ' ' <<  vbl.h << ' ' << vbl.k << ' ' << vbl.l << ' ' << '\n';
                double testCalc();
                std::cout << x;
            }
            }
            else std::cout << "Unable to open file";
        }

    while (!std::cin.fail());

    file.close();
    std::cin.sync();
    std::cin.get();

    return 0;
}
Last edited on
closed account (48T7M4Gy)
next step in the plan you are going to do some :)
Last edited on
One thing that seems to have gotten lost: the requirement that 5 numbers appear on a single line. Here's how to handle that. I've also shown how to pass a Vars struct to a function. Note that I'm passing it as a const reference. If you passed it by value then the program would have to copy all the params each time it called the function.
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
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>

struct Vars
{
    double wl = 0, a = 0;
    int h = 0, k = 0, l = 0;
};

double testCalc(const Vars &params)
{
    double x;
    x = params.wl*params.a;
    return x;
}



int
main()
{
    std::ifstream file("params.txt");
    Vars vbl;
    std::string line;
    unsigned lineNum = 0;
    
    if (!file) {
	std::cerr << "Can't read params.txt\n";
	return 1;
    }
    
    while (getline(file, line)) {
	++lineNum;
	std::istringstream is(line);
	if (is >> vbl.wl >> vbl.a >> vbl.h >> vbl.k >> vbl.l) {
	    std::cout << line << ": testCalc=" << testCalc(vbl) << '\n';
	} else {
	    std::cerr << "Can't parse line " << lineNum << ": " << line << '\n';
	}
    }
    while (std::cin.eof());

    file.close();
    std::cin.sync();
    std::cin.get();

    return 0;
}

@kemort
It's for the program to stop without closing the console window (system() BAD).
The next step is to use the variables (from a single line) to calculate things, then move to the next line and calculate again with the new set.
I do not need to store things within the program itself, but learning how to do it will be useful. I will do that after i figure out the rest. And storing into a file is the last think on the list.

@dhayden
Thank you for the example, i will look into it.
Last edited on
closed account (48T7M4Gy)
The next step is to use the variables
Last edited on
I want to use a struct, so i can learn how to use a struct :P

Thank you for your great examples. I'm half way through to implementing this into my program. But i do have some issues with what i did.

#1 - line 25 doesn't work: i removed params.txt to check and i got the console window with a crapload of random characters being shown moving very fast
#2 - line 42 doesn't work: adding a bad line (a b c d e) did not cause an error to show up (char's in place of double's and int's)
#3 - line 49 also doesn't work, nothing shows up

(Also change 'a' to 't' as i should have been from the start).

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
#include <iostream>
#include <fstream>
#include <cmath>
#include <math.h>

int main() //everything in this will be elsewhere, true main() has only function calls
{
    struct Vars
    {
        double wl = 0, t = 0;
        int h = 0, k = 0, l = 0;
    };

    std::ifstream file ("params.txt");

    Vars vbl;
    int lineNum = 0;
    double d;
    double a;

    do
        {
        if (!file.is_open())
            {
            std::cerr << "Unable to locate file. File params.txt must be in the same folder as Crystal.exe"; //Crystal.exe is name of this program.
            }
        if (file.is_open())
            {
        while (file >> vbl.wl >> vbl.t >> vbl.h >> vbl.k >> vbl.l )
            {
            lineNum++;
            d=(vbl.wl/(2*sin(vbl.t))); //will be moved to a separate file for calculating functions; use dhayden example
            a=sqrt((pow(vbl.h,2) + pow(vbl.k,2) + pow(vbl.l,2))*(pow(d,2))); //ditto; shame cant paralelize
            std::cout << "Line " << lineNum << " input: " << vbl.wl << " nm" << vbl.t << " [deg/2deg/rad]" <<  vbl.h << " h" << vbl.k << " k" << vbl.l << " l" << "\n"; //standarize t units
            std::cout << "Line " << lineNum << " results: d=" << d << "nm a=" << a <<"nm \n";
            std::ofstream o( "Lattice Parameters Auto.txt", std::ios::app );
            o << "Line " << lineNum << "from DATE " << "d_" << vbl.h << vbl.k << vbl.l << "=" << d << "[nm]\ta=" << a << "[nm]\t" << std::endl; //need to add date
            }
            }
        else
            {
            std::cerr << "Can't parse line " << lineNum;
            }
        }

    while (!std::cin.fail());

    file.close();
    std::cout << "Finished";

    return 0;
}
Last edited on
Indent your code to match the actual block structure and the problems will be more obvious.
Fixed the first problem. Line 25 was in a loop :P
Edit: I think it's properly indented now. Is it ?

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
#include <iostream>
#include <fstream>
#include <math.h>

int main() //everything in this will be elsewhere, true main() has only function calls
{
    struct Vars
        {
        double wl = 0, t = 0;
        int h = 0, k = 0, l = 0;
        };

    std::ifstream file ("params.txt"); //make user definable

    Vars vbl;
    int lineNum = 0;
    double d;
    double a;

    do
        {
        if (!file.is_open())
            {
            std::cerr << "Unable to locate file. File params.txt must be in the same folder as Crystal.exe"; //Crystal.exe is name of this program.
            break;
            }
        else
            {
            if (file.is_open())
                {
                while (file >> vbl.wl >> vbl.t >> vbl.h >> vbl.k >> vbl.l )
                    {
                    lineNum++;
                    d=(vbl.wl/(2*sin(vbl.t))); //will be moved to a separate file for calculating functions; use dhayden example
                    a=sqrt((pow(vbl.h,2) + pow(vbl.k,2) + pow(vbl.l,2))*(pow(d,2))); //ditto; shame cant paralelize
                    std::cout << "Line " << lineNum << " input: Wavelenght = " << vbl.wl << "[nm] - Double theta = " << vbl.t << "[2deg] " << "(hkl)_(" <<vbl.h << vbl.k << vbl.l << ")\n"; //standarize t units
                    std::cout << "Line " << lineNum << " results: d=" << d << "nm a=" << a <<"nm \n";
                    std::ofstream o( "Lattice Parameters Auto.txt", std::ios::app );
                    o << "Line " << lineNum << "from DATE " << "d_" << vbl.h << vbl.k << vbl.l << "=" << d << "[nm]\ta=" << a << "[nm]\t" << std::endl; //need to add date
                    }
                }
            else
                {
                std::cerr << "Can't parse line " << lineNum;
                }
            }
        }
        while (!std::cin.fail());

    file.close();
    std::cin.sync();
    std::cin.get();
    std::cout << "Finished";

    return 0;
}
Last edited on
Pages: 12