【问题标题】:Switch Statement Called Inside Of A Failed If Statement在失败的 If 语句中调用 Switch 语句
【发布时间】:2021-07-19 11:06:35
【问题描述】:

抱歉,如果标题具有误导性或笼统。我真的不知道还有什么可以命名的标题。我创建了一个函数,可以将任何类型的向量转换为字符串。我有 template<typename K> 前面的函数代码,它用作向量类型的占位符。我的主要问题是用于检查向量类型的 if 语句中的嵌套 switch 语句。即使 if 语句检查失败,代码仍然会出现此错误:a switch expression of type 'float' is not valid。例如,如果我在 main 中声明了一个 float 类型的向量,那么我使用该函数将向量转换为字符串,它会给我两个错误。一个用于嵌套在int 检查内的switch 语句,另一个用于嵌套在char 检查内的switch 语句。这是非常令人沮丧的,因为如果由于向量不是intchar 而导致检查失败。此外,它们也不能同时是intchar!我一直在尝试剖析我的代码并解决这个问题,但我没有找到解决方案。也许是因为我不熟悉模板和 std::is_same 函数。

这是我的头文件代码(有点长):

#include <string>
#include <vector>

//Converts a vector of any type into a string like this: 2, 5, 6, 3, (Yes the comma stays at the end like that. That can be fixed but it will require huge amounts of code)
template<typename K>
std::string convertToString(std::vector<K>& V) {

    std::string result_str{""};

    for (auto s : V) {

        if (std::is_same<K, bool>::value) {

            if (s == true) {

                result_str += "true, ";

            }
            else if (s == false) {

                result_str += "false, ";

            }

        }
        else if (std::is_same<K, int>::value) {

            switch (s) {

            case 1:
                result_str += "1, ";
                break;

            case 2:
                result_str += "2, ";
                break;

            case 3:
                result_str += "3, ";
                break;

            case 4:
                result_str += "4, ";
                break;

            case 5:
                result_str += "5, ";
                break;

            case 6:
                result_str += "6, ";
                break;

            case 7:
                result_str += "7, ";
                break;

            case 8:
                result_str += "8, ";
                break;

            case 9:
                result_str += "9, ";
                break;

            default:
                result_str += "Not a digit, ";

            }

        }
        else if (std::is_same<K, float>::value) {

            //Because switch statements cannot take floating point values (For some reason I thought this would fix my problem but it didn't)
            if (s == 1) {

                result_str += "1, ";

            }
            else if (s == 2) {

                result_str += "2, ";

            }
            else if (s == 3) {

                result_str += "3, ";

            }
            else if (s == 4) {

                result_str += "4, ";

            }
            else if (s == 5) {

                result_str += "5, ";

            }
            else if (s == 6) {

                result_str += "6, ";

            }
            else if (s == 7) {

                result_str += "7, ";

            }
            else if (s == 8) {

                result_str += "8, ";

            }
            else if (s == 9) {

                result_str += "9, ";

            }
            else {
                result_str += "., ";
            }

        }
        else if (std::is_same<K, char>::value) {

            switch (s)
            {
            case 'a': 
                result_str += "a, ";
                break;

            case 'A':
                result_str += "A, ";
                break;

            case 'b': 
                result_str += "b, ";
                break;

            case 'B':
                result_str += "B, ";
                break;

            case 'c': 
                result_str += "c, ";
                break;

            case 'C':
                result_str += "C, ";
                break;

            case 'd': 
                result_str += "d, ";
                break;

            case 'D':
                result_str += "D, ";
                break;

            case 'e': 
                result_str += "e, ";
                break;

            case 'E':
                result_str += "E, ";
                break;

            case 'f': 
                result_str += "f, ";
                break;

            case 'F':
                result_str += "F, ";
                break;

            case 'g': 
                result_str += "g, ";
                break;

            case 'G':
                result_str += "G, ";
                break;

            case 'h':
                result_str += "h, ";
                break;

            case 'H':
                result_str += "H, ";
                break;

            case 'i':
                result_str += "i, ";
                break;

            case 'I':
                result_str += "I, ";
                break;

            case 'j': 
                result_str += "j, ";
                break;

            case 'J':
                result_str += "J, ";
                break;

            case 'k': 
                result_str += "k, ";
                break;

            case 'K':
                result_str += "K, ";
                break;

            case 'l': 
                result_str += "l, ";
                break;

            case 'L':
                result_str += "L, ";
                break;

            case 'm': 
                result_str += "m, ";
                break;

            case 'M':
                result_str += "M, ";
                break;

            case 'n': 
                result_str += "n, ";
                break;

            case 'N':
                result_str += "N, ";
                break;

            case 'o': 
                result_str += "o, ";
                break;

            case 'O':
                result_str += "O, ";
                break;

            case 'p': 
                result_str += "p, ";
                break;

            case 'P':
                result_str += "P, ";
                break;

            case 'q': 
                result_str += "q, ";
                break;

            case 'Q':
                result_str += "Q, ";
                break;

            case 'r': 
                result_str += "r, ";
                break;

            case 'R':
                result_str += "R, ";
                break;

            case 's': 
                result_str += "s, ";
                break;

            case 'S':
                result_str += "S, ";
                break;

            case 't': 
                result_str += "t, ";
                break;

            case 'T':
                result_str += "T, ";
                break;

            case 'u': 
                result_str += "u, ";
                break;

            case 'U':
                result_str += "U, ";
                break;

            case 'v': 
                result_str += "v, ";
                break;

            case 'V':
                result_str += "V, ";
                break;

            case 'w': 
                result_str += "w, ";
                break;

            case 'W':
                result_str += "W, ";
                break;

            case 'x':
                result_str += "x, ";
                break;

            case 'X':
                result_str += "X, ";
                break;

            case 'y': 
                result_str += "y, ";
                break;

            case 'Y':
                result_str += "Y, ";
                break;

            case 'z': 
                result_str += "z, ";
                break;

            case 'Z':
                result_str += "Z, ";
                break;
            }

        }

    }

    return result_str;

}

这是我的 cpp 文件代码:

#include "Helper.h"
#include <iostream>

std::vector<float> nums{ 2.4, 65.2, 56.3, 4.6 };

int main() {

    std::cout << convertToString(nums);

}

【问题讨论】:

    标签: c++ if-statement templates vector types


    【解决方案1】:

    我认为编译器在编译期间会检查 switch expr。 也许你可以使用一些字符串方法来做到这一点,就像那样
    else if (std::is_same&lt;K, char&gt;::value) { result_str.push_back(s); }

    else if (std::is_same&lt;K, int&gt;::value) { result_str.append(std::to_string(s)); }

    【讨论】:

    • 我考虑过使用 if/else 逻辑,但如果我可以使用 switch 语句似乎有点不必要。我想弄清楚的是,如果“if”语句的计算结果为假,为什么编译器会检查 switch 语句?编译器不会完全跳过它吗?
    【解决方案2】:

    我认为你把事情复杂化了。您可以利用 std::to_string 和类型特征检查器来完成大部分工作:

    #include <string>
    #include <type_traits>
    #include <vector>
    
    template<typename K>
    std::string convertToString_helper(K s) {
        //Test from most specific to least to prevent bool and char being converted incorrectly.
        if constexpr(std::is_same_v<K, bool>) {
            return s ? std::string{"true"} : std::string{"false"};
        } else if constexpr(std::is_same_v<K, char>) {
            return std::string{s};
        } else if constexpr(std::is_integral_v<K> || std::is_floating_point_v<K>) {
            return std::to_string(s);
        } else if constexpr(std::is_convertible_v<K, std::string>) {
            return s;
        } else {
            return "Not convertible to a string";
        }
    }
    
    template<typename K>
    std::string convertToString(std::vector<K>& V) {
        std::string result{};
        for(auto iter = std::cbegin(V); iter != std::cend(V) - 1; ++iter) {
            result += convertToString_helper(*iter) + ", ";
        }
        auto last_iter = std::cend(V) - 1;
        result += convertToString_helper(*last_iter);
        return result;
    }
    

    【讨论】:

    • 你的函数其实比我的复杂,只是我的函数更长。另外,convertToString_helper() 中的 constexpr 在做什么?
    • 那么为什么你在把东西放入convertToString_helper()时使用指针?
    • @HyperTextMarkupMan 不是指针。迭代器。它们需要被取消引用才能获得基础值。
    • @HyperTextMarkupMan convertToString_helper 防止重复重复代码只是为了不在末尾附加逗号。
    • 所以在那种情况下指针实际上并不像指针一样?我也知道convertToString_helper 防止重复重复代码只是为了不在末尾附加逗号,但constexpr 在函数中做了什么?我以前从未在我的任何程序中使用过constexpr,所以如果我要使用该功能,了解它的工作原理会很有帮助。
    【解决方案3】:

    您使用的是浮点向量,因此当编译器编译代码时,它会将模板版本替换为浮点版本,因此switch (s) 行在 switch 语句中使用浮点,至于解决方案,这里是使用字符串流的简化版本

    #include <string>
    #include <vector>
    #include <iostream>
    #include <sstream>
    
    std::vector<float> nums{2.4, 65.2, 56.3, 4.6};
    std::vector<bool> b{true, false, false};
    std::vector<int> i{1,2,3,4,5};
    //Converts a vector of any type into a string like this: 2, 5, 6, 3, (Yes the comma stays at the end like that. That can be fixed but it will require huge amounts of code)
    template <typename K>
    std::string convertToString(std::vector<K> &V)
    {
        std::string result_str{""};
        for (auto s : V)
        {
                std::stringstream converter;
                converter << std::boolalpha << s; 
                result_str += converter.str() + ", ";
    
        }
        return result_str;
    }
    
    int main()
    {
        std::cout<< convertToString(b)<<std::endl;
        std::cout<< convertToString(nums)<<std::endl;
        std::cout<< convertToString(i)<<std::endl;
    }
    

    如果需要,您可以跟进子字符串操作以删除最后一个逗号。

    【讨论】:

    • 谢谢!这比 Casey 的版本简单得多,也更容易理解,尽管 Casey 的版本仍然运行良好并且非常有用。
    • 如果您对分辨率满意,请接受并关闭操作类型
    猜你喜欢
    • 1970-01-01
    • 2016-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 2019-01-26
    • 2010-09-15
    相关资源
    最近更新 更多