如何从用户输入中获取某些值并忽略其他值
How to get certain values from user input and ignore others
有没有办法只从这个字符串输入中获取数字:
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↵
得到 f7 -> h8
所有四种方案都遵循将输入读取为字符的基本思想,然后将它们转换为 [0, 63] 范围内的相应索引。
虽然 char
可能代表字符,但它也是一个整数值——特别是最小的可用整数类型。在(C 和)C++ 中,这没有区别。字符 '1'
存储为整数值 33
(假设 ASCII 代码))。 '1'
和 33
代表相同的值。因此,在合适的情况下(如上例中的 rcToInt()
)使用字符常量进行算术计算是很好的(甚至推荐)。
if (scanf(" %c%c %c%c ", &c0, &r0, &c1, &r1) < 4) {
- Formatter 以 space (
</code>) 开始,以消耗可选的未决白色 space.</li>
<li><code>%c
存储一个字符。因此,必须提供 char*
参数(指向足够的存储空间)。
- Formatter 以 space (
</code>) 结尾以消耗终止 <kbd>ENTER</kbd>。</li>
<li>检查 <code>scanf()
的 return 值以授予将分配所有 4 个参数。
if (scanf(" %1[a-h]%1[1-8] %1[a-h]%1[1-8] ", c0, r0, c1, r1) < 4) {
- Formatter 以 space (
</code>) 开始和结束以消耗周围的白色 space(如上例所示)。</li>
<li><code>%1[a-h]
读取长度为 1 的字符串,该字符串可能仅包含字符 a
、b
、...、h
。必须为额外字节提供存储空间,因为格式化程序将始终存储额外的 0 终止符 ([=26=]
)。因此,在这种情况下声明 char c0[2], r0[2], c1[2], r1[2];
。
%1[1-8]
类似于上面的字符 1
、2
、...、8
。请注意,数字被读取为字符。
if (!(std::cin >> c0 >> r0 >> c1 >> r1)) {
- 使用流输入运算符读取四个
char
变量。
iostream
header 为此提供了多种重载的 operator>>
(例如 std::istream& operator>>(std::istream&, char&)
)。
- 白色space(发生在读取
c1
之前)被std::cin
的默认设置跳过。
if (!std::getline(std::cin, line) || line.size() < 5) {
- 将一整行读入
std::string
(适当增长)。
- 分析
std::string
中的字符。
3. 和 4. 的组合是使用 std::getline()
读取一行,将读取的行包装在 std::istringstream
中以使用输入流运算符对其进行解析。
抱歉,如果我在上面的代码中交换了行和列。我不是国际象棋专家,也不知道通常的转换。
有没有办法只从这个字符串输入中获取数字:
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↵ 得到 f7 -> h8
所有四种方案都遵循将输入读取为字符的基本思想,然后将它们转换为 [0, 63] 范围内的相应索引。
虽然 char
可能代表字符,但它也是一个整数值——特别是最小的可用整数类型。在(C 和)C++ 中,这没有区别。字符 '1'
存储为整数值 33
(假设 ASCII 代码))。 '1'
和 33
代表相同的值。因此,在合适的情况下(如上例中的 rcToInt()
)使用字符常量进行算术计算是很好的(甚至推荐)。
if (scanf(" %c%c %c%c ", &c0, &r0, &c1, &r1) < 4) {
- Formatter 以 space (
</code>) 开始,以消耗可选的未决白色 space.</li> <li><code>%c
存储一个字符。因此,必须提供char*
参数(指向足够的存储空间)。 - Formatter 以 space (
</code>) 结尾以消耗终止 <kbd>ENTER</kbd>。</li> <li>检查 <code>scanf()
的 return 值以授予将分配所有 4 个参数。
- Formatter 以 space (
if (scanf(" %1[a-h]%1[1-8] %1[a-h]%1[1-8] ", c0, r0, c1, r1) < 4) {
- Formatter 以 space (
</code>) 开始和结束以消耗周围的白色 space(如上例所示)。</li> <li><code>%1[a-h]
读取长度为 1 的字符串,该字符串可能仅包含字符a
、b
、...、h
。必须为额外字节提供存储空间,因为格式化程序将始终存储额外的 0 终止符 ([=26=]
)。因此,在这种情况下声明char c0[2], r0[2], c1[2], r1[2];
。 %1[1-8]
类似于上面的字符1
、2
、...、8
。请注意,数字被读取为字符。
- Formatter 以 space (
if (!(std::cin >> c0 >> r0 >> c1 >> r1)) {
- 使用流输入运算符读取四个
char
变量。
iostream
header 为此提供了多种重载的operator>>
(例如std::istream& operator>>(std::istream&, char&)
)。 - 白色space(发生在读取
c1
之前)被std::cin
的默认设置跳过。
- 使用流输入运算符读取四个
if (!std::getline(std::cin, line) || line.size() < 5) {
- 将一整行读入
std::string
(适当增长)。 - 分析
std::string
中的字符。
- 将一整行读入
3. 和 4. 的组合是使用 std::getline()
读取一行,将读取的行包装在 std::istringstream
中以使用输入流运算符对其进行解析。
抱歉,如果我在上面的代码中交换了行和列。我不是国际象棋专家,也不知道通常的转换。