2011-01-22 12 views

Odpowiedz

5

Można użyć locale ch ange, jakie rzeczy są czytane z pliku podczas jego odczytu. Oznacza to, że można odfiltrować wszystkie wartości nienumeryczne:

struct numeric_only: std::ctype<char> 
{ 
    numeric_only(): std::ctype<char>(get_table()) {} 

    static std::ctype_base::mask const* get_table() 
    { 
     static std::vector<std::ctype_base::mask> 
      rc(std::ctype<char>::table_size,std::ctype_base::space); 

     std::fill(&rc['0'], &rc[':'], std::ctype_base::digit); 
     return &rc[0]; 
    } 
}; 

std::fstream myFile("foo.txt"); 
myfile.imbue(std::locale(std::locale(), new numeric_only())); 

Następnie podczas odczytu pliku, będzie to przeliczenia wszystkich cyfr do pomieszczeń, pozostawiając Ci tylko numery. Następnie możesz po prostu użyć zwykłych konwersji, aby przekształcić to, co jest czytane w int.

std::vector<int> intFromFile; 
std::istream_iterator<int> myFileIter(myFile); 
std::istream_iterator<int> eos; 
std::copy(myFileIter, eos, std::back_inserter(intFromFile)); 

odpowiedź do poniższych uwag:

Oto co zrobiłem, aby zmusić go do pracy

int main(int args, char** argv){ 
    std::fstream blah; 
    blah.open("foo.txt", std::fstream::in); 
    if(!blah.is_open()){ 
     std::cout << "no file"; 
     return 0; 
    } 
    blah.imbue(std::locale(std::locale(), new numeric_only())); 

    std::vector<int> intFromFile; 
    std::istream_iterator<int> myFileIter(blah); 
    std::istream_iterator<int> eos; 
    std::copy(myFileIter, eos, std::back_inserter(intFromFile)); 

    return 0; 
} 

I umieścić tylko ints do wektora, nic więcej, nic mniej. Powód, dla którego nie działał wcześniej, był dwojaki:

  1. Wypełniałem do "9", ale nie "9". Zmieniłem wypełnienie na ":"
  2. Liczby większe niż to, co int może zawierać, stanowią problem. Proponuję używać długich.
+0

Próbowałem; ale wydaje się, że nie działa. – Nawaz

+0

@Nawaz ok, daj mi sekundę, aby uruchomić mój kompilator i zobaczyć, gdzie popełniłem błąd. – wheaties

+0

@wheaties: Przy okazji, pomysł jest naprawdę dobry, jeśli sprawisz, że zadziała. Chciałbym zobaczyć, jak to działa. :-) – Nawaz

1
int a,b,c; 

    cin >> a; 
    cin.ignore(100,'-'); 
    cin >> b; 
    cin.ignore(100,':'); 
    cin >> c; 

    cout << "a = "<< a <<endl; 
    cout << "b = "<< b <<endl; 
    cout << "c = "<< c <<endl; 

Wejście:

1 - 2: 3

wyjściowa:

a = 1
b = 2
c = 3

Zobacz siebie tutaj: http://www.ideone.com/DT9KJ

Uwaga: może obsługiwać dodatkowe spacje również. Więc można odczytać nawet to:

 1  -  2  :  3

Podobny temat:

Using ifstream as fscanf

+3

Be * bardzo * ostrożny magicznych liczb w kodzie. Oni * powrócą, aby cię ugryźć. –

+0

@Konrad: mówisz o '100' w' ignore() '? Możesz to zwiększyć do dowolnej dużej liczby, która według Ciebie może zawierać dodatkową liczbę spacji! – Nawaz

+3

możesz, ale nie powinieneś. To naprawdę nic nie zmienia. Powinieneś użyć 'numeric_limits :: max()', jeśli takie istnieją. –

0

Wystarczy,

ifstream file("file.txt"); 
int n1, n2, n3; 
char tmp; 
while (file.good()) { 
    file >> n1 >> tmp >> n2 >> tmp >> n3; 
} 
+0

To nie zdoła wyodrębnić n3, jeśli nie ma na przykład komponentów numerycznych dla n1 lub n2. –

2

polecam zrobić przynajmniej pobieżnych testów poprawności po przeczytaniu tego:

int a, b, c; 
char dash, colon; 

if (not (cin >> a >> dash >> b >> colon >> c) or dash != '-' or colon != ':') 
    Failure. Do something. 
0

Sorry Konrad, ale polecam: nigdy pod groźbą śmierci, nigdy nigdynigdy (czy to wystarczająco jasne? :-) odczytać sformatowane dane z pliku. Po prostu nie rób tego.

Jest tylko jeden prawidłowy sposób wprowadzania danych sformatowanych: przeczytaj fragmenty znaków (zazwyczaj linie, ale możesz także czytać bloki o stałej długości).

Następnie przeanalizuj tekst wejściowy. Nie będziesz przeprowadzać pobieżnego sprawdzania, użyjesz parsera, który gwarantuje wychwycenie dowolnego błędu formatowania i zgłosisz ten błąd w zrozumiały sposób, podejmiesz odpowiednie działania (zakończenie, pomiń linię i kontynuuj, cokolwiek).

Oddzielne wejście (operacja We/Wy) od parsowania.

Ta rada od dziesięcioleci doświadczenia jako programista komercyjny: czytanie sformatowanych danych wejściowych jest przeznaczone dla programów micky mouse proof-of-principal. Nawet jeśli masz wyłączną kontrolę nad tworzeniem pliku, zawsze parsuj i sprawdzaj i raportuj błędy: w końcu, zmiany w materiałach mogą działać dzisiaj, ale nie jutro.

Piszę C++ od dziesięcioleci i nigdy nie czytałem liczby całkowitej.

7

myślę, że ten będzie najszybszy -yet elegant- sposób:

int a, b, c; 
scanf("%d-%d:%d", &a, &b, &c); 
Powiązane problemy