【问题标题】:Crosses initialization of string and jump to label case跨越字符串初始化并跳转到标签大小写
【发布时间】:2017-03-05 11:58:45
【问题描述】:

我正在尝试为我的程序制作案例菜单。而且我总是遇到交叉初始化错误,我以前从未见过这个错误。也许有人可以解释我的代码出了什么问题。

#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;
}

错误:

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'

【问题讨论】:

    标签: c++ menu switch-statement


    【解决方案1】:

    case 标签真的很像可怕的goto 标签;它们不构成新的范围。因此,switch 选择要跳转到的正确 case 标签无论好坏,很像 goto 语句跳转到标签。不允许跳转跨越各种对象的初始化 - 正如错误消息所说。

    您要做的最干净的事情是剪切case 1:break; case 2: 之间的所有内容并将其粘贴到一个名为enterCar 之类的新函数 中。

    void enterCar() {
        // code previously found between the case labels
    }
    
    // ...
    switch(choice1) {
        case 1: enterCar(); break;
        case 2:
        // ...
    }
    

    一个函数构成了一个新的作用域,您的本地对象可以在其中正确初始化。作为奖励,您正在迈出将所有意大利面条代码抛在脑后的第一步。

    【讨论】:

    • 它很好的重构谢谢。但是现在我的输入模型和输入年份都立即显示,我无法输入模型,我不知道发生了什么,在我开始使用案例切换之前它已经工作了。
    • @NotsoPr0 - 这里描述了输入问题:Why does std::getline skip input after a formatted extraction?
    • 感谢您的帮助!
    【解决方案2】:

    您必须用范围括号 {} 将变量定义括在 case 块中。

    另一件事:忘记 #define 以获得完整的时间常数,使用 constexpr

    constexpr size_t NumCars = 5;
    

    还要注意 size_t:用于描述大小的变量和常量,例如数组大小或索引,使用 size_t。

    此外,您还包括 cstdlibstdlib.h。 C-standardlibrary 中的头文件应始终包含在 c-prefix 和 .h-省略中,因此请退出 stdlib.h。反正你也不需要。

    【讨论】:

    • “还要注意 size_t:对于描述大小的变量和常量,例如数组大小或索引,请使用 size_t。” - 不,最好对大小使用有符号类型,因为否则您实际上是在用负数隐藏错误。见stackoverflow.com/a/10168569/3313064
    • 好的,谢谢你的建议。它现在正在工作,但enter title cout 与enter year 一起使用,我现在无法输入标题。
    • 链接的帖子不能说服我。它指出,使用有符号整数进行算术运算并混合无符号整数时存在缺陷,但另一方面,使用无符号整数进行算术运算并混合有符号整数基本相同。我要说明的一点是:仔细考虑是否要进行有符号或无符号算术。对于 NotsoPr0:stackoverflow.com/questions/10553597/…
    • @TheTechel:是的,混合有符号和无符号是不好的。因此,一般而言,您应该远离无符号数字。无符号数仅对位操作真正有用,即当您对单个位感兴趣时;当只允许正数时使用它们来避免负数是一个坏主意。
    • 一个坏主意?为什么?
    猜你喜欢
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 2015-10-09
    相关资源
    最近更新 更多