Input from a File and reading out into a graph

I have been trying to get the top portion of my program to correctly read in 3 separate arrays from a .txt file and after trying a few different ways I cannot get it to work. The professor suggested I use a for loop to read in the data however each time I try to adjust the for loop and going to run it the programs stops working and shuts down.
The code I have right now is
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
using namespace std;
#include<iostream>
#include<cmath>
#include<fstream>
#include<iomanip>


void noisedata(int, double[], double[], double[]);

int main() {

char skiplines [220];
int i;
double dc[4], gt[25], snr[25];
double dval;

cout<<"Linear regression results of snr  vs. gt:  snr = gt*slope + intercept\n\n";
cout<<"dc (atoms/cc*10e-17)     slope     intercept     r-squared\n";
cout<<"----------------------------------------------------------------\n";
ifstream indata("noisedata.txt");
for (i=0;i<43;i++)
{
    indata.getline (skiplines, 220);
}   
for (i=0;i<33;i++)
{
    indata>>dc[i]>>gt[i]>>snr[i];
}
//cout<<setprecision(2)<<setw(8)<<dc[i]<<setprecision(2)<<setw(8)<<a[i]<<
//setprecision(2)<<setw(8)<<b[i]<<setprecision(6)<<setw(8)rsquared[i]<<endl;


cout<<"Please input a design value for snr between 1 and 100:   \n";
cin>>dval;       //dval is double value




system("pause");
return 0;
}


void noisedata(int i, double a[], double b[], double rsquared[])
//void function, to determine the slopes (a[i]) intercepts (b[i]), and rsquared[i] 
//of the best fit lines of snr(y) vs. gt(x) for each value of dc (There are FIVE values of DC)
//        the void fun. passes by reference arrays a[i], b[i], rsquared[i] and their values back to the main program.
//        the void function prints out a well formatted screen to a file named results.txt

//snr[x]=a[i]gt+b[i]
//gt[i]=(snrinput - b[i])/a[i]
{                  
double snr[i], gt[i];
for(i=0;i<4;i++)
                {
                a[i]=(snr[i])/(gt[i]);
                b[i]=gt[i]*a[i];
                rsquared[i]=


I know the program is only partially done but if someone could steer me near how to correctly input the data it would help with the rest of my program.

The input data file looks like this..
This data file is arranged as follows
The number on a lone line is the dopant concentration in atoms/cucm x 1.00E-17
The next five lines are the gt in nanometers
followed by the signal to noise ratio in decibels
1.1
2 35.1
2.2 36.3
2.4 37.2
2.6 38.1
2.8 39.5
1.2
2 37.2
2.2 39.5
2.4 41.2
2.6 42.3
2.8 46.2
1.5
2 41.2
2.2 44.2
2.4 48.2
2.6 50.3
2.8 53.4
1.7
2 48.2
2.2 51.2
2.4 55.6
2.6 60.2
2.8 65.2
1.9
2 55.6
2.2 62.3
2.4 66.2
2.6 72.5
2.8 78.6

Well if it's only a problem to get the file contents in - that's not really a problem. More problematic on the other hand is the fact that the interpretation of your code is next to impossible.

One thing that's bound to cause trouble is the following:

1
2
3
4
5
6

for (i=0;i<33;i++)
{
    indata>>dc[i]>>gt[i]>>snr[i];
}


Every single array you use in this loop is defined with a range smaller than the maximum value of your counter variable i. As soon as you hit i = 4 your dc[i] is undefined!

Please tell us something about how the data in the file supposed to end up in your arrays.

Last edited on
The data is read in 5 different groups, for each dc value. Each of those values are then used in a void function that calculates the slope, intercept, and rsquared based off of the following equation
snr = a[i]*gt + b[i] for a given dc

So would I put the void function that has all those calculations within the for loop that reads the initial values?

I'm not sure on how to include the void function to read the 5 groupings of values
One problem with your file is that it's not that easy to parse since there are no obvious indications which line stands for what kind of data. The other problem is the nature of the input data - it's gonna be a string or an array of type char which is not suitable as input for your void function. Therefore you'll need string to number conversion.

There is one distinct quality that separates the dc identifier from the rest - the white spaces in between two values.

The following program reads the file contents into a a vector of structures of type dc_data. For every line in the file is determines if there is a new structure, everytime there is NO white space in the line, or data to put into the current dc_data.

Since our buffer size is currently at 220, every non-number and non-whitespace character in the current line is removed by trim(). Then the line is processed accordingly: If a dc value is found, a new dc_data is pushed back into the vector of dc_datas, otherwise the gt and snr values are read, converted and added to the current dc_data structure.

I've tested the program with your data from above.

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

std::string trim(const std::string& str)
{
    // line is empty except for wspaces 
    if(str.find_first_not_of(' ') == std::string::npos) 
        return std::string(); // return empty string
    
    // remove all trailing chars that are no number or wspace
    else
        return str.substr(0, str.find_first_not_of(".0123456789 "));
}

// my standard template for str -> number of type T
template<typename T> T toNumber(const std::string &str) 
{
    std::istringstream stream(str);
    T value;
    stream >> value;
    return value;
}

struct dc_data  // give the child a name you like
{
    std::vector<double> gt;
    std::vector<double> snr;
};

std::vector<dc_data> dc_vector; // one data structure for each dc
char data[220];

int main(int argc, char **argv) {
    
    std::ifstream indata("data.txt");
    
    // now we'll parse the data 
    while(indata.good())
    {
        indata.getline(data, 220); 
        
        // create string object with content of current line
        std::string data_str = trim(std::string(data));

        // if no relevant data in current line
        if(data_str.empty())
            continue;
        
        // check if white space is present
        size_t white_space_pos = data_str.find(' '); 
        
        // got dc - no white space in line
        if(white_space_pos == std::string::npos) 
            dc_vector.push_back(dc_data()); // add new data to vector
        
        // got line with white space - read gt and snr
        else 
        {
            double gt_val = toNumber<double>(data_str.substr(0, white_space_pos));
            dc_vector.back().gt.push_back(gt_val);
        
            double snr_val = toNumber<double>(data_str.substr(white_space_pos));
            dc_vector.back().snr.push_back(snr_val);
        }
    }
    
    for(int i = 0; i < dc_vector.size(); ++i)
        for(int j = 0; j < dc_vector[i].gt.size(); ++j)
            std::cout << "( " << dc_vector[i].gt[j] 
                      << " | " << dc_vector[i].snr[j] 
                      << ")" << std::endl;
    
    
    std::cout << "dcs read: " << dc_vector.size() << std::endl;
    std::cout << "Done!" << std::endl;
    return 0;
}


Hope that helps!

Thomas
Last edited on
Topic archived. No new replies allowed.