与 C++ 中 python 的 Input(“msg”) 类似的函数

Similar function to Input("msg") from python in C++

提问人:Lampros 提问时间:12/22/2021 最后编辑:user438383Lampros 更新时间:1/6/2022 访问量:244

问:

我希望在 c++ 中制作这个函数,input(“x = ”);,有点像在 python 中,这个函数在 () 和期望输入中打印消息。它只能接受 bool,str,int,double。我想像这样做一个结构输入

struct input {
 
 std::string str;
 int num;
 double dub;
 bool boolean;
 input(const char *s) {
   std::cout << s;
   std::cin >> ### ; //here is my problem 
 }
};

但这就是我所能做到的。我尝试了模板,但仍然无法弄清楚。

提取输入应该不是那么困难,我会弄清楚的,现在我只想看看如何在结构中获取我的数据。

C++ C++11 模板 IOstream

评论

2赞 eike 12/22/2021
由于您可能从输入中读取的所有内容最初都是字符串,因此您如何知道要提取哪种类型?每个输入适合一个字符串,每个整数字符串适合一个双精度。您必须具有优先级或某种标记来决定如何解释输入

答:

4赞 463035818_is_not_an_ai 12/22/2021 #1

通常,由于根本不同的类型系统,将Python翻译成C++是困难的。但是,这不是问题。从文档

如果存在 prompt 参数,则将其写入标准输出,而不带尾随换行符。然后,该函数从输入中读取一行,将其转换为字符串(去除尾随换行符),并返回该字符串。读取 EOF 时,将引发 EOFError。

Python 不做任何转换。它只返回一个字符串。可以启用异常,但在实际引发异常时,它需要一些样板来重置流异常设置。它可以在 RAII 类的帮助下完成,该类的唯一目的是重置流以前的异常设置,无论函数是返回还是抛出。inputEOF

struct eof_exception_enabled {
    std::istream & inp;
    std::ios::iostate old;
    eof_exception_enabled(std::istream& inp) : inp(inp), old(inp.exceptions()) {
        inp.exceptions(old | std::ios::eofbit);
    }
    ~eof_exception_enabled() {
        inp.exceptions(old);
    }
};


std::string input(std::string prompt = "") {
    std::cout << prompt;
    std::string res;
    auto inp = eof_exception_enabled{std::cin};
    std::getline(inp.inp, res);
    return res;
}

实际上,将输入流也传递给,以便可以使用不同的流会更习惯。不确定这对于提示用户并通常从标准输入中读取的函数有多大意义。input


如果要启用转换,可以使用利用字符串流进行转换的函数模板:

template <typename T>
T from_string(const std::string& str) {
    std::stringstream ss{str};
    T t;
    ss >> t;
    return t;
}

用法将是

auto age = from_string<int>( input("enter your age:"));

但是,正确处理由于意外输入而导致的错误需要更多。 当从整数类型的流中提取失败时,才会返回。不过,现在我们谈论的是转换,在 Python 中也不是由 .from_string0input

评论

1赞 Konrad Rudolph 12/22/2021
为什么?只需无条件打印,它总是有效的。至于 EOF 错误,您可以使用查询并(暂时)告诉流在 EOF 上抛出异常。if (prompt.size() > 0)std::cin.exceptions()
0赞 463035818_is_not_an_ai 12/22/2021
@KonradRudolph 我首先错过了“没有训练换行符”,因此 .我对输入流的例外情况并不流利,但幸运的是,我最近刚刚看到一个关于 Bjarnes 的问题ifIo_guard
0赞 Lampros 1/6/2022 #2

我所做的是做一个班级,

template <typename T> using couple = std::pair<bool, T>;
struct input {
  std::string inp;
  couple<std::string> str = {false, ""};
  couple<int> num = {false, 0};
  couple<double> dbl = {false, 0};
  couple<bool> bl = {false, 0};

  input(const char *s) {
    std::cout << s;
    std::cin >> inp;
    fillinput(inp);
  }
  bool check_bool(std::string inputVal) {
    transform(inputVal.begin(), inputVal.end(), inputVal.begin(), ::tolower);
    if (inputVal == "false") {
      bl.first = true;
      bl.second = false;
      return true;
    }
    if (inputVal == "true") {
      bl.first = bl.second = true;
      return true;
    }
    return false;
  }
  bool check_double(std::string inputVal) {
    int dots = std::count(inputVal.begin(), inputVal.end(), '.');
    bool digits = std::all_of(inputVal.begin(), inputVal.end(), ::isdigit);
    if (dots == 1 && digits) {
      dbl.first = true;
      dbl.second = std::stod(inputVal);
      return true;
    }
    return false;
  }
  bool check_int(std::string inputVal) {
    bool digits = std::all_of(inputVal.begin(), inputVal.end(), ::isdigit);
    if (digits) {
      num.first = true;
      num.second = std::stoi(inputVal);
      return true;
    }
    return false;
  }
  void fillinput(std::string Input) {
    if (check_int(Input) || (check_bool(Input)) || (check_double(Input)))
      return;
    else {
      str.first = true;
      str.second = Input;
    }
  }
};

要使其可用需要更多的工作,但这就是方法。我知道它不是好的代码,但它就是这样。