Storing data from 2 columns in a .csv

Pages: 12
That's good in two respects, first that it did what you wanted,but perhaps more important, that you understood it - that means you should be able to modify or re-use these ideas later.

One additional thought, for real-world use, rather than hard-coding the filenames in the program, you may want to read them from the command line. Then perhaps execute the program from a bat file or script.
That will be another can of worms to open that I'm not sure if I am ready to tackle as of now. I am modifying it now just adding checks to make sure the file was in the directory and opened, also that it completed writing the file.

I will have to dig into the bat file and script to see what all it in tells.

I'm sure you will see me posting here again in the near future.
No worries. I wasn't trying to open a can of worms, rather I was thinking of ways to make it simpler and quicker for you to get from a to b. Leave that for some other time, when or if you feel a need for it.
Chervil wrote:
My version. It may be flawed, just consider it a first attempt.

I did notice a problem which causes loss of data.

The input data is converted from a string to a double.That's ok. But when writing to the output file, the default precision may discard some digits, for example 1502.491 may appear as 1502.49 or 1502.397 may appear as 1502.4

In order to remedy this, before writing any data to the output file, set the required precision, something like this:
 
    fout.precision(10); // do this after opening output file, to avoid loss of accuracy 
Note also that the meaning of precision changes, if changing to fixed format. See docs.


That can of worms. A function takes ideally a stream. It does not open it. Now the caller can choose to pass cin or fstream, i.e program can be smart enough to read both from pipe and file. The reader function should not care.
I noticed the same thing yesterday Chervil when I started QC'n the data and validating between the values. No wonder I couldn't get the precision to work due to I had never worded with
fout.precision(). I will work on implementing that.

Could you point me in the direction of how to convert to say a .bat or script? I see where it could be a problem if I were to run this on my own computer and not have a D:\JOBS\ directory. Much rather not hard coding in the path, which y'all had stated earlier. Was just trying to take the code a step at a time to not overwhelm myself, and to actually be able to learn and follow along. Thanks.
So I inserted fout.precision(10); as so:
1
2
3
4
5
6
string export_filename;
export_filename += ("export-" + filename);
string pathout = ("D:\\JOBS\\");
string export_filename = path + export_filename;
ofstream fout(export_fullname.c_str());
fout.precision(10);


And it worked, going to work on doing another validation between data sets again. Thanks once again.

One other thing, could you point me where I can read on creating a window that allows the user to navigate to the input file and then select the output location.
Last edited on
Well, I'm still trying to keep things fairly simple.
I was thinking along the lines of passing the file names as parameters to the program. I dare say this is not exactly what you were thinking of, but I'll at least show my idea. This is in terms of a windows OS
1
2
offshore2.exe "D:\JOBS\SV Cast_Test_Data.csv" "D:\JOBS\output.txt"
@pause

You could store a command like that in a text file, called run.bat. Then rather than editing the program and recompiling it, you only need to edit this single line.

The program would read these parameters and process them if they make sense. This is just a skeleton, you would put all the important stuff inside function process().

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

    using namespace std;

int process(istream & fin, ostream & fout);

int main(int argc, char * argv[])
{
    if (argc != 3)
    {
        cout << "  Usage:\n\n"
             << "  progname inputfile outputfile\n\n"
             << "  where inputfile and outputfile\n"
             << "  are the full names of files including path" << endl;
        return 1;
    }
    cout << "Input:  " << argv[1] << endl;
    cout << "Output: " << argv[2] << endl;
    ifstream fin(argv[1]);
    if (!fin)
    {
        cout << "Unable to open input" << endl;
        return 2;
    }

    ofstream fout(argv[1]);
    if (!fout)
    {
        cout << "Unable to open output" << endl;
        return 3;
    }

    return process(fin, fout);

}

//---------------------------------------------------------------------------

int process(istream & fin, ostream & fout)
{
    // do domething with the input and output streams
    return 0;
}

While I'm on this topic, here's a complete program based upon that concept:
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <cstdlib>

    using namespace std;

int process(istream & fin, ostream & fout);

struct values {
    double num2;
    double num3;
    values() {};
    values(double a, double b) : num2(a), num3(b) {};
};

double getNumber(std::istream & is);
const char comma = ',', tab = '\t';


int main(int argc, char * argv[])
{
    if (argc != 3)
    {
        cout << "  Usage:\n\n"
             << "  progname inputfile outputfile\n\n"
             << "  where inputfile and outputfile\n"
             << "  are the full names of files including path" << endl;
        return 1;
    }
    cout << "Input:  " << argv[1] << endl;
    cout << "Output: " << argv[2] << endl;
    ifstream fin(argv[1]);
    if (!fin)
    {
        cout << "Unable to open input" << endl;
        return 2;
    }

    ofstream fout(argv[2]);
    if (!fout)
    {
        cout << "Unable to open output" << endl;
        return 3;
    }

    return process(fin, fout);

}
//---------------------------------------------------------------------------

int process(istream & fin, ostream & fout)
{
    // do domething with the input and output streams

    std::vector<values> dataVec;

    int incount  = 0;
    int outcount = 0;

    std::string line;
    for (int i=0; i<32;i++)
    {
        if (getline(fin, line))
            incount++;
    }

    bool ignore_zero = true;

    while (getline(fin, line))
    {
        incount++;

        std::istringstream ss(line);
        getNumber(ss);
        double num2 = getNumber(ss);
        double num3 = getNumber(ss);

        if (ignore_zero && num2 != 0.0)
            ignore_zero = false;

        if (!ignore_zero)
            dataVec.push_back(values(num2, num3));
    }

    // find col3 max
    int index = 0;
    for (unsigned int i=0; i<dataVec.size(); i++)
        if (dataVec[i].num3 >= dataVec[index].num3)
            index = i;

    // create output file
    fout.precision(10);
    for (int i=0; i<= index; i++)
    {
        fout << dataVec[i].num3 << tab << dataVec[i].num2 << std::endl;
        outcount++;
    }

    cout << "\nInput lines processed:  " << incount
         << "\nOutput lines processed: " << outcount
         << "\n" << endl;

    return 0;
}

double getNumber(std::istream & is)
{
    std::string str;
    getline(is, str, comma);
    return atof(str.c_str());
}
Of course you are right keskiverto. Though my previous code requires very little modification, in fact a big simplification in order to use that technique.
Topic archived. No new replies allowed.
Pages: 12