Inputing into a double vector

Hello everyone!

I have posted something on this yesterday, I was hoping that finding the flow in part of the code would resolve the whole issue but I was wrong...

This is a program that reads a file and inputs integer values into a double vector.
The 2nd line of the file to be read has the number of clauses and the number of variables I will make use... The Idea is to insert specific values into a vector of dimensions: clause number by literal number...

I'm using command line to call the function
example C:\folder\prog.exe file

Here is the 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
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>


using namespace std;




int main(int argc, char ** argv)
{
    int numClause, numLit; //number of clauses, number of literals
    int linecount = 0;
    int spacecount_;
    int varcount;
    ofstream tempfile;
    ifstream tempfile_;
    string str;
    int array[50][50];
    vector< vector< int > > matrix;
    ifstream inData;
    inData.open(argv[1]);


    while ( !inData.eof() )
    {
        getline (inData, str);
        if (linecount == 1)
        {
            sscanf(str.data(), "p cnf %d %d", &numClause, &numLit);
            vector< int > clause;
            for (int j = 0; j < numLit; j++) clause.push_back(0);
            for (int i = 0; i < numClause; i++) matrix.push_back(clause);
        }
        if (linecount > 1 && linecount < numClause)
        {

            spacecount_ = 0;
            for(int i = 0; i != str.size(); i++) spacecount_ += ( str[i] == ' ');
            varcount = spacecount_ + 1;


            int *temp;
            temp = new (nothrow) int [varcount
            tempfile.open("fout.txt");
            tempfile << str;
            tempfile.close();
            int number;
            tempfile_.open("fout.txt");
            for (int i = 0; i < varcount; i++) tempfile_ >> temp[i];
            tempfile_.close();
 


            for (int i = 0; i < varcount; i++)
            {
                int column = abs(temp[i]);
                int row    = linecount - 1;
                int value  = (temp[i] > 0 ? 1 : 2);
                matrix[column][row] = value;
            }
            delete [] temp;

        }
        cout << str << endl;
        linecount++;
    }
    inData.close();


    return 0;
}


Algorithms is:

(1) open file to be read
(2) 2nd line contains info about dimensions... Initialize the double vector
(3) line 3 and on has the variables I want to process
(4) I am counting spaces to know how many variables there is in a line
(5) creating a 1d dynamic array to store variables
(6) process the variables
(7) inserting then into the vector in a specific way
(8) repeating from (1)

But for some reason the program seems to crash. I am perfectly sure that my algorithm works but I am obliged to use a double vector...

Any help would be much appreciated!
Last edited on
For starters this is wrong:
1
2
3
    while ( !inData.eof() )
    {
        getline (inData, str);

The reason is that EOF will not be flagged until *after* getline() fails. so your entire loop will execute on one line of bad data from a failed read when EOF is reached.

It best to loop like this:
1
2
3
    while ( getline (inData, str) )
    {
        // now str *must* contain good data. 
Last edited on
I wouldn't trust this myself:
 
for(int i = 0; i != str.size(); i++) spacecount_ += ( str[i] == ' ');

I would probably do something like this:
1
2
3
4
5
#include <algorithm>

// ... stuff ...

spacecount_ = std::count(str.begin(), str.end(), ' ')

Last edited on
This is very data sensitive. Is it possible to see some of the data that this is failing on?
Also, although it shouldn't effect anything here, you are using the C headers:
1
2
#include <stdio.h>
#include <stdlib.h> 

In C++ you should use the C++ versions:
1
2
#include <cstdio>
#include <cstdlib> 
Dear Galik,

Thank you very much for your post, to begin with...

I did modified the code, as you suggested... Maybe I missed out on a certain detail, program is running, but it is crashing midway i.e. sometimes it crashes on 2nd line, 3rd line or 5th line. I know so because I am printing to screen as you can tell. I tried hiding the line:
matrix[column][row] = value;

So program goes through the end (even before changing the .eof()...
So what to do?
Last edited on

I would probably do something like this:

1
2
3
4
5
6
 #include <algorithm>

// ... stuff ...

spacecount_ = std::count(str.begin(), str.end(), ' ')
 



I thought I would be having a problem with that i.e. dynamic arrays isn't having enough spaces to store my readed variables, yet, programs still crashes
This is very data sensitive. Is it possible to see some of the data that this is failing on?


ok the file I'm reading is of text format... it reads:


bla bla
p cnf 12 15
2 -10 8 4
3 8 9 7
5 3
6 4 8 7 10 -15
-8 14 6 -4
1 -2 9 11 -12
-13 5 9 11
-1 3 7 -5
-6 -2 -13
13 15
-9 7 5 4
6 -7
It seems that you set your numLit value to 15 from the file. However the file contains indices of 15, which is one greater than the amount you allocate. If 15 is the maximum value, then the array (or vector) needs 16 elements, 0 - 15.
1
2
3
4
                int column = abs(temp[i]); // column can = 15 which is too large for matrix[][]
                int row    = linecount - 1;
                int value  = (temp[i] > 0 ? 1 : 2);
                matrix[column][row] = value;

The question is, is the 15 the max value? Or do the values range from 1-15 rather than 0-15? If the values range from 1-15 then I think you need to subtract 1 from column before using it as an index. Otherwise I think you need to add one to ...

Hang on. I begin to think you have your rows and columns the wrong way round:
1
2
3

            for (int j = 0; j < numLit; j++) clause.push_back(0); // these are the rows (second index) matrix[?][numlit];
            for (int i = 0; i < numClause; i++) matrix.push_back(clause); // these are the columns (first index) matrix[numClause][?] 


Is that what you intend?
Dear Galik,

Well you can put it in the way the numClause are the columns and numLit are the rows, but I want the opposite, I think this doesnt matter to me as I can print them in any way I want, rows then columns... Right?

I think what I'm doing is true: Loop1: 0 -> numClause exclusive ie 12 clauses
Loop2: 0 -> numLit exclusive ie 15 literals.

Next, I want the numClause (row count) to be exactly 12, (well this is the number I must get) and numLit the number of columns to be exactly 15.

N.B. I havent mentioned this, I'm reading text in "normal conjuctive form"... A boolean statement...
Last edited on
The point being that you make numClause the first index of matrix but you access the matrix using the numClause component as the second index. You need to make that consistant.
1
2
3
4
5
6
7
8
9
10
11
12
13
        if (linecount == 1)
        {
            sscanf(str.data(), "p cnf %d %d", &numClause, &numLit);
            // numLit is out of range, either add 1 here or subtract 1 from column
            // if indexing from 1-15 rather than 0-15
            ++numLit; 

// etc...

               int column = abs(temp[i]);
               int row    = linecount - 1;
               int value  = (temp[i] > 0 ? 1 : 2);
               matrix[row][column] = value; // swap row and column 
Last edited on
Dear Galik,

I already tried that trick... Didn't work.
I'll check with my professor and try to get back on you, I believe you don't know what I am exactly trying to do and therefore have the right of predicting what suits the code.

Thanks again.
Well, let me point out something about the code. You set the array temp[] from the numerical data from the file:
 
           for (int i = 0; i < varcount; i++) tempfile_ >> temp[i];

You then use those numbers to index your matrix:
1
2
3
int column = abs(temp[i]);
// ...
matrix[column][row] = value;

Now if you look at your data, the maximum number is 15. So you are going to be accessing one of the indices of your vector using the number 15 (which is the 16th element):
 
matrix[15][row] = value;

But that number is too big. According to line 2 of your data the maximum size of your matrix dimensions is 15. If its size is 15 then it can only be indexed from 0-14. But you are indexing it with 15.

Either you need to add one to the dimension size making it 16 (0-15) or you need to subtract one from the number before you use it as an index (1-15 => 0-14).
Last edited on
Yeah, I used that, as I pointed out:

int column = abs(temp[i]);

The program analyzes the 1st 2 lines (and outputs them) and crashes on line 3...
Last edited on
Which means that you are trying to access column number 15 of a matrix that only has column numbers 0-14.
correction, excuse me but this is driving me nuts, I mean I used:
int column = abs(temp[i]) - 1;
Okay. But I still think you have your column and your rows mixed up. I think that what you have defined as columns you are addressing as rows and vice versa. When I make that change and the change you did by subtracting 1 from the column number it reads the data right to the end of the file.
This code reads to the end of the file for me:
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
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <algorithm>

using namespace std;




int main(int argc, char ** argv)
{
    int numClause, numLit; //number of clauses, number of literals
    int linecount = 0;
    int spacecount_;
    int varcount;
    ofstream tempfile;
    ifstream tempfile_;
    string str;
    int array[50][50];
    vector< vector< int > > matrix;
    ifstream inData;
    inData.open(argv[1]);


    while (getline (inData, str))
    {
        if (linecount == 1)
        {
            sscanf(str.data(), "p cnf %d %d", &numClause, &numLit);


            vector< int > clause;
            for (int j = 0; j < numLit; j++) clause.push_back(0);
            for (int i = 0; i < numClause; i++) matrix.push_back(clause);
        }
        if (linecount > 1 && linecount < numClause)
        {

            spacecount_ = 0;
            spacecount_ = std::count(str.begin(), str.end(), ' ');
            varcount = spacecount_ + 1;

            int *temp;
            temp = new (nothrow) int [varcount];
            tempfile.open("fout.txt");
            tempfile << str;
            tempfile.close();
            int number;
            tempfile_.open("fout.txt");
            for (int i = 0; i < varcount; i++) tempfile_ >> temp[i];
            tempfile_.close();



            for (int i = 0; i < varcount; i++)
            {
               int column = abs(temp[i]) - 1;
                int row    = linecount - 1;
                int value  = (temp[i] > 0 ? 1 : 2);
//                matrix[column][row] = value;
                matrix[row][column] = value;
            }
            delete [] temp;

        }
        cout << str << endl;
        linecount++;
    }
    inData.close();


    return 0;
}
Another thing. You can use strings as streams using <sstream>:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <sstream>

// .. stuff ...

//            tempfile.open("fout.txt");
//            tempfile << str;
//            tempfile.close();
//            int number;
//            tempfile_.open("fout.txt");
//            for (int i = 0; i < varcount; i++) tempfile_ >> temp[i];
//            tempfile_.close();
            std::istringstream iss(str); // make str into an input stream
            for(int i = 0; iss >> temp[i]; ++i);

That saves writing out a temporary file.
Dear Galik,

The program finally worked smoothly, and correctly...

I want to note 2 things:

(1) The "fixed" code you posted, the one you implied that worked, caused the program to crash while reading the 1st clause (line 3 of file)

(2) replacing the input/output thing by the sstream solved the entire issue.

(3) I am using Code::Blocks with MinGW, it says the compiler is GCC, what compiler are you using, do you think it has anything to do with it?
Topic archived. No new replies allowed.