О струнных потоках в 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;
Здесь из струнного потока aa
мы сначала читаем рациональную часть ra
(затем buff
за плюс "+"?), то мнимая часть ia
а затем buff
еще раз (может быть, для \n
?). Правильно ли мое понимание? Если я удаляю буферы, это работает нормально для входов, таких как 1+2i
но терпит неудачу, где мнимая часть отрицательна, как 1+-2i
(да не 1-2i
).
Пожалуйста, дайте мне знать, если мое понимание верно. Спасибо!
2 ответа
Вы почти правы. Когда у вас есть строка, как 1+1i
у вас есть два действительных целых числа и два действительных символа. Так aa>>ra
читает первые целые числа в ra
оставляя тебя с +1i
, затем >>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
Таким образом, добавляя явное чтение одного символа, вы читаете "+" во 2-м operator >>
и может читать "3" или "-3" правильно в 3-м вызове operator >>