如何从用户输入中获取某些值并忽略其他值

How to get certain values from user input and ignore others

本文关键字:其他 获取 用户 输入      更新时间:2023-10-16

有没有办法从这个字符串输入中只获取数字:

h8 f7

如果尝试 fscanf。但是,可能我用错了。

int positionOfTheKnight = 0, finalDestination = 0;
fscanf("%*s%d %*s%d", &positionOfTheKnight, &finalDestination);
cout << positionOfTheKnight << " " << finalDestination;

它显示以下错误:

cpp|11|error: cannot convert 'const char*' to 'FILE* {aka _iobuf*}' for argument '1' to 'int fscanf(FILE*, const char*, ...)'|

我做了一个小样本来演示阅读 OP 示例的多种方法:

#include <cstdio>
#include <iostream>
#include <string>
int rcToInt(char c, char r)
{
if (c < 'a' || c > 'h' || r < '1' || r > '8') {
std::cerr << "Wrong input!n";
return -1;
}
return (c - 'a') * 8 + (r - '1'); // convert characters to index
}
int main()
{
{ // using scanf
std::cout << "Using scanf():n";
char r0, c0, r1, c1;
if (scanf(" %c%c %c%c ", &c0, &r0, &c1, &r1) < 4) {
std::cerr << "Reading move with scanf() failed!n";
} else {
const int pos0 = rcToInt(c0, r0), pos1 = rcToInt(c1, r1);
if (pos0 >= 0 && pos1 >= 0) {
std::cout << "Got " << c0 << r0 << " -> " << c1 << r1 << 'n';
}
}
}
{ // Yet another way to use scanf():
std::cout << "Using scanf():n";
char c0[2], r0[2], c1[2], r1[2];
if (scanf("%1[a-h]%1[1-8] %1[a-h]%1[1-8] ", c0, r0, c1, r1) < 4) {
std::cerr << "Reading move with scanf() failed!n";
} else {
const int pos0 = rcToInt(*c0, *r0), pos1 = rcToInt(*c1, *r1);
if (pos0 >= 0 && pos1 >= 0) {
std::cout << "Got " << c0 << r0 << " -> " << c1 << r1 << 'n';
}
}
}
{ // using std::cin
std::cout << "Using operator>>():n";
char r0, c0, r1, c1;
if (!(std::cin >> c0 >> r0 >> c1 >> r1)) {
std::cerr << "Reading move with operator>>() failed!n";
} else {
const int pos0 = rcToInt(c0, r0), pos1 = rcToInt(c1, r1);
if (pos0 >= 0 && pos1 >= 0) {
std::cout << "Got " << c0 << r0 << " -> " << c1 << r1 << 'n';
}
}
}
// There is still the [ENTER] in input queue which must be consumed:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
// ...before proceeding
{ // using std::cin
std::cout << "Using std::getline():n";
std::string line;
if (!std::getline(std::cin, line) || line.size() < 5) {
std::cerr << "Reading move with std::getline() failed!n";
} else {
const char c0 = line[0], r0 = line[1], c1 = line[3], r1 = line[4];
const int pos0 = rcToInt(c0, r0), pos1 = rcToInt(c1, r1);
if (pos0 >= 0 && pos1 >= 0) {
std::cout << "Got " << c0 << r0 << " -> " << c1 << r1 << 'n';
}
}
}
// done
return 0;
}

输出:

使用 scanf():H8 F7得到 h8 -> f7 使用 scanf():F7 H8得到 f7 -> h8 使用运算符>>():H8 F7得到 h8 -> f7 使用 std::getline():F7 H8

coliru 上

获得 f7 -> h8 现场演示所有四种备选方案都遵循基本思想,将输入读取为字符,然后将它们转换为 [0, 63] 范围内的相应索引。

虽然char可能表示字符,但它也是一个整数值 - 特别是最小的可用整数类型。在(C和)C++中,这没有区别。字符'1'存储为整数值33(假设为 ASCII 代码))。'1'33表示相同的值。因此,如果合适,可以使用字符常量进行算术计算(如上例中的rcToInt())。

  1. if (scanf(" %c%c %c%c ", &c0, &r0, &c1, &r1) < 4) {

    • 格式化程序以空格 () 开头,以使用可选的挂起空格。
    • char*存储一个字符。因此,必须提供一个scanf()参数(指向足够的存储空间)。
    • 格式化程序以空格 () 结尾,以使用终止的ENTER
    • 检查%1[a-h]的返回值以授予将分配所有 4 个参数的权限。
  2. a

    • 格式化程序以空格 () 开头和结尾,以使用周围的空白(如前面的示例所示)。
    • h读取长度为 1 的字符串,该字符串只能由字符char c0[2], r0[2], c1[2], r1[2];、...、%1[1-8]组成。必须为额外的字节提供存储,因为格式化程序将始终存储一个额外的 0 终止符 (1)。因此,在这种情况下2分项。
    • 8与上面类似的字符if (!(std::cin >> c0 >> r0 >> c1 >> r1)) {char、...、iostream。请注意,数字被读取为字符。
  3. operator>>

    • 使用流输入运算符读取四个std::istream& operator>>(std::istream&, char&)变量。
      c1接头提供各种重载std::cin(例如if (!std::getline(std::cin, line) || line.size() < 5) {)为此。
    • 空格
    • (在读取std::string之前出现)将按照默认设置std::string跳过。
  4. std::getline()

    • 将整行读入std::istringstream(适当生长)。
    • 分析该CC_34中的字符。

3. 和 4. 的组合将是读取带有 CC_35 的行,将读取行包装在CC_36中以使用输入流运算符解析它。


抱歉,如果我在上面的代码中交换了行和列。我不是国际象棋专家,也不知道通常的转换。

相关文章: