1

I am trying to do case menu for my program. And I always getting error of cross initialization, I have never before saw this error. Maybe someone could explain me what is happening wrong with my code.

#include <iostream>
#include <cstdlib>
#include <string>
#include <sstream>
#include <stdlib.h>
#include <fstream>

using namespace std;

#define N_CARS 1

struct car{
    string model;
    int year;
    double price;
    bool available;
}cars [N_CARS];


void menu();
void mainMenu();

void writeToFile(ofstream &outputFile , const car& p)
{
    outputFile << p.model << " "
               << p.year << " "
               << p.price << " "
               << p.available<<"\n";
}

int choice1 = 0;


int main(int argc, char** argv) {

    menu();
    return 0;
}


void menu() {

    do {
        mainMenu();

        switch(choice1) {

            case 1:
                string mystr;
                string mystr2;
                string mystr3;

                int n;
                for (n=0; n<N_CARS; n++)
                {
                    cout << "Enter title: ";
                    getline (cin,cars[n].model);
                    cout << "Enter year: ";
                    getline (cin,mystr);
                    stringstream(mystr) >> cars[n].year;
                    cout << "Enter price: ";
                    getline (cin,mystr2);
                    stringstream(mystr2) >> cars[n].price;
                    cout << "Choose availability: ";
                    getline (cin,mystr3);
                    stringstream(mystr3) >> cars[n].available;
                }

                ofstream outputFile;
                outputFile.open("bla.txt", fstream::app);
                for (n=0; n<N_CARS; n++)
                    writeToFile(outputFile, cars[n]);
                outputFile.close();
                break;

            case 2:
                break;

            case 5:
                break;
        }

    } while(choice1 != 5);

}


void mainMenu(void) {

    cout << "Main Menu\n";
    cout << "1 - Enter Car\n";
    cout << "5 - Quit\n";
    cout << "Please choose: ";

    cin >> choice1;
}

Errors:

In function 'void menu()':
    [Error] jump to case label [-fpermissive]
    [Error] crosses initialization of 'std::ofstream outputFile'
    [Error] crosses initialization of 'std::string mystr3'
    [Error] crosses initialization of 'std::string mystr2'
    [Error] crosses initialization of 'std::string mystr'
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
NotsoPr0
  • 53
  • 1
  • 9

2 Answers2

2

case labels are really a lot like dreaded goto labels; they do not constitute a new scope. Consequently, a switch selecting the correct case label to jump to is, for better or worse, a lot like goto statement jumping to a label. The jump is not allowed to cross the initialisation of your various objects - exactly as the error messages say.

The cleanest thing for you to do would be to cut everything between case 1: and break; case 2: and paste it into a new function called something like enterCar.

void enterCar() {
    // code previously found between the case labels
}

// ...
switch(choice1) {
    case 1: enterCar(); break;
    case 2:
    // ...
}

A function constitutes a new scope in which your local objects can be correctly initialised. As a bonus, you are making first steps towards leaving all the spaghetti code behind you.

Christian Hackl
  • 25,191
  • 3
  • 23
  • 53
  • Its good refactor thank you. But now my enter model and enter year show up both instantly, I can not enter model, I dont know what happened, it worked before I start using case switch. – NotsoPr0 Mar 05 '17 at 12:38
  • @NotsoPr0 - The input problem is described here: [Why does std::getline skip input after a formatted extraction?](http://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction) – Bo Persson Mar 05 '17 at 12:48
  • Thank you for your help! – NotsoPr0 Mar 05 '17 at 12:53
0

You have to enclose variable definitions within case-blocks with scope brackets {}.

Another thing: forget about #define for comple time constants, use constexpr:

constexpr size_t NumCars = 5;

Also note the size_t: for variables and constants describing sizes, e.g. array sizes or indices, use size_t.

Further, you include cstdlib and stdlib.h. Headerfiles from the C-standardlibrary should always be included with the c-prefix and .h-omission, so kick out the stdlib.h. You don't need it anyway.

The Techel
  • 814
  • 8
  • 13
  • *"Also note the size_t: for variables and constants describing sizes, e.g. array sizes or indices, use size_t."* - No, it's better to use a signed type for sizes, because otherwise you are effectively hiding errors with negative numbers. See http://stackoverflow.com/a/10168569/3313064 – Christian Hackl Mar 05 '17 at 12:24
  • okey, thanks for you advice. It is working now, but `enter title` cout goes together with `enter year` and I can not enter title now. – NotsoPr0 Mar 05 '17 at 12:25
  • The linked post doesn't convince me. It states that there are pitfalls when doing arithmetic with signed integers and mixing in unsigned ones, but at the other hand doing arithmetic with unsigned integers and mixing in signed ones is basically the same. The point I'm trying to make: Think carefully whether you want to do signed oder unsigned arithmetic. For NotsoPr0: http://stackoverflow.com/questions/10553597/cin-and-getline-skipping-input – The Techel Mar 05 '17 at 13:44
  • @TheTechel: Yes, mixing signed and unsigned is bad. You should therefore stay away from unsigned numbers *in general*. Unsigned numbers are only really useful for bit operations, i.e. when you are interested in individual bits; using them to avoid negative numbers when only positive ones are allowed is a bad idea. – Christian Hackl Mar 05 '17 at 15:18
  • A bad idea? Why? – The Techel Mar 05 '17 at 15:37
  • There are reasons to use unsigned over signed arithmetic or vice versa, e.g. Indexing something vs. doing calculations with actual *values* like money and coordinates. – The Techel Mar 05 '17 at 15:45