"?" aus Datei einlesen



  • also ist doch mit == alles perfekt oder nicht?



  • uerderli schrieb:

    [...]
    In meinen C++ Buch steht, dass es mit == geht.

    Wenn es std::string s sind, stimmt das auch ...

    hint: char* sonstwas oder "foobar" sind keine std::string s ...



  • uerderli schrieb:

    also ist doch mit == alles perfekt oder nicht?

    Aber nicht bei Zeigern. Da müsstest du diese zuerst dereferenzieren, und nicht mal das klappt - wenn du folgendes machst:

    *"Hallo Welt!"
    

    ist das Ergebnis 'H'. String-Literale sind nähmlich eigentlich char-Pointer mit Null-Terminatoren.

    "Hal" :
    
    0x65464ea      73   //Oder so ähnlich; ASCII-, bzw. ANSI-Werte
    0x65464eb      97
    0x65464ec      109
    0x65464ed      0
    


  • so hier mal mein Code

    #include "stdafx.h"
    
    #include <iostream>
    #include <fstream>
    #include <string>
    
    #define num 9658
    #define att 27
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	ifstream datei("auf.txt");
    
    	if(!datei)
    	{
    		cerr << "Fehler beim Öffnen";
    		cin.get();
    		return 2;
    	}
    
    	//int* tap;
    	int (*tab)[att] = new int[num][att];
    	char zeile[70];
    	char separator[] = ",";
    	char* token;
    	int z = 0, s = 0;
    	datei.getline(zeile, 70);
    	while( datei.getline(zeile, 70))
    	{
    		s = 0;
    		token = strtok(zeile, separator);        /* erstes Token ermitteln */
    		while( token != NULL )
    		{
    			//if(token != "no" || token != "yes" || token != "?")
    			if(strcmp(token, "no") != 0 || strcmp(token, "yes") != 0 || strcmp(token, "?") != 0)
    			{
    				tab[z][s] = atoi(token);
    				cout << tab[z][s] << " | ";
    			}
    			else
    			{
    				if(token == "no")
    					tab[z][s] = 0;
    				else
    				if(token == "yes")	
    					tab[z][s] = 1;
    				else
    				if(token == "?")
    					tab[z][s] = -42;
    			}
    			token = strtok(NULL, separator);        /* weitere Token ermitteln */
    			++s;
    		}
    		//cout << endl << z << " geschaft" << endl;
    		//cin.sync();
    		//cin.get();
    		++z;
    	}
    
    	cout << "Dateneinfelsen abgeschossen" << endl;
    
    	//double* tab2;
    	double (*tab2)[num] = new double[num][num];  //Distanzmatrix
    
    	double diff;
    	double sum;
    
    	for(int i = 0; i < num -1; ++i)
    	{
    		for(int j = i+1; j < num; ++j)
    		{
    			sum = 0;
    			for(int k = 0; k < att - 1; ++k)  //cancerler nicht
    			{
    				if(tab[i][k] == -42 || tab[j][k] == -42)
    					diff = 0;
    				else
    					diff = tab[i][k] - tab[j][k];
    				sum += diff * diff;
    			}
    			tab2[i][j] = sqrt(sum);
    			//cout << endl << i << " " << j << " " << tab2[i][j] << endl;
    			//cin.sync();
    			//cin.get();
    		}
    	}
    
    	cout << "Distanzen berechnet" << endl;
    
    	double* tab3 = new double[num]; //Mittelwerte der Distanzwerte
    
    	double sum2 = 0;
    
    	for(int i = 0; i < num; ++i)
    	{
    		sum = 0;
    		for(int j = 0; j < num; ++j)
    		{
    			if(i == j)
    				sum += 0;
    			else
    			if(i < j)
    				sum += tab2[i][j];
    			else
    				sum += tab2[j][i];
    		}
    		tab3[i] = sum / (num -1);
    		sum2 += tab3[i];
    		//cout << endl << i << " " << tab3[i] << endl;
    		//cin.sync();
    		//cin.get();
    	}
    
    	double median = sum2 / num;
    
    	cout << "Mittelwerte gebildet" << endl;
    
    	//cout << median;
    	int a = 0;
    
    	ofstream outFile("auf2.txt", ios::app);
    
    	if(!outFile)
    	{
    		cerr << "Fehler beim Öffenen zum Schreiben" << endl;
    		cin.get();
    		return 2;
    	}
    
    	for(int i = 0; i < num; ++i)
    	{
    		if(abs(tab3[i] - median) > 8)
    		{
    			++a;
    			cout << i << endl;
    		}
    		else
    		{
    			for(int j = 0; j < att; ++j)
    			{
    				//if(tab[i][j] < -100)
    					//cout << i << " " << j << endl;
    				if(tab[i][j] == -42)
    					outFile << "?";
    				else
    				if(j == (att - 1) && tab[i][j] == 0)
    					outFile << "no";
    				else
    				if(j == (att - 1) && tab[i][j] == 1)
    					outFile << "yes";
    				else
    					outFile << tab[i][j];
    
    				outFile << ",";
    			}
    			outFile << endl;
    		}
    	}
    
    	cout << endl << a;  //265
    
    	cin.sync();
    	cin.get();
    	return 0;
    }
    

    Warum werden die ? als 0 interpretiert?
    Ist es wegen der Vergleiche mit c-strings oder kann generell ein ? nicht eingelesen werden, weil es ein Sonderzeichen ist



  • Dankeschön, das lesen wir natürlich alles sofort.



  • gibt es die Funktion strtok auch für C++-Strings?



  • uerderli schrieb:

    gibt es die Funktion strtok auch für C++-Strings?

    boost::algorithm::split oder ähnliches...



  • Hacker schrieb:

    Dankeschön, das lesen wir natürlich alles sofort.

    😮 wirklich!? 😃



  • Swordfish schrieb:

    Hacker schrieb:

    Dankeschön, das lesen wir natürlich alles sofort.

    😮 wirklich!? 😃

    Nein! 😃 😃



  • danke für eure Hilfe mit den String-Vergleichen.

    Aber nochmal zu dem ?.
    Trotz korrekter Vergleiche, die das ? immernoch als 0 gelesen.

    Weißt ihr warum?



  • Hacker schrieb:

    Swordfish schrieb:

    Hacker schrieb:

    Dankeschön, das lesen wir natürlich alles sofort.

    😮 wirklich!? 😃

    Nein! 😃 😃

    Aha. Das heißt also, ich sollte mein Codebeispiel, in dem das Problem auftritt, so kurz wie möglich halten, damit ich nicht unnötig mehr Zeit der evtl. hilfsbereiten Leser stehle, als nötig? 😉

    uerderli schrieb:

    Trotz korrekter Vergleiche, die das ? immernoch als 0 gelesen.

    Weißt ihr warum?

    Nein, wir weissen es nicht.



  • uerderli schrieb:

    danke für eure Hilfe mit den String-Vergleichen.

    Aber nochmal zu dem ?.
    Trotz korrekter Vergleiche, die das ? immernoch als 0 gelesen.

    Weißt ihr warum?

    oh Gott, tschuldigung für meine Rechtschreibung 😮



  • Swordfish schrieb:

    Hacker schrieb:

    Swordfish schrieb:

    Hacker schrieb:

    Dankeschön, das lesen wir natürlich alles sofort.

    😮 wirklich!? 😃

    Nein! 😃 😃

    Aha. Das heißt also, ich sollte mein Codebeispiel, in dem das Problem auftritt, so kurz wie möglich halten, damit ich nicht unnötig mehr Zeit der evtl. hilfsbereiten Leser stehle, als nötig? 😉

    Ja. 😉



  • uerderli schrieb:

    Mit
    token = strtok(zeile, separator);
    trenne ich dabei die Werte.

    Das ist keine gute Idee. Lese doch lieber gleich die Zahlen aus der Datei ein und überlese die Kommas dazwischen. Falls Du Beispiele suchst, suche hier im Forum nach 'csv istream' oder in Google nach 'csv Datei lesen istream'.

    Das Einlesen des '?' statt einer Zahl, kann man mit einem sogenannten Manipulator lösen.
    Hier eine Code-Skizze:

    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    
    template< char C >
    std::istream& Char( std::istream& in )
    {
        char c;
        if( in >> c && c != C )
            in.setstate( std::ios_base::failbit );
        return in;
    }
    
    // --   Manipulator, zum Einlesen von Zahlen und einem '?'
    //      wird ein '?' erkannt, so erhält die Zahl den Wert '-42.'
    struct query
    {
        explicit query( double& nr ) : m_number( nr ) {}
        friend std::istream& operator>>( std::istream& in, query q )
        {
            typedef std::istream::traits_type Traits;
            if( in >> std::ws && !in.eof() )
            {
                if( Traits::to_char_type( in.peek() ) == '?' )
                {
                    in.ignore(1); // '?' überlesen
                    q.m_number = -42.;
                }
                else
                    in >> q.m_number;
            }
            return in;
        }
    private:
        double& m_number;
    };
    
    int main()
    {
        using namespace std;
        ifstream datei("datei.txt");
        if(!datei)
        {
            cerr << "Fehler beim Öffnen";
            cin.get();
            return 2;
        }
        for( int zeile = 1; datei; ++zeile )
        {
            cout << zeile << ".Zeile: ";
            double zahl;
            for( int i=0; i<26 && datei >> query( zahl ) >> Char<','>; ++i )
            {
                cout << zahl << "|";
            }
            string yes_no;
            if( datei >> yes_no )
                cout << yes_no;
            cout << endl;
        }
        cin.get();
        return 0;
    }
    

    Gruß
    Werner



  • @Werner
    vielen Dank!

    so funktioniert es perfekt!



  • Blöde Frage, aber wieso funktioniert das?

    for( int i=0; i<26 && datei >> query( zahl ) >> Char<','>; ++i )

    Char ist doch eine Funktion, welcher >>-Operator passt da?



  • if(strcmp(token, "no") != 0 || strcmp(token, "yes") != 0 || strcmp(token, "?") != 0)
    

    Diese Bedingung kann niemals "false" werden. Jeder mögliche String ist entweder ungleich "no" ODER (||) ungleich "yes" ODER (||) ungleich "?".
    Was du suchst ist UND (&&).



  • Ethon schrieb:

    Blöde Frage, aber wieso funktioniert das?

    for( int i=0; i<26 && datei >> query( zahl ) >> Char<','>; ++i )

    Char ist doch eine Funktion, welcher >>-Operator passt da?

    Dieser:

    namespace std
    {
        template <class charT, class traits = char_traits<charT> >
            class basic_istream : virtual public basic_ios<charT,traits> 
        {
        public:
            // Kapitel 27.7.2.2.3 Formatted input: [istream::extractors]
            basic_istream<charT,traits>& operator>>(
                basic_istream<charT,traits>& (*pf)(basic_istream<charT,traits>&) );
            // 1 Effects: None. This extractor does not behave as a formatted input function (as described in 27.7.2.2.1.)
            // 2 Returns: pf(*this).
    
        // ...
        }
    }
    

    Funktioniert genau so wie z.B. std::ws.

    Gruß
    Werner


Anmelden zum Antworten