Tại sao câu lệnh switch không thể được áp dụng trên chuỗi?


227

Biên dịch mã sau đây và nhận được lỗi của type illegal.

int main()
{
    // Compilation error - switch expression of type illegal
    switch(std::string("raj"))
    {
    case"sda":
    }
}

Bạn không thể sử dụng chuỗi trong một switchhoặc case. Tại sao? Có giải pháp nào hoạt động độc đáo để hỗ trợ logic tương tự như bật chuỗi không?


6
Có một sự thay thế thúc đẩy nào che giấu việc xây dựng bản đồ, enum đằng sau một MACRO không?
balki

@balki Tôi không chắc chắn về boost nhưng thật dễ dàng để viết các macro như vậy. Trong trường hợp Qt thì bạn có thể ẩn ánh xạ vớiQMetaEnum
phuclv

Câu trả lời:


189

Lý do tại sao phải làm với hệ thống loại. C / C ++ không thực sự hỗ trợ các chuỗi như một loại. Nó không hỗ trợ ý tưởng về một mảng char không đổi nhưng nó không thực sự hiểu đầy đủ khái niệm về một chuỗi.

Để tạo mã cho câu lệnh chuyển đổi, trình biên dịch phải hiểu ý nghĩa của hai giá trị là bằng nhau. Đối với các mục như ints và enums, đây là một so sánh bit nhỏ. Nhưng trình biên dịch nên so sánh 2 giá trị chuỗi như thế nào? Trường hợp nhạy cảm, không nhạy cảm, nhận thức văn hóa, vv ... Nếu không có nhận thức đầy đủ về chuỗi, điều này không thể được trả lời chính xác.

Ngoài ra, các câu lệnh chuyển đổi C / C ++ thường được tạo dưới dạng bảng nhánh . Việc tạo bảng chi nhánh cho chuyển đổi kiểu chuỗi gần như không dễ dàng.


11
Đối số bảng nhánh không nên áp dụng - đó chỉ là một cách tiếp cận khả thi cho tác giả trình biên dịch. Đối với một trình biên dịch sản xuất, người ta phải thường xuyên sử dụng một số cách tiếp cận tùy thuộc vào độ phức tạp của công tắc.
plinth

5
@plinth, tôi đặt nó ở đó chủ yếu vì lý do lịch sử. Rất nhiều câu hỏi "tại sao C / C ++ làm điều này" có thể dễ dàng được trả lời bởi lịch sử của trình biên dịch. Vào thời điểm họ viết nó, C đã được vinh danh lắp ráp và do đó chuyển đổi thực sự là một bảng chi nhánh thuận tiện.
JaredPar

114
Tôi bỏ phiếu vì tôi không hiểu làm thế nào trình biên dịch có thể biết cách so sánh 2 giá trị chuỗi trong câu lệnh if mà quên cách thực hiện điều tương tự trong câu lệnh switch.

15
Tôi không nghĩ 2 đoạn đầu là lý do hợp lệ. Đặc biệt là từ C ++ 14 khi std::stringchữ được thêm vào. Nó chủ yếu là lịch sử. Nhưng có một vấn đề mà tôi suy nghĩ là với đường switchhiện đang hoạt động, sao chép cases phải được phát hiện tại thời gian biên dịch; tuy nhiên điều này có thể không dễ dàng cho các chuỗi (xem xét lựa chọn ngôn ngữ thời gian chạy, v.v.). Tôi cho rằng một điều như vậy sẽ phải yêu cầu constexprcác trường hợp, hoặc thêm vào hành vi không xác định (không bao giờ là điều mà chúng tôi muốn làm).
MM

8
Có một định nghĩa rõ ràng về cách so sánh hai std::stringgiá trị hoặc thậm chí std::stringvới một mảng const char (cụ thể là bằng cách sử dụng toán tử ==) không có lý do kỹ thuật nào có thể ngăn trình biên dịch tạo ra câu lệnh chuyển đổi cho bất kỳ loại nào cung cấp toán tử đó. Nó sẽ mở ra một số câu hỏi về những thứ như thời gian sống của lables nhưng tất cả điều này chủ yếu là một quyết định thiết kế ngôn ngữ, không phải là một khó khăn kỹ thuật.
MikeMB

60

Như đã đề cập trước đây, trình biên dịch muốn xây dựng các bảng tra cứu để tối ưu hóa các switchcâu lệnh thành thời gian gần O (1) bất cứ khi nào có thể. Kết hợp điều này với thực tế là Ngôn ngữ C ++ không có kiểu chuỗi - std::stringlà một phần của Thư viện chuẩn không phải là một phần của Ngôn ngữ.

Tôi sẽ cung cấp một giải pháp thay thế mà bạn có thể muốn xem xét, tôi đã sử dụng nó trong quá khứ để có hiệu quả tốt. Thay vì tự chuyển đổi chuỗi, hãy chuyển qua kết quả của hàm băm sử dụng chuỗi làm đầu vào. Mã của bạn sẽ gần như rõ ràng như chuyển qua chuỗi nếu bạn đang sử dụng một bộ chuỗi được xác định trước:

enum string_code {
    eFred,
    eBarney,
    eWilma,
    eBetty,
    ...
};

string_code hashit (std::string const& inString) {
    if (inString == "Fred") return eFred;
    if (inString == "Barney") return eBarney;
    ...
}

void foo() {
    switch (hashit(stringValue)) {
    case eFred:
        ...
    case eBarney:
        ...
    }
}

Có một loạt các tối ưu hóa rõ ràng gần như tuân theo những gì trình biên dịch C sẽ làm với câu lệnh chuyển đổi ... thật buồn cười khi điều đó xảy ra.


15
Điều này thực sự đáng thất vọng vì bạn không thực sự băm. Với C ++ hiện đại, bạn thực sự có thể băm vào thời gian biên dịch bằng cách sử dụng hàm băm constexpr. Giải pháp của bạn có vẻ sạch sẽ nhưng có tất cả những điều khó chịu nếu thang không may xảy ra. Các giải pháp bản đồ dưới đây sẽ tốt hơn và tránh gọi hàm. Ngoài ra, bằng cách sử dụng hai bản đồ, bạn cũng có thể có văn bản để ghi nhật ký lỗi.
Dirk Bester


Hashit có thể là một hàm constexpr? Cho rằng bạn truyền vào một const char * chứ không phải là chuỗi std ::.
Victor Stone

Nhưng tại sao? Bạn có thể sử dụng toàn bộ thời gian thực hiện câu lệnh if trên đỉnh của một công tắc. Cả hai đều có tác động tối thiểu, nhưng những lợi thế về hiệu suất với một công tắc bị xóa bỏ bởi tra cứu if-other. Chỉ cần sử dụng một if-other sẽ nhanh hơn một chút, nhưng quan trọng hơn, ngắn hơn đáng kể.
Zoe

20

C ++

Hàm băm constexpr:

constexpr unsigned int hash(const char *s, int off = 0) {                        
    return !s[off] ? 5381 : (hash(s, off+1)*33) ^ s[off];                           
}                                                                                

switch( hash(str) ){
case hash("one") : // do something
case hash("two") : // do something
}

1
Bạn phải chắc chắn rằng không có trường hợp nào của bạn băm đến cùng một giá trị. Và thậm chí sau đó, bạn có thể có một số lỗi trong đó các chuỗi khác băm, ví dụ, cùng một giá trị như hàm băm ("một") sẽ thực hiện không chính xác "cái gì đó" đầu tiên trong chuyển đổi của bạn.
David Ljung Madison Stellar

Tôi biết, nhưng nếu nó băm đến cùng một giá trị thì nó sẽ không biên dịch và bạn sẽ nhận thấy nó đúng hạn.
Nick

Điểm hay - nhưng điều đó không giải quyết được xung đột băm cho các chuỗi khác không phải là một phần của chuyển đổi của bạn. Trong một số trường hợp có thể không quan trọng, nhưng nếu đây là một giải pháp "đi đến" chung chung, tôi có thể tưởng tượng nó là một vấn đề bảo mật hoặc tương tự tại một số điểm.
David Ljung Madison Stellar

7
Bạn có thể thêm một operator ""để làm cho mã đẹp hơn. constexpr inline unsigned int operator "" _(char const * p, size_t) { return hash(p); }Và sử dụng nó như case "Peter"_: break; Demo
hare1039

15

Bản cập nhật C ++ 11 dường như không phải @MarmouCorp ở trên mà là http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4067/Switch-on-Strings-in-C.htm

Sử dụng hai bản đồ để chuyển đổi giữa các chuỗi và enum lớp (tốt hơn so với enum đơn giản vì các giá trị của nó nằm trong phạm vi và tìm kiếm ngược lại cho các thông báo lỗi tốt).

Có thể sử dụng tĩnh trong mã codeguru với sự hỗ trợ của trình biên dịch cho các danh sách khởi tạo có nghĩa là VS 2013 plus. gcc 4.8.1 vẫn ổn với nó, không chắc nó sẽ tương thích xa hơn bao nhiêu.

/// <summary>
/// Enum for String values we want to switch on
/// </summary>
enum class TestType
{
    SetType,
    GetType
};

/// <summary>
/// Map from strings to enum values
/// </summary>
std::map<std::string, TestType> MnCTest::s_mapStringToTestType =
{
    { "setType", TestType::SetType },
    { "getType", TestType::GetType }
};

/// <summary>
/// Map from enum values to strings
/// </summary>
std::map<TestType, std::string> MnCTest::s_mapTestTypeToString
{
    {TestType::SetType, "setType"}, 
    {TestType::GetType, "getType"}, 
};

...

std::string someString = "setType";
TestType testType = s_mapStringToTestType[someString];
switch (testType)
{
    case TestType::SetType:
        break;

    case TestType::GetType:
        break;

    default:
        LogError("Unknown TestType ", s_mapTestTypeToString[testType]);
}

Tôi nên lưu ý rằng sau đó tôi đã tìm thấy một giải pháp yêu cầu chuỗi ký tự và tính toán thời gian biên dịch (C ++ 14 hoặc 17 tôi nghĩ) nơi bạn có thể băm chuỗi trường hợp trong thời gian biên dịch và băm chuỗi chuyển đổi khi chạy. Nó sẽ có giá trị cho các công tắc thực sự dài có lẽ nhưng chắc chắn thậm chí ít tương thích ngược hơn nếu điều đó quan trọng.
Dirk Bester

Bạn có thể chia sẻ giải pháp biên dịch thời gian ở đây không? Cảm ơn!
qed

12

Vấn đề là vì lý do tối ưu hóa, câu lệnh chuyển đổi trong C ++ không hoạt động trên bất cứ thứ gì ngoại trừ các kiểu nguyên thủy và bạn chỉ có thể so sánh chúng với các hằng số thời gian biên dịch.

Có lẽ lý do cho sự hạn chế là trình biên dịch có thể áp dụng một số hình thức tối ưu hóa biên dịch mã xuống một lệnh cmp và một goto trong đó địa chỉ được tính dựa trên giá trị của đối số khi chạy. Do việc phân nhánh và các vòng lặp không chơi tốt với các CPU hiện đại, đây có thể là một tối ưu hóa quan trọng.

Để đi xung quanh điều này, tôi sợ bạn sẽ phải dùng đến nếu tuyên bố.


Một phiên bản tối ưu hóa của câu lệnh chuyển đổi có thể hoạt động với chuỗi là hoàn toàn có thể. Việc họ không thể sử dụng lại cùng một đường dẫn mã mà họ sử dụng cho các kiểu nguyên thủy không có nghĩa là họ không thể thực hiện std::stringvà những người khác là công dân đầu tiên trong ngôn ngữ và hỗ trợ họ trong câu lệnh chuyển đổi với thuật toán hiệu quả.
ceztko

10

std::map + Mô hình lambdas C ++ 11 không có enum

unordered_mapcho khoản khấu hao tiềm năng O(1): Cách tốt nhất để sử dụng HashMap trong C ++ là gì?

#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

int main() {
    int result;
    const std::unordered_map<std::string,std::function<void()>> m{
        {"one",   [&](){ result = 1; }},
        {"two",   [&](){ result = 2; }},
        {"three", [&](){ result = 3; }},
    };
    const auto end = m.end();
    std::vector<std::string> strings{"one", "two", "three", "foobar"};
    for (const auto& s : strings) {
        auto it = m.find(s);
        if (it != end) {
            it->second();
        } else {
            result = -1;
        }
        std::cout << s << " " << result << std::endl;
    }
}

Đầu ra:

one 1
two 2
three 3
foobar -1

Sử dụng các phương thức bên trong với static

Để sử dụng hiệu quả mẫu này bên trong các lớp, hãy khởi tạo bản đồ lambda một cách tĩnh hoặc nếu không bạn phải trả tiền O(n)mỗi lần để xây dựng nó từ đầu.

Ở đây chúng ta có thể thoát khỏi việc {}khởi tạo một staticbiến phương thức: Biến tĩnh trong các phương thức lớp , nhưng chúng ta cũng có thể sử dụng các phương thức được mô tả tại: constructor tĩnh trong C ++? Tôi cần khởi tạo các đối tượng tĩnh riêng

Cần phải chuyển đổi bắt giữ bối cảnh lambda [&]thành một đối số hoặc điều đó sẽ không được xác định: const lambda tự động tĩnh được sử dụng với chụp bằng tham chiếu

Ví dụ tạo ra cùng một đầu ra như trên:

#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

class RangeSwitch {
public:
    void method(std::string key, int &result) {
        static const std::unordered_map<std::string,std::function<void(int&)>> m{
            {"one",   [](int& result){ result = 1; }},
            {"two",   [](int& result){ result = 2; }},
            {"three", [](int& result){ result = 3; }},
        };
        static const auto end = m.end();
        auto it = m.find(key);
        if (it != end) {
            it->second(result);
        } else {
            result = -1;
        }
    }
};

int main() {
    RangeSwitch rangeSwitch;
    int result;
    std::vector<std::string> strings{"one", "two", "three", "foobar"};
    for (const auto& s : strings) {
        rangeSwitch.method(s, result);
        std::cout << s << " " << result << std::endl;
    }
}

3
Lưu ý rằng có một sự khác biệt giữa phương pháp này và một switchtuyên bố. Sao chép các giá trị trường hợp trong một switchcâu lệnh là một lỗi thời gian biên dịch. Sử dụng std::unordered_mapâm thầm chấp nhận các giá trị trùng lặp.
D.Shawley

6

Trong C ++ và C switch chỉ hoạt động trên các loại số nguyên. Sử dụng một thang nếu khác thay thế. C ++ rõ ràng có thể đã thực hiện một số loại tuyên bố swich cho chuỗi - tôi đoán không ai nghĩ nó đáng giá và tôi đồng ý với chúng.


đồng ý, nhưng bạn có biết điều gì khiến điều này không thể sử dụng được không
yesraaj

Lịch sử? Chuyển sang số thực, con trỏ và cấu trúc (chỉ các loại dữ liệu khác của C) không tạo ra sanse, vì vậy C đã giới hạn nó thành số nguyên.

Đặc biệt nếu bạn bật các lớp cho phép chuyển đổi ngầm định, bạn sẽ có một khoảng thời gian thực sự tốt một lần.
sharptooth

6

Tại sao không? Bạn có thể sử dụng thực hiện chuyển đổi với cú pháp tương đương và ngữ nghĩa tương tự. Các Cngôn ngữ không có các đối tượng và chuỗi đối tượng ở tất cả, nhưng chuỗi trong Clà null chấm dứt chuỗi tham chiếu bởi con trỏ. Các C++ngôn ngữ có khả năng để thực hiện chức năng quá tải cho các đối tượng so sánh hoặc kiểm tra đối tượng bất bình đẳng. Như Cnhư C++là đủ linh hoạt để có công tắc như vậy cho các chuỗi cho C ngôn ngữ và cho các đối tượng của bất kỳ loại hỗ trợ mà comparaison hoặc bình đẳng séc cho C++ngôn ngữ. Và hiện đại C++11cho phép để thực hiện chuyển đổi này đủ hiệu quả.

Mã của bạn sẽ như thế này:

std::string name = "Alice";

std::string gender = "boy";
std::string role;

SWITCH(name)
  CASE("Alice")   FALL
  CASE("Carol")   gender = "girl"; FALL
  CASE("Bob")     FALL
  CASE("Dave")    role   = "participant"; BREAK
  CASE("Mallory") FALL
  CASE("Trudy")   role   = "attacker";    BREAK
  CASE("Peggy")   gender = "girl"; FALL
  CASE("Victor")  role   = "verifier";    BREAK
  DEFAULT         role   = "other";
END

// the role will be: "participant"
// the gender will be: "girl"

Có thể sử dụng các loại phức tạp hơn, ví dụ std::pairshoặc bất kỳ cấu trúc hoặc lớp nào hỗ trợ các hoạt động bình đẳng (hoặc kết hợp cho chế độ nhanh ).

Đặc trưng

  • bất kỳ loại dữ liệu nào hỗ trợ so sánh hoặc kiểm tra sự bình đẳng
  • khả năng xây dựng các tầng chuyển đổi lồng nhau lồng nhau.
  • khả năng phá vỡ hoặc rơi qua các báo cáo trường hợp
  • khả năng sử dụng các biểu thức trường hợp không cố định
  • có thể bật chế độ tĩnh / động nhanh với tìm kiếm cây (đối với C ++ 11)

Sự khác biệt của Sintax với chuyển đổi ngôn ngữ là

  • từ khóa viết hoa
  • cần dấu ngoặc đơn cho câu lệnh CASE
  • dấu chấm phẩy ';' cuối báo cáo không được phép
  • dấu hai chấm ':' tại câu lệnh CASE không được phép
  • cần một trong những từ khóa BREAK hoặc FALL ở cuối câu lệnh CASE

Đối với C++97ngôn ngữ sử dụng tìm kiếm tuyến tính. Để C++11hiện đại hơn có thể sử dụng quickchế độ tìm kiếm cây wuth trong đó câu lệnh return trong CASE trở nên không được phép. Việc Cthực hiện ngôn ngữ tồn tại ở đó char*các phép so sánh chuỗi kết thúc kiểu và không được sử dụng.

Tìm hiểu thêm về việc thực hiện chuyển đổi này.


6

Để thêm một biến thể bằng cách sử dụng vùng chứa đơn giản nhất có thể (không cần bản đồ được đặt hàng) ... Tôi sẽ không bận tâm với enum - chỉ cần đặt định nghĩa vùng chứa ngay trước công tắc để dễ dàng xem số nào đại diện cho trong trường hợp nào.

Điều này thực hiện tra cứu băm trong unordered_mapvà sử dụng liên kết intđể điều khiển câu lệnh switch. Nên khá nhanh. Lưu ý rằng atđược sử dụng thay vì [], như tôi đã tạo ra container đó const. Việc sử dụng []có thể nguy hiểm - nếu chuỗi không có trong bản đồ, bạn sẽ tạo một ánh xạ mới và có thể kết quả không xác định hoặc bản đồ đang phát triển liên tục.

Lưu ý rằng at()hàm sẽ đưa ra một ngoại lệ nếu chuỗi không có trong bản đồ. Vì vậy, bạn có thể muốn kiểm tra đầu tiên bằng cách sử dụng count().

const static std::unordered_map<std::string,int> string_to_case{
   {"raj",1},
   {"ben",2}
};
switch(string_to_case.at("raj")) {
  case 1: // this is the "raj" case
       break;
  case 2: // this is the "ben" case
       break;


}

Phiên bản có kiểm tra chuỗi không xác định sau:

const static std::unordered_map<std::string,int> string_to_case{
   {"raj",1},
   {"ben",2}
};
// in C++20, you can replace .count with .contains
switch(string_to_case.count("raj") ? string_to_case.at("raj") : 0) {
  case 1: // this is the "raj" case
       break;
  case 2: // this is the "ben" case
       break;
  case 0: //this is for the undefined case

}

4

Tôi nghĩ lý do là trong các chuỗi C không phải là kiểu nguyên thủy, như tomjen đã nói, hãy nghĩ trong một chuỗi như một mảng char, vì vậy bạn không thể làm những việc như:

switch (char[]) { // ...
switch (int[]) { // ...

3
Nếu không tìm kiếm nó, một mảng ký tự có thể sẽ suy biến thành char *, chuyển đổi trực tiếp thành một kiểu tích phân. Vì vậy, nó có thể biên dịch tốt, nhưng chắc chắn nó sẽ không làm những gì bạn muốn.
David Thornley

3

Trong chuỗi c ++ không phải là công dân hạng nhất. Các hoạt động chuỗi được thực hiện thông qua thư viện tiêu chuẩn. Tôi nghĩ rằng, đó là lý do. Ngoài ra, C ++ sử dụng tối ưu hóa bảng nhánh để tối ưu hóa các câu lệnh tình huống chuyển đổi. Có một cái nhìn vào liên kết.

http://en.wikipedia.org/wiki/Switch_statement


2

Trong C ++, bạn chỉ có thể sử dụng câu lệnh chuyển đổi trên int và char


3
Một char cũng biến thành int.
strager

Con trỏ cũng có thể. Điều đó có nghĩa là đôi khi bạn có thể biên dịch thứ gì đó có ý nghĩa bằng một ngôn ngữ khác, nhưng nó sẽ không chạy đúng.
David Thornley

Bạn thực sự có thể sử dụng longlong long, sẽ không biến thành int. Không có nguy cơ cắt ngắn ở đó.
MSalters


0
    cout << "\nEnter word to select your choice\n"; 
    cout << "ex to exit program (0)\n";     
    cout << "m     to set month(1)\n";
    cout << "y     to set year(2)\n";
    cout << "rm     to return the month(4)\n";
    cout << "ry     to return year(5)\n";
    cout << "pc     to print the calendar for a month(6)\n";
    cout << "fdc      to print the first day of the month(1)\n";
    cin >> c;
    cout << endl;
    a = c.compare("ex") ?c.compare("m") ?c.compare("y") ? c.compare("rm")?c.compare("ry") ? c.compare("pc") ? c.compare("fdc") ? 7 : 6 :  5  : 4 : 3 : 2 : 1 : 0;
    switch (a)
    {
        case 0:
            return 1;

        case 1:                   ///m
        {
            cout << "enter month\n";
            cin >> c;
            cout << endl;
            myCalendar.setMonth(c);
            break;
        }
        case 2:
            cout << "Enter year(yyyy)\n";
            cin >> y;
            cout << endl;
            myCalendar.setYear(y);
            break;
        case 3:
             myCalendar.getMonth();
            break;
        case 4:
            myCalendar.getYear();
        case 5:
            cout << "Enter month and year\n";
            cin >> c >> y;
            cout << endl;
            myCalendar.almanaq(c,y);
            break;
        case 6:
            break;

    }

4
Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do và / hoặc cách mã này trả lời câu hỏi cải thiện giá trị lâu dài của nó.
Benjamin W.

0

trong nhiều trường hợp, bạn có thể tránh được việc làm thêm bằng cách kéo char đầu tiên từ chuỗi và bật nó. cuối cùng có thể phải thực hiện một chuyển đổi lồng nhau trên charat (1) nếu trường hợp của bạn bắt đầu với cùng một giá trị. Bất cứ ai đọc mã của bạn cũng sẽ đánh giá cao một gợi ý bởi vì hầu hết sẽ thăm dò chỉ khi-khác-nếu


0

Giải pháp thay thế chức năng cho vấn đề chuyển đổi:

class APIHandlerImpl
{

// define map of "cases"
std::map<string, std::function<void(server*, websocketpp::connection_hdl, string)>> in_events;

public:
    APIHandlerImpl()
    {
        // bind handler method in constructor
        in_events["/hello"] = std::bind(&APIHandlerImpl::handleHello, this, _1, _2, _3);
        in_events["/bye"] = std::bind(&APIHandlerImpl::handleBye, this, _1, _2, _3);
    }

    void onEvent(string event = "/hello", string data = "{}")
    {
        // execute event based on incomming event
        in_events[event](s, hdl, data);
    }

    void APIHandlerImpl::handleHello(server* s, websocketpp::connection_hdl hdl, string data)
    {
        // ...
    }

    void APIHandlerImpl::handleBye(server* s, websocketpp::connection_hdl hdl, string data)
    {
        // ...
    }
}

-1

Bạn không thể sử dụng chuỗi trong trường hợp chuyển đổi. Chỉ được phép int & char. Thay vào đó, bạn có thể thử enum để biểu diễn chuỗi và sử dụng nó trong khối trường hợp chuyển đổi như

enum MyString(raj,taj,aaj);

Sử dụng nó int tuyên bố trường hợp swich.



-1

Công tắc chỉ hoạt động với các loại tích phân (int, char, bool, v.v.). Tại sao không sử dụng bản đồ để ghép một chuỗi với một số và sau đó sử dụng số đó với công tắc?


-2

Đó là bởi vì C ++ biến các công tắc thành các bảng nhảy. Nó thực hiện một thao tác tầm thường trên dữ liệu đầu vào và nhảy đến địa chỉ thích hợp mà không so sánh. Vì một chuỗi không phải là một số, mà là một mảng các số, C ++ không thể tạo bảng nhảy từ nó.

movf    INDEX,W     ; move the index value into the W (working) register from memory
addwf   PCL,F       ; add it to the program counter. each PIC instruction is one byte
                    ; so there is no need to perform any multiplication. 
                    ; Most architectures will transform the index in some way before 
                    ; adding it to the program counter

table                   ; the branch table begins here with this label
    goto    index_zero  ; each of these goto instructions is an unconditional branch
    goto    index_one   ; of code
    goto    index_two
    goto    index_three

index_zero
    ; code is added here to perform whatever action is required when INDEX = zero
    return

index_one
...

(mã từ wikipedia https://en.wikipedia.org/wiki/Branch_table )


4
C ++ không yêu cầu thực hiện cụ thể cú pháp của nó. Việc triển khai cmp/ ngây thơ jcccó thể có giá trị theo Tiêu chuẩn C ++.
Ruslan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.