有什么方法可以从此字符串输入中仅获取数字:
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*, ...)'|
答案 0 :(得分:2)
我制作了一个小样本来演示阅读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;
}
输出:
Using scanf(): h8 f7↵ Got h8 -> f7 Using scanf(): f7 h8↵ Got f7 -> h8 Using operator>>(): h8 f7↵ Got h8 -> f7 Using std::getline(): f7 h8↵ Got f7 -> h8
所有四个替代方案都遵循基本思想,即以字符形式读取输入,然后将其转换为[0,63]范围内的相应索引。
尽管char
可能表示字符,但它也是一个整数值-特别是最小的可用整数类型。在(C和)C ++中,这没有区别。字符'1'
被存储为整数值33
(假定为ASCII代码)。 '1'
和33
代表相同的值。因此,在适当的情况下(例如上例中的rcToInt()
中),最好(甚至建议)使用字符常量进行算术计算。
if (scanf(" %c%c %c%c ", &c0, &r0, &c1, &r1) < 4) {
)开头,以消耗可选的未决空白。%c
存储一个字符。因此,必须提供char*
参数(指向足够的存储空间)。
)结尾,也要使用终止的 ENTER 。scanf()
的返回值以授予将分配所有4个参数。 if (scanf(" %1[a-h]%1[1-8] %1[a-h]%1[1-8] ", c0, r0, c1, r1) < 4) {
),以占用周围的空白(如上例所示)。%1[a-h]
读取长度为1的字符串,该字符串只能由字符a
,b
,...,h
组成。必须提供一个额外的字节存储空间,因为该格式化程序将始终存储一个额外的0终止符(\0
)。因此,在这种情况下,char c0[2], r0[2], c1[2], r1[2];
的小数位数。%1[1-8]
与上面的字符1
,2
,...,8
类似。请注意,数字被读为字符。 if (!(std::cin >> c0 >> r0 >> c1 >> r1)) {
char
变量。iostream
标头为此提供了各种重载的operator>>
(例如std::istream& operator>>(std::istream&, char&)
)。c1
会跳过空白(在读取std::cin
之前发生)。 if (!std::getline(std::cin, line) || line.size() < 5) {
std::string
(适当增长)。std::string
中的字符。 3和4.的组合是使用std::getline()
读取一行,将读取的行包装在std::istringstream
中,以使用输入流运算符对其进行解析。
对不起,如果我在上面的代码中交换了行和列。我不是国际象棋专家,也不了解通常的转换。