Program compiles, but crashes.

Hi. I am trying to write a program to make data entry at work quicker. I have only taken an intro course in C++, and that was a year ago, so I am a novice and having trouble recalling everything I learned.

Anyways, The program asks the user to input concentrations of compounds at certain temperatures and then averages the concentrations and organizes them into a matrix. Then the matrix is sent to an output file.

I am using dev-C++ 4.9.9.2 on Windows Vista. The program compiles correctly, but I am running into a few problems when trying to run it.

First, it runs on one computer, but not another. Both computers use Windows Vista as an operating system.

Second, on the computer that does run it, the program crashes once it gets to the point where it asks the user to input concentrations for C3H6 at whatever temperature is 50 degrees above the minimum temperature (by the way, you can only input temperatures that are multiples of 50 i.e. 50, 100, 150, 200, etc.). This problem arose once I added the TempCheck function to the program. Before that, I was able to run the program to completion (on the computer that ran it). However, the resulting matrix in the output file did not turn out right. The first element in every row after the first was the same as the last element in the preceding row.

Lastly, I realize that if the user types 'd' without typing any concentrations, then the program will be dividing by zero when trying to find an average. I have been trying to find a way to make the matrix a character array so that when the user types 'd' without typing any concentrations, the element is just a hyphon. However, I can't see how this is possible to do, since then I'd have to make the average concentrations strings instead of doubles, and as far as I know strings cannot be considered as a single element in an array. Is there a way around this?

Sorry for the long explanation. I appreciate any help that anyone has to offer. Here is the source code, along with comments:

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*This program finds averages for concentrations of compounds at certain
temperatures, and then organizes the data in a matrix that is sent to an output
file.*/

#include<iostream>    //Allows for the use of cout/cin commands.
#include<fstream>//Enables one to load data from files and output data to files.
#include<cstdlib>    /*Needed for checking that the file was loaded correctly 
and also to convert strings to integers or doubles.*/
#include<cstring>    //Needed to find string lengths.
#include<cctype>    /*Allows for the use of isdigit function to check that an
array element is a digit*/
using namespace std;    //Allows for basic C++ functions.  
int i,check1=0;    //Declares global variables as integers.                            
int main()    //Begins main function.
{
    int MaxTemp,MinTemp,NROWS,NCOLS=9,j,x;    //Declares variables as integers.
    char OutputFileName[100];    //Declares variable as a string.
    double A[NROWS][8];    //Declares an array with elements as doubles.
    int TempCheck(char extreme[]); /*Declares an integer function with a string
    as the only input.*/
    double data(char compound[]); /*Declares a double function with a string as
    the only input.*/
    ofstream outfile;    //Declares variable.
    cout<<"Enter output file name (use a .csv extension): ";
    cin>>OutputFileName;
    outfile.open(OutputFileName);    //Creates output file.
    MaxTemp=TempCheck("maximum");//Calls function and assigns output to MaxTemp.
    NROWS=MaxTemp/50-1; 
    MinTemp=TempCheck("minimum");//Calls function and assigns output to MinTemp.
    for(i=MaxTemp;i>=MinTemp;i=i-50) /*For every 50 degree increment of the
    temperature starting at MaxTemp and ending at MinTemp...*/
    {
        x=(i-MinTemp)/50; /*Needed so that for each turn of the loop, the row
        number decreases by 1, and eventually reaches 0.*/
        A[x][0]=data("CH4"); /*Calls function and assigns output to the 
        appropriate element in an array.*/
        A[x][1]=data("CO");
        A[x][2]=data("NO");
        A[x][3]=data("NO2");
        A[x][4]=data("C2H6");
        A[x][5]=data("C3H6");
        A[x][6]=data("C3H8");
        A[x][7]=data("HCHO");
        A[x][8]=data("CH3OH");
    }
    for(i=0;i<NROWS;i++)    //For each successive row...
    {
        for(j=0;j<NCOLS;j++)    //For each successive column in a given row...
            outfile<<A[i][j]<<",";    /*Send the element in that position to
            the output file.*/
        outfile<<endl;
    }
    cout<<endl;
    outfile.close();    //Close output file.
    system("pause");    //Pause console window.
    return 0;
}    //Ends main function.

int TempCheck(char extreme[]) /*This function checks to see that the
temperature input consists only of digits, and if so, returns the temperature as
an integer.*/
{
    char Temp[100]; //Declares variable as a string.
    int y; //Declares variable as an integer.
    cout<<"\nEnter "<<extreme<<" temperature: ";
    while(1==1)    //Always true, therefore infinite loop.
    {  
        cin>>Temp;    //Take in whatever user may type.
        for(i=0;i<strlen(Temp);i++)    //For each character in the string...
        {
            if(isdigit(Temp[i]))    //If the character is a digit...
                check1=check1+1;
        }
        if(check1==strlen(Temp))    //If every character is a digit...
        {
            y=atoi(Temp);    //Convert the string to an integer and assign to y.
            check1=0;    //Reset value to zero.
            return y;    //Return temperature as an integer.
            break;    //End the loop.
        }
        else //Otherwise...
            cout<<"\n                    Invalid Entry.\n\nEnter "<<extreme<<" temperature: ";
            check1=0;    //Reset value to zero.
    }
}
                
double data(char compound[]) /*This function asks the user to input either
concentrations of compounds or type 'd' to finish, averages the
concentrations once the user is finished, and returns the average.*/
{
    char concentration[100];    //Declares variable as a string.
    int k,ndatapoints=0,check2=0;    //Declares variables as integers.
    double sum=0,z,average;    //Declares variables as doubles.
    cout<<"\nEnter concentrations for "<<compound<<" at "<<i<<" \370C one by one. Press 'd' when done:\n\n                        ";
    while(1==1)    //Always true, therefore infinite loop.
    {
        cin>>concentration;    //Take in whatever the user may type.
        cout<<"                        ";
        if(strlen(concentration)==1&concentration[0]=='d')    /*If the user
        types 'd' and only 'd'...*/
            break;    //End the loop.  
        for(k=0;k<strlen(concentration);k++)    /*For each character in the
        string...*/
        {    
            if(isdigit(concentration[k]))    //If the character is a digit...
                check1=check1+1;
            if(concentration[k]=='.')  //If the character is a decimal point...
                check2=check2+1;
        }
        if((check1+check2)==strlen(concentration)&check2<=1) /*If the string
        consists of digits and either one or no decimal points...*/
        {
            z=atof(concentration);    /*Convert the string to a double and
            assign to z.*/
            sum=sum+z;    //Add the concentration to the total sum.
            ndatapoints=ndatapoints+1;    /*Increase the number of
            concentrations by one.*/
            check1=0;    //Reset value to zero.
            check2=0;    //Reset value to zero.
        }
        else    //Otherwise...
        {    
            cout<<"\n                    Invalid Entry.\n\n                        ";
            check1=0;    //Resets value to zero.
            check2=0;    //Resets value to zero.
        }
    }
    average=sum/ndatapoints;    //Find the average concentration.
    return average;    //Return the average as a double.
}
dev-C++ 4.9.9.2

Get something else. That's a bad choice.

double A[NROWS][8]; //Declares an array with elements as doubles.
Variable length arrays are forbidden in C++. I expect you're using gcc which carries an extension to let you do this, but it's still something to be avoided.

Furthermore, what value does NROWS have? It could be anything. Set it to a value before you use it.

Thanks for the quick reply.

What else would you suggests other than dev-C++? I chose it because it is free and I learned the programming language through dev-C++.

Also, you say variable length arrays are forbidden in C++, but I need my program to be such that the amount of rows can change depending on the user's needs. Is there another way to achieve the same result?

To answer your question, I later defined NROWS to be equal to MaxTemp/50-1:

NROWS=MaxTemp/50-1;
http://www.cplusplus.com/forum/articles/36896/

Also, you say variable length arrays are forbidden in C++, but I need my program to be such that the amount of rows can change depending on the user's needs. Is there another way to achieve the same result?

Either create them dynamically when you know how big they need to be, using new, or use a C++ container such as vector that takes care of its own size for you.

To answer your question, I later defined NROWS to be equal to MaxTemp/50-1:
Bit late then, isn't it? You've already used some random value of NROWS to make your array :) What happens if that random value was very small? Oh noes! Not enough space and you'll probably get a segFault and the program will crash!
Last edited on
Okay, I haven't yet tried out your suggestion about dynamic memory and using new, nor have I tried using a C++ container such as vector (not sure what this one meant; could you provide more information or a link to a tutorial?). But I thought about what you said about the random value being too small, so I just let NROWS=15 in the beginning. The new code 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
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*This program finds averages for concentrations of compounds at certain
temperatures, and then organizes the data in a matrix that is sent to an output
file.*/

#include<iostream>    //Allows for the use of cout/cin commands.
#include<fstream>//Enables one to load data from files and output data to files.
#include<cstdlib>    /*Needed for checking that the file was loaded correctly 
and also to convert strings to integers or doubles.*/
#include<cstring>    //Needed to find string lengths.
#include<cctype>    /*Allows for the use of isdigit function to check that an
array element is a digit*/
using namespace std;    //Allows for basic C++ functions.  
int i,check1=0;    //Declares global variables as integers.                            
int main()    //Begins main function.
{
    int MaxTemp,MinTemp,NROWS=15,NCOLS=9,j,x;    //Declares variables as integers.
    char OutputFileName[100];    //Declares variable as a string.
    double A[NROWS][8];    //Declares an array with elements as doubles.
    int TempCheck(char extreme[]); /*Declares an integer function with a string
    as the only input.*/
    double data(char compound[]); /*Declares a double function with a string as
    the only input.*/
    ofstream outfile;    //Declares variable.
    cout<<"Enter output file name (use a .csv extension): ";
    cin>>OutputFileName;
    outfile.open(OutputFileName);    //Creates output file.
    MaxTemp=TempCheck("maximum");//Calls function and assigns output to MaxTemp.
    NROWS=MaxTemp/50-1; 
    MinTemp=TempCheck("minimum");//Calls function and assigns output to MinTemp.
    for(i=MaxTemp;i>=MinTemp;i=i-50) /*For every 50 degree increment of the
    temperature starting at MaxTemp and ending at MinTemp...*/
    {
        x=(i-MinTemp)/50; /*Needed so that for each turn of the loop, the row
        number decreases by 1, and eventually reaches 0.*/
        A[x][0]=data("CH4"); /*Calls function and assigns output to the 
        appropriate element in an array.*/
        A[x][1]=data("CO");
        A[x][2]=data("NO");
        A[x][3]=data("NO2");
        A[x][4]=data("C2H6");
        A[x][5]=data("C3H6");
        A[x][6]=data("C3H8");
        A[x][7]=data("HCHO");
        A[x][8]=data("CH3OH");
    }
    for(i=0;i<NROWS;i++)    //For each successive row...
    {
        for(j=0;j<NCOLS;j++)    //For each successive column in a given row...
            outfile<<A[i][j]<<",";    /*Send the element in that position to
            the output file.*/
        outfile<<endl;
    }
    cout<<endl;
    outfile.close();    //Close output file.
    system("pause");    //Pause console window.
    return 0;
}    //Ends main function.

int TempCheck(char extreme[]) /*This function checks to see that the
temperature input consists only of digits, and if so, returns the temperature as
an integer.*/
{
    char Temp[100]; //Declares variable as a string.
    int y; //Declares variable as an integer.
    cout<<"\nEnter "<<extreme<<" temperature: ";
    while(1==1)    //Always true, therefore infinite loop.
    {  
        cin>>Temp;    //Take in whatever user may type.
        for(i=0;i<strlen(Temp);i++)    //For each character in the string...
        {
            if(isdigit(Temp[i]))    //If the character is a digit...
                check1=check1+1;
        }
        if(check1==strlen(Temp))    //If every character is a digit...
        {
            y=atoi(Temp);    //Convert the string to an integer and assign to y.
            check1=0;    //Reset value to zero.
            return y;    //Return temperature as an integer.
            break;    //End the loop.
        }
        else //Otherwise...
            cout<<"\n                    Invalid Entry.\n\nEnter "<<extreme<<" temperature: ";
            check1=0;    //Reset value to zero.
    }
}
                
double data(char compound[]) /*This function asks the user to input either
concentrations of compounds or type 'd' to finish, averages the
concentrations once the user is finished, and returns the average.*/
{
    char concentration[100];    //Declares variable as a string.
    int k,ndatapoints=0,check2=0;    //Declares variables as integers.
    double sum=0,z,average;    //Declares variables as doubles.
    cout<<"\nEnter concentrations for "<<compound<<" at "<<i<<" \370C one by one. Press 'd' when done:\n\n                        ";
    while(1==1)    //Always true, therefore infinite loop.
    {
        cin>>concentration;    //Take in whatever the user may type.
        cout<<"                        ";
        if(strlen(concentration)==1&concentration[0]=='d')    /*If the user
        types 'd' and only 'd'...*/
            break;    //End the loop.  
        for(k=0;k<strlen(concentration);k++)    /*For each character in the
        string...*/
        {    
            if(isdigit(concentration[k]))    //If the character is a digit...
                check1=check1+1;
            if(concentration[k]=='.')  //If the character is a decimal point...
                check2=check2+1;
        }
        if((check1+check2)==strlen(concentration)&check2<=1) /*If the string
        consists of digits and either one or no decimal points...*/
        {
            z=atof(concentration);    /*Convert the string to a double and
            assign to z.*/
            sum=sum+z;    //Add the concentration to the total sum.
            ndatapoints=ndatapoints+1;    /*Increase the number of
            concentrations by one.*/
            check1=0;    //Reset value to zero.
            check2=0;    //Reset value to zero.
        }
        else    //Otherwise...
        {    
            cout<<"\n                    Invalid Entry.\n\n                        ";
            check1=0;    //Resets value to zero.
            check2=0;    //Resets value to zero.
        }
    }
    average=sum/ndatapoints;    //Find the average concentration.
    return average;    //Return the average as a double.
}


The program no longer crashes and runs to completion (at least on one computer; I haven't tried the other yet). Does this mean I solved the problem by assigning a large enough value to NROWS in the beginning? Or do you suggests I still try the dynamic memory method or C++ container method you mentioned?

Also, I am still having the problem with the output matrix. The first element in each row after the first is the same as the last element of the preceding row. For instance, I get this as output:

1 2 3 4 5 6 7 8 9
9 11 12 13 14 15 16 17 18
18 20 21 22 23 24 25 26 27

when I really want this:

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

Any suggestions? And I really appreciate the help so far. I'm going to read up on dynamic memory right now.
If it runs happily now, and you've no need to change the size of the array, there's no need to do any more. So long as the array is big enough, it's fine.

Also, I am still having the problem with the output matrix.

You're definitely filling it badly. When you create this:
double A[15][8];
The following locations exist:
A[0][0]
A[0][1]
A[0][2]
A[0][3]
A[0][4]
A[0][5]
A[0][6]
A[0][7]
A[1][0]
A[0][1]
A[0][2]
and so on.... there is no A[0][8], or A[1][8], and the last one is A[14][7]

If you try to write to A[0][8], you will actually be writing to A[1][0]. This is because of what A[x][y] actually is interpreted as, and involves pointer arithmetic. If that doesn't mean anythign to you, don't worry. Just remember that in an array of size X, the first element is numbered 0 and the last element is numbered X-1.

So when you do this:
A[x][8]=data("CH3OH");

it's identical to
A[x+1][0]=data("CH3OH");

which is bad news for you, because you're going to end up writing over things you didn't mean to.

When you make an array of size i, the elements are numbered zero to i-1 ; there is no element i.

Looks to me like you want your array A to be:
double A[NROWS][9];




let NROWS=15

That sounds suspiciously like BASIC... you're not thinking in BASIC, are you? That's deadly when you try to code in C++. :)


Last edited on
Ah, of course. Such a simple mistake. it should have been written as:

double A[15][9];

I think I half knew this since I let NCOLS=9 in the beginning. Then for some reason I wrote 8 in the brackets!

Anyways, the output file is looking good now. Awesome! Thank you so much!

As for the last problem I had with the program dividing by zero when the user types 'd' without typing any concentrations, I no longer think that is an issue. I had originally wanted the program to fill in a hyphon in that element of the matrix to let the user know it is a blank space, but it seems to print -1.#IND automatically, which I think is just as effective as a hyphon, so I won't bother.

I am not sure what BASIC is. Another programming language? If so, I have never used it. The whole NROWS and NCOLS thing is just a habit I picked up from my professor last year.

Again, a thousand thanks. I am eternally grateful :). This program should make data entry at work much more bearable!
Topic archived. No new replies allowed.