2010-02-02 12 views
14

C++ non è la mia lingua preferita.Serve aiuto di base per analizzare una stringa in C++

Ho un file che contiene questo:

e 225,370 35,75 

voglio separare e, 225, 370, 35 e 75 l'una dall'altra in un char e int, ma sto avendo problemi. Ho provato a fare tutto quello che ho trovato online e nel mio libro C++ e ancora non funziona. Per favore aiuto.

Mi piacerebbe farlo in Java.

+0

Diteci cosa avete. – bmargulies

+0

Grazie ragazzi. C++ è molto frustrante per me a volte quando ho imparato Java prima. –

+2

Anche se a volte può essere frustrante, aiuta a ottenere alcune librerie potenti che non sono sempre raggruppate direttamente come con Java. Immagina quanto sarebbe frustrante Java se tutto ciò che avevi fosse la lingua principale e nessuna libreria. – joshperry

risposta

-1
#include <iostream> 
#include <fstream> 

using namespace std; 

int main() 
{ 
     ifstream f("a.txt"); // check for errors. 

     char ch,dummy; 
     int i1,i2,i3,i4; 

     f>>ch>>i1>>dummy>>i2>>i3>>dummy>>i4; 

     cout<<ch<<endl<<i1<<endl<<i2<<endl<<i3<<endl<<i4<<endl; 

     return 0; 
} 
2

Supponendo che avete letto i dati in uno stringhe ...

  1. strchr è come String.index.
  2. strtol è come Integer.parseInt()

Che altro avete bisogno?

+1

strtok sarebbe più conveniente di strchr –

+0

'strtok' non è thread-safe, però, se questo è un problema. – greyfade

2
#include <fstream> 

/* ... */ 

ifstream file; 
file.open("yourfile.txt"); 
char c, dummy; 
int i[4]; 
file >> c >> i[0] >> dummy >> i[1] >> i[2] >> dummy >> i[3]; 
file.close(); 
+0

Non sono sicuro del comportamento, dato che non sono un programmatore C++, ma sarei sorpreso se questo semplicemente ignorasse le virgole nel file. Lo fa? – danben

+0

@danben: può, ma per impostazione predefinita non lo farà. Anche i programmatori C++ più dedicati non toccano mai le parti della libreria necessarie per far sì che ignori le virgole (devi creare un "faccetto" ctype personalizzato, creare un 'locale' contenente quel' facet', quindi 'imbusta' il flusso con che 'locale'). –

+0

@danden, hai ragione. Ho aggiornato la mia soluzione. –

4

Se si ha il controllo sul formato, sarà (leggermente) più facile da leggere se si eliminano le virgole, e solo in ingresso come

e 225 370 35 75

Con questo formato, il codice di Poita_ per la lettura dei dati funzionerà [modifica: da allora aggiorna il suo codice per leggere e saltare esplicitamente le virgole]. In caso contrario, sarà necessario passare esplicitamente sopra le virgole:

char ingore1, ignore2; 
char ch; 
int i[4]; 

file >> ch >> i[0] >> ignore1 >> i[1] >> i[2] >> ignore2 >> i[3]; 

[Edit: se siete paranoici o davvero bisogno di verificare il tuo ingresso, a questo punto, è possibile verificare che ignore1 e ignore2 contengono le virgole.]

Nella maggior parte dei casi, tuttavia, i dati sono probabilmente correlati, quindi ti consigliamo di leggere un intero linea in un unico struct (o classe):

struct data { 
    char ch; 
    int i[4]; 

    std::istream &operator>>(std::istream &is, data &d) { 
     char ignore1, ignore2; 
     return is >> ch >> i[0] >> ignore1 >> i[1] >> i[2] >> ignore2 >> i[3]; 
    } 
}; 

Dopo aver fatto questo, è possibile leggere un intero oggetto data alla volta:

std::ifstream infile("my data file.txt"); 
data d; 

infile >> d; 

Oppure, se si dispone di un intero file completo di questi, tutti si può leggere in un vettore:

std::vector<data> d; 

std::copy(std::istream_iterator<data>(infile), 
    std::istream_iterator<data>(), 
    std::back_inserter(d)); 
+0

Bello. Di solito sto scherzando con i metodi find e substr di string. – StackedCrooked

3

Se si desidera utilizzare il vecchio runtime C stile

FILE * pf = fopen(filename, "r"); 
char e; 
int a, b, c, d; 
int ii = fscanf(pf, "%c %d,%d %d,%d", &e, &a, &b, &c, &d); 
if (ii < 5) 
    printf("problem in the input file"); 
fclose (pf); 

modifica: aggiunto controllo degli errori in base al commento da dreamlax

+1

Questo è molto pulito. Sebbene, assicurati di controllare che il valore di ritorno di 'fscanf' sia 5 per assicurarsi che tutte le variabili siano state assegnate in modo appropriato. – dreamlax

+1

In queste situazioni credo che fscanf sia superiore ai modi C++. – StackedCrooked

+0

Cosa succede con tutto il drive per markdown su questa risposta? il punteggio attuale è +4 -3, e non un singolo markdown disposto a spiegare il perché. –

2

Uso Aumentare Tokenizer per dividere la stringa. Io parto dal presupposto che solo il primo token è un char, in modo da codice di esempio sarebbe qualcosa di simile:

#include <iostream> 
#include <boost/tokenizer.hpp> 
#include <string> 
#include <vector> 

using namespace std; 

... 

typedef boost::tokenizer<boost::char_separator<char> > tokenizer; 

string teststring("e 225,370 35,75"); 
boost::char_separator<char> separators(", "); 
tokenizer tokens(teststring, separators); 
vector<string> substrings; 
for (tokenizer::iterator iter = tokens.begin(); iter != tokens.end(); ++iter) 
{ 
    substrings.push_back(*iter); 
} 

e, voilà, si dispone di tutte le stringhe in un vettore pulito.Il char si trova in sottostringhe [0] come std :: string, e i seguenti valori int sono in sottostringhe [1] e quelli che seguono, anche come std :: string. Dovrai convertirli in valori interi. Per questo ti suggerisco di guardare stringstream.

+0

Le librerie Boost possono essere trovate qui: http://www.boost.org/users/download/ – Demi

13

Il C++ String Toolkit Library (StrTk) ha la seguente soluzione al vostro problema:

 
int main() 
{ 
    std::string data("e 225,370 35,75"); 
    char c1; 
    int i1,i2,i3,i4; 
    strtk::parse(data,", ",c1,i1,i2,i3,i4); 
    return 0; 
} 

Più esempi si possono trovare Here

Problemi correlati