#c #if-statement #hashmap
Вопрос:
Я занимаюсь C , и мое приложение, например, принимает подкоманды ./my_app test 123
.
Я наполовину новичок в C и ничего не могу найти в Интернете, так что я не знаю, ха-ха.
Например, в python я бы сделал:
#!/usr/bin/env python3
import sys
def test(num):
print(f"Test {num}")
subcommands = {"test": test}
subcommands[sys.argv[1](sys.argv[2])
какой-нибудь C эквалайзер к этому? если да, то должен ли я использовать его или придерживаться if-else_if-else?
Комментарии:
1. Я не знаю, что такое стена «если». Какие — нибудь отношения с Ларри Уоллом?
2. @user4581301 стена оператора if = набор операторов if/else if/else, пример: pastebin.com/4nJ6QmXr
3. Придерживайтесь
if
сначала. Если вы действительно хотите, попробуйтеstd::map
,std::string
иstd::function
, но они приводят к снижению производительности.4. В C , в отличие от Python, нет встроенной поддержки сопоставления строки с функцией. Если вам нужна такая возможность, вам необходимо ее реализовать (например, структура данных и/или код для явного сопоставления строки с указателем функции, чтобы вызвать эту функцию — и это должно быть адаптировано для приложения). Разница заключается в разных причинах, например, Python является интерпретируемым языком, в то время как C — нет.
5. @Ari157 Спасибо. Приятно это знать. Я всегда называл их «если бы лестницы».
Ответ №1:
Взгляните на std::map
/ std::unordered_map
, например:
#include <iostream>
#include <map>
#include <string>
void test(const std::string amp;value) {
std::cout << "Test " << value << std::endl;
}
using cmdFuncType = void(*)(const std::string amp;);
const std::map<std::string, cmdFuncType> subcommands = {
{"test": amp;test}
};
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "usage: program command value" << std::endl;
return 0;
}
auto iter = subcommands.find(argv[1]);
if (iter == subcommands.end()) {
std::cerr << "unknown command: " << argv[1] << std::endl;
return 0;
}
iter->second(argv[2]);
return 0;
}
Комментарии:
1. Я склонен идти
std::function<void(std::stringamp;)>
, а не вытаскиватьvoid(*)(const std::string amp;
. Есть ли преимущество в использованииcmdFuncType
такого определения?2. @Martin York template_instantiate_undefined: Неявный экземпляр неопределенного шаблона «std::функция<пусто>»
3. @Ari157 вы добавили
#include <functional>
в использованиеstd::function
?4. @MartinYork
std::function
хорош, если вы хотите использовать лямбды для записей или смешивать лямбды/функторы/функции вместе. Но если все записи будут простыми функциями, то накладныеstd::function
расходы будут немного излишними.5. @Remy Lebeau я сделал, но ваше решение работает, как будто оно ломается только тогда, когда я использую чистую std::функцию<void(std::stringamp;)>
Ответ №2:
Это то, чего вы пытаетесь достичь:
#include <string>
#include <functional>
#include <iostream>
#include <map>
void test(int num) {
std::cout << "Test " << num << "n";
}
std::map<std::string, std::function<void(int)>> subcommands = {
{"test", test}
};
int main(int argc, char* argv[]) {
subcommands[argv[1]](std::atoi(argv[2]));
}
Комментарии:
1. Ошибка сегментации 🙁
2. @Ari157 Я предполагаю, что пользователь вводит допустимые значения. Это MVP.
3. Если вы добавите проверку ошибок. Тогда это в основном выглядит так, как у Реми выше. Уйду отсюда просто потому, что это использует
std::function<void(int)>
, а неvoid(*)(int)
как альтернативу.