changer le délimiteur pour cin (c++)
j'ai redirigé "cin" pour lire à partir d'un flux de fichiers cin.rdbug(inF.rdbug())
Lorsque j'utilise l'extraction de l'opérateur, il lit jusqu'à ce qu'il atteigne un caractère espace blanc.
Est-il possible d'utiliser un autre délimiteur? Je suis passé par l'api dans cplusplus.com mais je n'ai rien trouvé.
3 réponses
il est possible de changer le délimiteur d'inter-mots pour cin
ou std::istream
, en utilisant std::ios_base::imbue
pour ajouter un custom ctype
facet
.
si vous lisez un fichier dans le style de / etc / passwd, le programme suivant Lira chacun des :
- mots délimités séparément.
#include <locale>
#include <iostream>
struct colon_is_space : std::ctype<char> {
colon_is_space() : std::ctype<char>(get_table()) {}
static mask const* get_table()
{
static mask rc[table_size];
rc[':'] = std::ctype_base::space;
rc['\n'] = std::ctype_base::space;
return &rc[0];
}
};
int main() {
using std::string;
using std::cin;
using std::locale;
cin.imbue(locale(cin.getloc(), new colon_is_space));
string word;
while(cin >> word) {
std::cout << word << "\n";
}
}
Pour les chaînes, vous pouvez utiliser le std::getline
surcharges à lire à l'aide d'un délimiteur différent.
pour l'extraction de nombres, le délimiteur n'est pas vraiment "whitespace" pour commencer, mais n'importe quel caractère invalide dans un nombre.
C'est une amélioration sur Robᵩ's réponse, parce que c'est la bonne (et je suis déçu qu'il n'a pas été acceptée.)
Ce que vous devez faire est de modifier le tableau ctype
regarde pour décider ce qu'est un délimiteur.
Dans le cas le plus simple, vous pouvez créer votre propre:
const ctype<char>::mask foo[ctype<char>::table_size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ctype_base::space};
sur ma machine '\n'
10. J'ai placé cet élément du tableau à la valeur du délimiteur:ctype_base::space
. ctype
initialisé avec foo
délimiterait seulement sur '\n'
' '
ou '\t'
.
Maintenant, c'est un problème parce que le tableau passé en ctype
définit plus que ce qu'est un délimiteur, il définit aussi les lettres, les nombres, les symboles, et d'autres cochonneries nécessaires pour le streaming. ( Ben Voigt 's la réponse touche à cela.) Donc, ce que nous voulons vraiment, c'est modifiermask
, pas d'en créer un à partir de zéro.
Qui peut être accompli comme ceci:
const auto temp = ctype<char>::classic_table();
vector<ctype<char>::mask> bar(temp, temp + ctype<char>::table_size);
bar[' '] ^= ctype_base::space;
bar['\t'] &= ~(ctype_base::space | ctype_base::cntrl);
bar[':'] |= ctype_base::space;
ctype
initialisé avec bar
délimiter sur '\n'
et ':'
mais pas ' '
ou '\t'
.
Vous allez sur la configuration de cin
, ou istream
pour utiliser votre custom ctype
comme ceci:
cin.imbue(locale(cin.getloc(), new ctype<char>(data(bar))));
vous pouvez aussi basculer entre ctype
s et le comportement de changement de milieu de jet:
cin.imbue(locale(cin.getloc(), new ctype<char>(foo)));
si vous avez besoin de revenir au comportement par défaut, faites ceci:
cin.imbue(locale(cin.getloc(), new ctype<char>));