I am getting an error in Windows Vista that says "Project3.exe has stopped working", and has a bar like a loading a bar, and under it, it says it is looking for a solution. The program is an class assignment that takes a data fiile with information about energy usage and can do different things with that information. This is my code ( The code is unfinished, i was just testing this first function)

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <stdint.h>
using namespace std;

void option1 ( int energy[29][14], string types[13], int64_t total[29] )
{
     short int year;
     short int i;
     float percent[13];
     restart:
     cout << "Enter the year: ";
     cin >> year;
     if ( year < 1980 || year > 2008 )
     {
          cout << "Year must be at least 1980 and at most 2008!\n";
          goto restart;
     }
     year = year % 29;
     cout << setprecision ( 3 ) << setiosflags ( ios::fixed ) << setiosflags ( ios::showpoint );
     for ( i = 0; i < 28; i++ )
     {
         percent[i] = ((float) total[year] )/ energy[year][i];
     }
     cout << "Energy Source" << setw ( 50 ) << "Energy in Megawatt Hours" << setw ( 80 ) << "Percent of Total Energy\n";
     for ( i = 0; i < 13; i++ )
     {
         cout << types[i] << energy[year][i+1] << percent[i] << "\n";
     }
}
int main()
{
    int energy[29][14];
    int64_t fossilfuel[29];
    int64_t renewable[29];
    int64_t total[29];
    string types[13] = {"Coal","Petroleum","Natural Gas","Other Gases","Nuclear","Hydro-Electric Pumped Storage","Hydro-Electric","Biomass - Wood","Biomass - Waste","Geothermal","Solar","Wind","Other"};
    int r, c;
    short int option;
    ifstream energyfile("energy.dat");
    for ( r = 0; r < 29; r++ )
    {
        for ( c = 0; c < 13; c++ )
        {
            energyfile >> energy[r][c];
        }
    }
    for ( int i = 0; i <= 28; i++ )
    {
        fossilfuel[i] = 0;
        renewable[i] = 0;
        total[i] = 0;
        for ( c = 1; c <= 4; c++ )
        {
            fossilfuel[i] += energy[i][c];
            total[i] += energy[i][c];
        }
        total[i] += energy[i][5];
        total[i] += energy[i][6];
        for ( c = 7; c <= 12; c++ )
        {
            renewable[i] += energy[i][c];
            total[i] += energy[i][c];
        }
        total[i] += energy[i][13];
    }
    cout << "Please enter an option:\nOption 1. Input a year and display a result with energy uses for each energy type.\nOption 2. The peak year of production of a certain energy type.\nOption 3. Create a data file to be opened by Excel." << endl;
    cin >> option;
    switch ( option )
    {
           case 1:
                option1 ( energy, types, total );
                break;
           case 2:
                //option2 ( energy );
                break;
           case 3:
                //option3 ( energy);
                break;
    }
    cin.ignore();
    cin.get();
    return 0;
}

I figured it was a problem with the arrays, like i was accessing them wrong or something, but i checked them and it looked fine. any help would be appreciated.

>> for ( c = 0; c < 13; c++ )

should that 13 be 14 ?

and go ahead and run the debug mode. It will give you more experience.

I ran it in debug mode, and it said there was a segfault. When it told me where the error was, it was in the ostream header file. Now what do i do?

I ran it in debug mode, and it said there was a segfault. When it told me where the error was, it was in the ostream header file. Now what do i do?

At least one out-of-bounds (13 vs. 28) write ..

float percent[13];
...
for ( i = 0; i < 28; i++ )
{
  percent[i] = ((float) total[year] )/ energy[year][i];
}

How about using const throughout the program for specifying various sizes/dimensions?

const int rows = 123;
const int cols = 123;

int blah[rows][cols];

for(int rr = 0; rr < rows; ++rr)
{
  for(int cc = 0; cc < cols; ++cc)
  {
     foobar(blah[rr][cc]);
  }
}
Comments
Very nice - especially using const for sizes :)

So your saying instead of doing

int stuff[10][10];

I do this?

const int r = 10;
const int c = 10;
int stuff[r][c];

OK, its something with the last for loop in the option1 function. I had it display int i every time it goes through, and after it hits 12, it just stops.

for ( i = 0; i < 13; i++ )
     {
         cout << i << endl;
         //cout << types[i] << energy[year][i+1] << percent[i] << "\n";
     }

that's what it looks like now. It stops when i = 12.

Does it stop once i=12 or after it displays the 12? Your statement isn't very clear...

If it shows the 12 then stops, that is normal behavior for the for loop as you have written it.

This is why mitrmkar suggested you use const values for your array sizes. That allows you to re-use the const value in your loop control statement(s). When you re-use the value, you only need to change it in 1 location, you don't have to find every instance of the value every time you need to make a change.

#include <iostream>
using std::cout;
using std::endl;

const int elementCount = 10;

int main() {
  //declare the array
  int anIntArray[elementCount];

  //populate the array
  for (int index = 0; index < elementCount; ++index) {
    anIntArray[index] = index *2;
  }

  //display the array
  for (int index = 0; index < elementCount; ++index) {
    cout << "The value in element " << index << " is " << anIntArray  [index] << endl;

  return 0;
}

Notice how I re-used "elementCount". If I decide I want to make the array have 20 elements, all I have to do is change elementCount and re-compile. I only have to change it once instead of three times, eliminating the possibility of missing one.

Edited 6 Years Ago by Fbody: n/a

The problem isn't that i forgot to change one, the compiler would've said something about it. The problem is what i first stated, it says that the program has had a problem. And the problem isn't with arrays, even when taking the array out of the for loop, it still has an error.

Edited 6 Years Ago by mebob: n/a

OK, so here is my testing code:

void option1 ( int energy[29][14], string types[13], int64_t total[29] )
{
     short int year;
     short int i;
     int elementCount = 28;
     float percent[13];
     restart:
     cout << "Enter the year: ";
     cin >> year;
     if ( year < 1980 || year > 2008 )
     {
          cout << "Year must be at least 1980 and at most 2008!\n";
          goto restart;
     }
     year = year % 29;
     cout << setprecision ( 3 );
     for ( i = 0; i < elementCount; i++ )
     {
         percent[i] = ((float) total[year] )/ energy[year][i];
     }
     cout << energy[year][1];
     cout << "Energy Source" << "Energy in Megawatt Hours" << "Percent of Total Energy\n";
     elementCount = 13;
     for ( i = 0; i < elementCount; i++ )
     {
         cout << i << endl;
         //cout << types[i] << energy[year][i+1] << percent[i] << "\n";
     }
     cout << "hi";
}

It displays hi. I find that sort of weird. It's not a problem with the loop.

//The bottom of the main function
    option1(energy,types,total);
    cout << "Hi";
    cin.ignore();
    cin.get();
    return 0;

It doesn't display that "Hi". That is really strange. So when the function ends, the program runs into a problem. Whats wrong with it?

Look at lines 17 thru 20:

for ( i = 0; i < elementCount; i++ )
     {
         percent[i] = ((float) total[year] )/ energy[year][i];
     }

This is the problem. At this point in the function, elementCount is 28 while percent[] only has 13 elements. You are still overrunning the array boundaries. Use your debugger, see what happens when "i" reaches 13 or higher.

This is why you need carefully named const variables. Otherwise, you have a maintenance nightmare.

Edited 6 Years Ago by Fbody: n/a

Wow, one simple little problem. Anyway, why did the error occur at the end of the function, not right where the problem was?

Couldn't tell ya for sure.

When you overrun an array's boundaries, you begin to access and/or modify memory that is not specifically allocated for that array. The memory that you overran into probably contained something needed at the end of the function that was getting damaged by the array overrun(s).

Boundary errors can be benign or catastrophic. It just depends on what is already stored in the memory that is corrupted by the overrun. It is considered good practice to avoid them completely, because you just don't know.

Edited 6 Years Ago by Fbody: n/a

OK, the program is not crashing anymore, but after adding the second option, after i enter the option while the program is running, it just stops, and if i try entering it again, it exits. Here is my new code:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <stdint.h>
using namespace std;

void option1 ( int energy[29][14], string types[13], int64_t total[29] )
{
     short int year;
     short int i;
     char choice;
     ofstream output;
     string filename;
     int elementCount = 28;
     float percent[13];
     cout << "Would you also like to output to a file (y or n)? ";
     cin >> choice;
     switch (choice)
     {
            case 'y':
                 cout << "What would you like the file name to be? ";
                 cin >> filename;
                 filename += ".txt";
                 output.open(filename.c_str());
                 restart1:
                 cout << "Enter the year: ";
                 cin >> year;
                 if ( year < 1980 || year > 2008 )
                 {          
                            cout << "Year must be at least 1980 and at most 2008!\n";
                            goto restart1;
                 }
                 output << "The selected year was " << year << endl;
                 year = year % 29;
                 cout << setprecision ( 3 );
                 output << setprecision ( 3 );
                 for ( i = 0; i < 12; i++ )
                 {
                     percent[i] = ((float) total[year] )/ energy[year][i];
                 }
                 cout << setiosflags(ios::fixed) << setiosflags(ios::showpoint) << setprecision(4);
                 cout << setw(0) << "Energy Source" << setw(35) << "Energy in Megawatt Hours" << setw(43) << "Percent of Total Energy\n";
                 output << setiosflags(ios::fixed) << setiosflags(ios::showpoint) << setprecision(4);
                 output << setw(0) << "Energy Source" << setw(35) << "Energy in Megawatt Hours" << setw(43) << "Percent of Total Energy\n";
                 elementCount = 13;
                 for ( i = 0; i < elementCount; i++ )
                 {
                     cout << setw(0) << types[i] << setw(35) << energy[year][i+1] << setw(43) << percent[i] << "%" << "\n";
                     output << setw(0) << types[i] << setw(35) << energy[year][i+1] << setw(43) << percent[i] << "%" << "\n";
                 }
                 output.close();
                 break;
            case 'n':
                 restart2:
                 cout << "Enter the year: ";
                 cin >> year;
                 if ( year < 1980 || year > 2008 )
                 {          
                            cout << "Year must be at least 1980 and at most 2008!\n";
                                 goto restart2;
                 }
                 year = year % 29;
                 cout << setprecision ( 3 );
                 for ( i = 0; i < 12; i++ )
                 {
                     percent[i] = ((float) total[year] )/ energy[year][i];
                 }
                 cout << setiosflags(ios::fixed) << setiosflags(ios::showpoint) << setprecision(4);
                 cout << setw(0) << "Energy Source" << setw(15) << "Energy in Megawatt Hours" << setw(30) << "Percent of Total Energy\n";
                 elementCount = 13;
                 for ( i = 0; i < elementCount; i++ )
                 {
                     cout << setw(0) << types[i] << setw(15) << energy[year][i+1] << setw(30) << percent[i] << "%" << "\n";
                 }
                 break;
     }
}
void sort ( int input[][14], int reference[], int output[], int l, int mat )
{
     bool t;
     int i;
     for ( i = 0; i < l; i++ )
     {
         reference[i] = i;
     }
     do
     {
         t = false;
         for ( i = 0; i < l-1; i++ )
         {
             if ( input[i] > input[i+1] )
             {
                  t = true;
                  input[i][mat] = input[i][mat]^input[i+1][mat];
                  input[i+1][mat] = input[i][mat]^input[i+1][mat];
                  input[i][mat] = input[i][mat]^input[i+1][mat];
                  reference[i] = reference[i]^reference[i+1];
                  reference[i+1] = reference[i]^reference[i+1];
                  reference[i] = reference[i]^reference[i+1];
             }
         }
     }while(t);
     for ( i = 0; i < 29; i++ )
     {
         output[i] = input[i][mat];
     }
}
void option2 ( int energy[29][14], string types[13], int64_t total[29], int64_t fossilfuel[29], int64_t renewable[29] )
{
     unsigned char choice;
     int ref[29] = {0,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};
     int sorted[29];
     int i;
     cout << "Please enter the energy type you are finding the peak of out of these choices:" << endl;
     for ( i = 0; i < 13; i++ )
     {
         cout << i+1 << ". " << types[i] << endl;
     }
     cin >> choice;
     sort ( energy, ref, sorted, 29, i );
     cout << energy[0][i+1] << endl << energy[1][i+1];
}
int main()
{
    int energy[29][14];
    int64_t fossilfuel[29];
    int64_t renewable[29];
    int64_t total[29];
    string types[13] = {"Coal","Petroleum","Natural Gas","Other Gases","Nuclear","Hydro-Electric Pmpd.","Hydro-Electric","Biomass - Wood","Biomass - Waste","Geothermal","Solar","Wind","Other"};
    int r, c;
    unsigned char option;
    ifstream energyfile("energy.dat");
    for ( r = 0; r < 29; r++ )
    {
        for ( c = 0; c < 13; c++ )
        {
            energyfile >> energy[r][c];
        }
    }
    for ( int i = 0; i <= 28; i++ )
    {
        fossilfuel[i] = 0;
        renewable[i] = 0;
        total[i] = 0;
        for ( c = 1; c <= 4; c++ )
        {
            fossilfuel[i] += energy[i][c];
            total[i] += energy[i][c];
        }
        total[i] += energy[i][5];
        total[i] += energy[i][6];
        for ( c = 7; c <= 12; c++ )
        {
            renewable[i] += energy[i][c];
            total[i] += energy[i][c];
        }
        total[i] += energy[i][13];
    }
    cout << "Please enter an option:\nOption 1. Input a year and display a result with energy uses for each energy type.\nOption 2. The peak year of production of a certain energy type.\nOption 3. Create a data file to be opened by Excel." << endl;
    cin >> option;
    switch (option)
    {
           case 1:
                option1(energy, types, total);
                break;
           case 2:
                option2(energy, types, total, fossilfuel, renewable);
                break;
           case 3:
                //option3();
                break;
    }
    cin.ignore();
    cin.get();
    return 0;
}

Looks like you are still having out-of-bounds issue(s), at least. Note that even reading something out-of-bounds may result in a crash/surprise-behaviour (and certainly is a programming error at any rate).
I'd suggest that you add the following assert() to see it for yourself.

#include <cassert> // using assert()

void option2 (...)
{
  ...
  cin >> choice;
  sort ( energy, ref, sorted, 29, i );

  assert(i + 1 < 14);

  cout << energy[0][i+1] << endl << energy[1][i+1];
}

There may be other similar cases as well, so you need to carefully go through all of the code and make sure it doesn't do anything illegal. Using const , as suggested earlier, would ease your job of keeping track of array bounds.

Instead of the 'XOR-trickery' there, consider using std::swap() , like so ..

std::swap(input[i][mat], input[i+1][mat]);
std::swap(reference[i], reference[i+1]);

Or if std::swap() is not allowed, then rather use a temporary variable for swapping.

Then in general, unless planned for later use, remove all unused parameters from function signatures, as in option2() , total , fossilfuel and renewable are not used for anything.

And lastly, you should use better, more descriptive variable naming ( bool t =??), especially avoid using letter ell as an identifier (it looks a whole lot like 1).

Even after correcting my bounds, the same thing happens. After a little testing, i found out that the switch statement doesn't even run. I did this by having it output things like "test" before the switch statement and in the switch statement, and only the one before it gets displayed. That can't be a problem with bounds, can it?

the switch statement doesn't even run.

Add a default case ..

switch (choice)
{
  case 'y':
    ...
  break;
    ...
  default:
  cout << "default case: " << choice << endl;
  break;
}

>> That can't be a problem with bounds, can it?
If you trash memory, anything can happen.

Oh, i just figured out the problem. I was using a char, and i didn't put quotes around the cases (in the switch statement). Its funny how the littlest mistakes can cause the hugest problems.

This article has been dead for over six months. Start a new discussion instead.