关于 C++ 中的字符串流
About stringstreams in C++
在学习面试题的时候,在网上看到了这段代码:
class Solution {
public:
string complexNumberMultiply(string a, string b) {
//I initially did it using substring (searching for "+" etc.)
//But it is super easy using stringstreams
stringstream aa(a), bb(b), ans;
int ra, rb, ia, ib;
char buff;
aa>>ra>>buff>>ia>>buff;
bb>>rb>>buff>>ib>>buff;
ans<<ra*rb-ia*ib<<"+"<<ra*ib+rb*ia<<"i";
return ans.str();
}
};
此代码段将两个输入字符串相乘,表示 a+bi
形式的复数。因此,如果输入为 1+1i
和 1+1i
,则此代码生成的输出为 0+2i
(因为 i^2=-1
)。
我明白为什么使用字符串流 aa
和 bb
以及它们是如何工作的;但我不明白 char buff
的作用。考虑以下语句:
aa>>ra>>buff>>ia>>buff;
这里,从stringstream aa
我们首先读取有理部分ra
(然后buff
是加号“+”?),然后是虚部ia
,然后再次 buff
(可能是 \n
?)。我的理解正确吗?但是,如果我删除缓冲区,它对 1+2i
这样的输入工作正常,但在虚部为负的情况下失败,例如 1+-2i
(是的,不是 1-2i
)。
如果我的理解正确,请告诉我。谢谢!
你几乎是正确的。当你有一个像 1+1i
这样的字符串时,你有两个有效的整数和两个有效的字符。所以 aa>>ra
将第一个整数读入 ra
,留下 +1i
。然后 >>buff
将字符 (+
) 读入 buff,在流中留下 1i
。然后 >>ia
读取下一个整数并在流中留下 i
。然后 >>buff
消耗流中剩余的 i
。
通常在做这样的事情时我喜欢使用更具描述性的变量名。我喜欢使用 eater
很多,因为它暗示我只是在吃掉输入(扔掉它)。如果我知道输入的内容,那么更具描述性的名称就更好了,例如 sign
/operator
/imaginary_part
.
是的,你的理解是正确的。 operator >>
对于每个输入流(std::istream
的祖先)是通用的,它使用 std::num_get::get
表示整数。
根据阶段 2 逻辑和正虚部 aa >> ra >> rb
将 运行 像这样:
2 -> accumulated to storage "2"
(because 2 matches one of "0123456789abcdefxABCDEFX+-")
+ -> ignored, because "2+" is not valid integer for scanf, so first
operator >> terminates here
+ -> accumulated to storage "+"
3 -> accumulated to storage "+3"
i -> ignored, because "+3i" is not a valid integer, so we
can scan "+3" as integer 3 and put it to rb
第二个整数的负虚部被破坏:
+ -> accumulated to storage "+"
- -> "+-" is not a valid scanf, so we should terminate second
operator >> while putting 0 to ra because "+" is also is not
an integer
因此,通过添加单个字符的显式读取,您可以在第二次 operator >>
中读取“+”,并且可以在第三次调用 operator >>
[=19 时正确读取“3”或“-3” =]
在学习面试题的时候,在网上看到了这段代码:
class Solution {
public:
string complexNumberMultiply(string a, string b) {
//I initially did it using substring (searching for "+" etc.)
//But it is super easy using stringstreams
stringstream aa(a), bb(b), ans;
int ra, rb, ia, ib;
char buff;
aa>>ra>>buff>>ia>>buff;
bb>>rb>>buff>>ib>>buff;
ans<<ra*rb-ia*ib<<"+"<<ra*ib+rb*ia<<"i";
return ans.str();
}
};
此代码段将两个输入字符串相乘,表示 a+bi
形式的复数。因此,如果输入为 1+1i
和 1+1i
,则此代码生成的输出为 0+2i
(因为 i^2=-1
)。
我明白为什么使用字符串流 aa
和 bb
以及它们是如何工作的;但我不明白 char buff
的作用。考虑以下语句:
aa>>ra>>buff>>ia>>buff;
这里,从stringstream aa
我们首先读取有理部分ra
(然后buff
是加号“+”?),然后是虚部ia
,然后再次 buff
(可能是 \n
?)。我的理解正确吗?但是,如果我删除缓冲区,它对 1+2i
这样的输入工作正常,但在虚部为负的情况下失败,例如 1+-2i
(是的,不是 1-2i
)。
如果我的理解正确,请告诉我。谢谢!
你几乎是正确的。当你有一个像 1+1i
这样的字符串时,你有两个有效的整数和两个有效的字符。所以 aa>>ra
将第一个整数读入 ra
,留下 +1i
。然后 >>buff
将字符 (+
) 读入 buff,在流中留下 1i
。然后 >>ia
读取下一个整数并在流中留下 i
。然后 >>buff
消耗流中剩余的 i
。
通常在做这样的事情时我喜欢使用更具描述性的变量名。我喜欢使用 eater
很多,因为它暗示我只是在吃掉输入(扔掉它)。如果我知道输入的内容,那么更具描述性的名称就更好了,例如 sign
/operator
/imaginary_part
.
是的,你的理解是正确的。 operator >>
对于每个输入流(std::istream
的祖先)是通用的,它使用 std::num_get::get
表示整数。
根据阶段 2 逻辑和正虚部 aa >> ra >> rb
将 运行 像这样:
2 -> accumulated to storage "2"
(because 2 matches one of "0123456789abcdefxABCDEFX+-")
+ -> ignored, because "2+" is not valid integer for scanf, so first
operator >> terminates here
+ -> accumulated to storage "+"
3 -> accumulated to storage "+3"
i -> ignored, because "+3i" is not a valid integer, so we
can scan "+3" as integer 3 and put it to rb
第二个整数的负虚部被破坏:
+ -> accumulated to storage "+"
- -> "+-" is not a valid scanf, so we should terminate second
operator >> while putting 0 to ra because "+" is also is not
an integer
因此,通过添加单个字符的显式读取,您可以在第二次 operator >>
中读取“+”,并且可以在第三次调用 operator >>
[=19 时正确读取“3”或“-3” =]