Как я могу сопоставить Int с соответствующей строкой в ​​C / C ++ - PullRequest
4 голосов
/ 16 декабря 2009

У меня есть 20 цифр , и я хотел бы связать их со строками. Есть ли более быстрый способ, кроме использования оператора switch case для достижения этой цели.

Мне нужно преобразовать int в соответствующую строку, и числа не обязательно упакованы. Какой-нибудь код в Qt также может быть полезен?

Пример: следующие цифры и строки связаны друг с другом,

1:   "Request System Info"

2:   "Change System Info"

10:  "Unkown Error"

Ответы [ 10 ]

18 голосов
/ 16 декабря 2009

Я рекомендую std :: map <>

#include <map>
#include <string>

std::map<int, std::string> mapping;

// Initialize the map
mapping.insert(std::make_pair(1, "Request System Info"));
mapping.insert(std::make_pair(2, "Change System Info"));
mapping.insert(std::make_pair(10, "Unkown Error"));

// Use the map
std::map<int, std::string>::const_iterator iter =
    mapping.find(num);
if (iter != mapping.end())
{
    // iter->second contains your string
    // iter->first contains the number you just looked up
}

Если у вас есть компилятор, который реализует функцию initalizer-list проекта стандарта C ++ 0x , вы объединяете свое определение и инициализацию карты:

std::map<int, std::string> mapping = {{1, "Request System Info"},
                                      {2, "Change System Info"}
                                      {10, "Unkown Error"}};

std :: map <> хорошо масштабируется до большого количества записей, так как std :: map <> :: find выполняется в O (log N). Если у вас есть функция хеш-карты в черновом стандарте C ++ 0x , вы можете легко преобразовать ее в std :: unordered_map <>, которая должна быть в состоянии искать вещи за O (1) раз. .

7 голосов
/ 16 декабря 2009

Qt также предоставляет свои собственные реализации карт - QMap и QHash .

QMap<int, QString> myMap;
myMap[1234] = "Some value";
myMap[5678] = "Another value";

или

myMap.insert(1234, "Some value");

Документация дает больше примеров, но очень проста в использовании.

5 голосов
/ 16 декабря 2009

более простой способ использования карты

std::map<int, std::string> mymap;
mymap[1] = "foo";
mymap[10] = "bar";
// ...
int idx = 10;
std::string lookup = mymap[idx];
3 голосов
/ 16 декабря 2009

Если ваши строки известны во время компиляции, то вы можете сделать это в C:

#include <stdio.h>

struct message {
    int val;
    const char *msg;
};

int main(void)
{
    struct message messages[] = {
        {1, "Request System Info"},
        {2, "Change System Info"},
        {10, "Unkown Error"}
    };
    size_t nmessages = sizeof messages / sizeof messages[0];
    size_t i;

    for (i=0; i < nmessages; ++i) {
        printf("%d : '%s'\n", messages[i].val, messages[i].msg);
    }
    return 0;
}
3 голосов
/ 16 декабря 2009

Если вы ищете скорость, оператор switch будет наиболее эффективным. Большинство компиляторов C / C ++ реализуют его как двоичное дерево, поэтому оно действительно быстрое.

2 голосов
/ 16 декабря 2009

Если ваши числа и строки постоянны, карта не будет работать; это должно быть загружено.

Для константных чисел и строк я рекомендую массив:

struct Entry
{
   unsigned int  key;
   const char *  text;
};

А для большого количества используйте алгоритм двоичного поиска; в противном случае линейный поиск выполняется примерно так же быстро (если массив отсортирован).

1 голос
/ 16 декабря 2009

Что-то вроде:?

#include <sstream>
using namespace std;
string f(int i)
{
    ostringstream oss;
    oss << i;
    return oss.str();
}
0 голосов
/ 16 декабря 2009

Если ваши числа смежные (или почти совпадают), простой массив или вектор строк будут работать очень хорошо.

Если между числами имеются большие пробелы, скорее всего, самым быстрым методом будет массив std::pair<int, std::string> (или std::pair<int, char *>). В то время как большинство людей автоматически думают о бинарном поиске для быстрого поиска, в этом случае небольшое количество рассматриваемых возможностей вполне может позволить линейному поиску конкурировать довольно эффективно - фактически, это может быть самый быстрый доступный выбор. Причина проста: хотя он будет проводить больше сравнений, он избегает таких делений, как сравнение в 20 дюймов, в любом случае будет быстрым.

Редактировать: обратите внимание, что std :: map, вероятно, не действительно хороший выбор. std :: map обычно использует сбалансированное двоичное дерево, что означает, что 20 элементов будут использовать 20 узлов, каждый из которых обычно выделяется отдельно. Каждый узел обычно включает как минимум два указателя в дополнение к int, который вам нужно хранить, так что вы примерно в три раза увеличиваете объем хранимых данных - все это приводит к относительно плохой локализации кэша. Принимая во внимание небольшое количество элементов, один промах кеша будет стоить более 20 сравнений.

0 голосов
/ 16 декабря 2009

Известны ли строки во время компиляции? Если это так, создайте карту

std :: map messages;

messages [key] = "некоторое значение"; messages [key2] = "какое-то другое значение";

и т.д.

Если они должны быть прочитаны из файла, то что-то вроде этого

std::ifstream ifile("the file")

while (ifile && !ifile.eof())
{
  ifile >> key >> value;
  messages[key] = value;
}

и т.д.

0 голосов
/ 16 декабря 2009

std::map


Прочитав ваш вопрос еще раз, я думаю, вы говорите, что у вас есть только 20 цифр для сопоставления (вы сказали 20 цифр, что заставило меня думать об очень больших числах). Если все они находятся в довольно небольшом диапазоне, вам лучше использовать массив. Вам нужен массив строковых указателей размером largestIndex - smallestIndex + 1. Затем, чтобы получить строку, связанную с определенным числом, вы должны сделать что-то вроде:

std::string GetStatus(int statusID){
    return statusArray[statusID - smallestIndex];
}

Переменная statusArray инициализируется примерно так:

void SetStatus(int statusID, std::string description){
    statusArray[statusID - smallestIndex] = description;
}

void InitStatuses(){
    statusArray = new std::string[largestIndex - smallestIndex + 1];
    SetStatus(1, "Request System Info");
    SetStatus(2, "Change System Info");
    SetStatus(10, "Unknown Error");
}

Это будет быстрее, чем map, и довольно прост в использовании. Это просто не подходит, если ваши идентификаторы сильно различаются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...