Использование ifstream в качестве fscanf
предположим, что у меня есть вход следующим образом:
N (X_1,Y_1) (X_2,Y_2) .... (X_N, Y_N)
где N, X_i и Y_i-целые числа.
пример:
2 (55,1) (521,7)
читать это, я могу сделать что-то вроде этого(предположим, что все переменные и т. д.):
fscanf(fin,"%d ",&N);
for (int i = 0; i < N; i++)
fscanf(fin,"(%d,%d) ", &X[i], &Y[i]);
вопрос в том, как я могу сделать это легко, используя ifstream. Я могу получить строки, а затем я могу избавиться от nondigits и с помощью stringstream я могу получить два числа, но это кажется немного громоздким. Есть ли проще, больше элегантный способ?
спасибо
2 ответов
int n, x, y;
char c;
if (is >> n)
for (int i = 0; i < n; ++i)
if (is >> c && c == '(' &&
is >> x &&
is >> c && c == ',' &&
is >> y &&
is >> c && c == ')')
{
X[i] = x;
Y[i] = y;
}
else
throw std::runtime_error("invalid inputs");
вы можете упростить все важные внутренние if
условие выше...
is >> chlit('(') >> x >> chlit(',') >> y >> chlit(')')
...с простым типом поддержки для потребления определенного символа:
struct chlit
{
chlit(char c) : c_(c) { }
char c_;
};
inline std::istream& operator>>(std::istream& is, chlit x)
{
char c;
if (is >> c && c != x.c_)
is.setstate(std::iostream::failbit);
return is;
}
см. полную программу, иллюстрирующую это на ideone здесь.
мой старый пост сделал что-то подобное для потребления определенных строк. (Выше chlit
может быть шаблоном, но chlit<','>()
некрасиво читать и писать - я бы предпочел доверять компилятор.)
cin >> N;
for (int i = 0; i < N; i++)
{
cin.ignore(100,'(');
cin >> X[i];
cin.ignore(100,',');
cin >> Y[i];
cin.ignore(100,')');
}
Он также может обрабатывать пробелы, так как он может читать входные данные, такие как:
2 ( 1 , 3 ) ( 5 , 6 )
демонстрация в ideone:http://www.ideone.com/hO0xG