Problem mit Zeichenketten, brauche Denkanstoß :-)



  • Ich habe ein Programm geschrieben, welches bei jedem Start die aktuelle Uhrzeit + Datum in eine Datei schreibt. Die Datei soll die letzten 10 (oder auch mehr) einträge speichern.

    zu nächst mal der Quelltext

    #include <iostream>
    #include <ctime>
    #include <cstring>
    #include <new>
    #include <fstream>
    #include <cstdlib>
    #include <conio.h>
    
    using namespace std;
    
    class dt
    {
    private:	
    	//date
    	unsigned short int day_of_month;
    	unsigned short int month_of_year;
    	unsigned long int year;
    	unsigned short int day_of_week;
    
    	char d_o_w[3];
    	char m_o_y[4];
    
    	//time
    	unsigned short int hour;
    	unsigned short int minute;
    	unsigned short int second;
    
    	//string
    	char str_time_date[30];
    
    	char temp[5];
    
    	//... from <ctime>
    	time_t sec_1970;
    	struct tm *date;
    
    public:
    	dt();
    
    	char *output(char *);
    };
    
    dt::dt()
    {	
    	time(&sec_1970);
    	date=localtime(&sec_1970);
    
    	//date
    	day_of_month=(*date).tm_mday;
    	month_of_year=(*date).tm_mon+=1;
    	year=(*date).tm_year+=1900;
    	day_of_week=(*date).tm_wday;
    
    	//time
    	hour=(*date).tm_hour;
    	minute=(*date).tm_min;
    	second=(*date).tm_sec;
    
    	//strings
    	switch(day_of_week)
    	{
    	case 0: strcpy(d_o_w,"So"); break;
    	case 1: strcpy(d_o_w,"Mo"); break;
    	case 2: strcpy(d_o_w,"Di"); break;
    	case 3: strcpy(d_o_w,"Mi"); break;
    	case 4: strcpy(d_o_w,"Do"); break;
    	case 5: strcpy(d_o_w,"Fr"); break;
    	case 6: strcpy(d_o_w,"Sa"); break;
    	default:strcpy(d_o_w,"--"); break;
    	}
    
    	switch(month_of_year)
    	{
    	case 1: strcpy(m_o_y,"Jan"); break;
    	case 2: strcpy(m_o_y,"Feb"); break;
    	case 3: strcpy(m_o_y,"Mar"); break;
    	case 4: strcpy(m_o_y,"Apr"); break;
    	case 5: strcpy(m_o_y,"Mai"); break;
    	case 6: strcpy(m_o_y,"Jun"); break;
    	case 7: strcpy(m_o_y,"Jul"); break;
    	case 8: strcpy(m_o_y,"Aug"); break;
    	case 9: strcpy(m_o_y,"Sep"); break;
    	case 10: strcpy(m_o_y,"Okt"); break;
    	case 11: strcpy(m_o_y,"Nov"); break;
    	case 12: strcpy(m_o_y,"Dez"); break;
    	default: strcpy(m_o_y,"+++"); break;
    	}
    
    	strcpy(str_time_date,d_o_w);
    	strcat(str_time_date,", ");
    
    	if(day_of_month<10)
    		strcat(str_time_date,"0");
    
    	strcat(str_time_date,_itoa(day_of_month,temp,10));
    	strcat(str_time_date,". ");
    	strcat(str_time_date,m_o_y);
    	strcat(str_time_date,". ");
    	strcat(str_time_date,_itoa(year,temp,10));
    
    	strcat(str_time_date,", ");
    
    	if(hour<10)
    		strcat(str_time_date,"0");
    	strcat(str_time_date,_itoa(hour,temp,10));
    	strcat(str_time_date,":");
    
    	if(minute<10)
    		strcat(str_time_date,"0");
    	strcat(str_time_date,_itoa(minute,temp,10));
    	strcat(str_time_date,":");
    
    	if(second<10)
    		strcat(str_time_date,"0");
    	strcat(str_time_date,_itoa(second,temp,10));
    
    	str_time_date[27]='\n';
    
    	str_time_date[28]='\0';
    
    }
    
    char *dt::output(char *str)
    {
    	strcpy(str,str_time_date);
    
    	return str_time_date;
    }
    
    int main()
    {
    
    	class dt watch;
    
    	const char root[]="C:\\";
    
    	const char file[]="watch.log";
    	char str_dat[20][30];
    
    	unsigned short int length;
    	unsigned short int i, j, k;
    	unsigned short int max=10; // 0<max<=20
    
    	length=strlen(root)+strlen(file);
    
    	char *path=new char[length];
    
    	strcpy(path,root);
    	strcat(path,file);
    
    	ifstream log_in(path, ios_base::in);
    
    	for(i=0;i<max;i++)
    	{
    		log_in.get(str_dat[i],30,'\0');
    
    	}
    
    	log_in.close();
    
    	for(j=(max-1);j>0;j--)
    	{
    
    		strcpy(str_dat[j],str_dat[j-1]);
    	}
    
    	watch.output(&str_dat[0][0]);
    
    	for(int m=0;m<max;m++)
    	{
    
    		cout<<str_dat[m];
    	}
    
    	ofstream log_out(path,ios_base::out | ios_base::trunc);
    
    	for(k=0;k<max;k++)
    	{
    
    		log_out<<str_dat[k];
    
    	}
    
    	log_out.close();
    
    	getch();
    
    	return 0x1;
    }
    

    Das Problem ist, das nach dem 11. Starten immer noch eine Textzeile drangehangen wird, was eigendölich nicht passieren soll.

    Zufälliger weise ergibt sich, das die letzte Zeile (also die 11.) genau 9 Zeichen lang ist.

    Durch ändern des Wertes von 'max' (soll die maximal gespeicherten Einträge angeben) sieht man, das die Länge von dieser Variable abhängig ist.

    Die Frage ist jetzt nur warum? Und wieso wird eine 11. Zeile geschrieben?

    Wenn man mir die Zeile zeigen würde in der der Fehler liegt würde mir das schon reichen 🙂

    Danke.



  • leider kann ich deinen cde so nicht lesen. der ist viel zu kompliziert.
    ich transformiere ihn also so lange in einfacheren code, bis der fehler
    sich offen zeigt und erschießen läßt.

    für

    switch(day_of_week) 
        { 
        case 0: strcpy(d_o_w,"So"); break; 
        case 1: strcpy(d_o_w,"Mo"); break; 
        case 2: strcpy(d_o_w,"Di"); break; 
        case 3: strcpy(d_o_w,"Mi"); break; 
        case 4: strcpy(d_o_w,"Do"); break; 
        case 5: strcpy(d_o_w,"Fr"); break; 
        case 6: strcpy(d_o_w,"Sa"); break; 
        default:strcpy(d_o_w,"--"); break; 
        }
    

    sollte man ein array nehmen.
    also

    static char* dowArray[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
    strcpy(_o_w,dowArray[day_of_week]);
    

    und kompliziert genug ist die funktion ac, daß man besser ne eigene funktion
    für sie baut.

    char* getDayOfWeekName(int dayOfWeek)
    {
    	static char* names[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
    	return names[dayOfWeek];
    }
    

    das attribut

    char d_o_w[3];
    

    fliegt also raus, weil es nicht mehr benötigt wird.
    ensprechend wird weiter unten geschrieben:

    strcpy(str_time_date,getDayOfWeekName(day_of_week));
    

    das gleiche hat mit der anderen switch-orgie zu geschehen.

    außerdem verwende ich andere namen, nämlich keine unterstriche, stattdessen großbuchstaben im wort als worttrenner. und month_of_year braucht man nicht zu schreiben, denn month reicht völlig.
    und die ausgabe in die datei habe ich auskommentiert, um nicht voe jedem testlauf die
    fehlererzeugende datei neu bauen zu müssen.

    #include <iostream> 
    #include <ctime> 
    #include <cstring> 
    #include <new> 
    #include <fstream> 
    #include <cstdlib> 
    #include <conio.h> 
    
    using namespace std; 
    
    char* getDayOfWeekName(int dayOfWeek)
    {
    	static char* names[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
    	return names[dayOfWeek];
    }
    
    char* getMonthName(int month)
    {
    	static char* names[]={"Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"};
    	return names[month];
    }
    
    class dt 
    { 
    private:    
        //date 
        unsigned short int day_of_month; 
        unsigned short int month_of_year; 
        unsigned long int year; 
        unsigned short int day_of_week; 
    
        //time 
        unsigned short int hour; 
        unsigned short int minute; 
        unsigned short int second; 
    
        //string 
        char str_time_date[30]; 
    
        char temp[5]; 
    
        //... from <ctime> 
        time_t sec_1970; 
        struct tm *date; 
    
    public: 
        dt(); 
    
        char *output(char *); 
    }; 
    
    dt::dt() 
    {    
        time(&sec_1970); 
        date=localtime(&sec_1970); 
    
        //date 
        day_of_month=(*date).tm_mday; 
        month_of_year=(*date).tm_mon+=1; 
        year=(*date).tm_year+=1900; 
        day_of_week=(*date).tm_wday; 
    
        //time 
        hour=(*date).tm_hour; 
        minute=(*date).tm_min; 
        second=(*date).tm_sec; 
    
        //strings 
        strcpy(str_time_date,getDayOfWeekName(day_of_week)); 
        strcat(str_time_date,", "); 
    
        if(day_of_month<10) 
            strcat(str_time_date,"0"); 
    
        strcat(str_time_date,_itoa(day_of_month,temp,10)); 
        strcat(str_time_date,". "); 
        strcat(str_time_date,getMonthName(month_of_year));
        strcat(str_time_date,". "); 
        strcat(str_time_date,_itoa(year,temp,10)); 
    
        strcat(str_time_date,", "); 
    
        if(hour<10) 
            strcat(str_time_date,"0"); 
        strcat(str_time_date,_itoa(hour,temp,10)); 
        strcat(str_time_date,":"); 
    
        if(minute<10) 
            strcat(str_time_date,"0"); 
        strcat(str_time_date,_itoa(minute,temp,10)); 
        strcat(str_time_date,":"); 
    
        if(second<10) 
            strcat(str_time_date,"0"); 
        strcat(str_time_date,_itoa(second,temp,10)); 
    
        str_time_date[27]='\n'; 
    
        str_time_date[28]='\0'; 
    
    } 
    
    char *dt::output(char *str) 
    { 
        strcpy(str,str_time_date); 
    
        return str_time_date; 
    } 
    
    int main() 
    { 
    
        class dt watch; 
    
        const char root[]="d:\\source\\test2\\"; 
    
        const char file[]="watch.log"; 
        char str_dat[20][30]; 
    
        unsigned short int length; 
        unsigned short int i, j; 
        unsigned short int max=10; // 0<max<=20 
    
        length=strlen(root)+strlen(file); 
    
        char *path=new char[length]; 
    
        strcpy(path,root); 
        strcat(path,file); 
    
        ifstream log_in(path, ios_base::in); 
    
        for(i=0;i<max;i++) 
        { 
            log_in.get(str_dat[i],30,'\0'); 
    
        } 
    
        log_in.close(); 
    
        for(j=(max-1);j>0;j--) 
        { 
    
            strcpy(str_dat[j],str_dat[j-1]); 
        } 
    
        watch.output(&str_dat[0][0]); 
    
        for(int m=0;m<max;m++) 
        { 
    
            cout<<str_dat[m]; 
        } 
    
    /*    ofstream log_out(path,ios_base::out | ios_base::trunc); 
    
        for(k=0;k<max;k++) 
        { 
    
            log_out<<str_dat[k]; 
    
        } 
    
        log_out.close(); */
    
        getch(); 
    
        return 0x1; 
    }
    

    und was soll die klasse überhaupt?
    sie berechnet ja einfach nur etwas und fühlt sich an, wie eine funktion.
    dann sollte sie aber auch eine funktion sein!

    nur weit unten mal passiert

    watch.output(&str_dat[0][0]);
    

    da kann man auch schreiben

    watchOutput(&str_dat[0][0]);
    

    es würde sich eh ein jeder, der deine klasse verwenden muss, diese funktion hier schreiben:

    void watchOutput(char* dst)
    {
       dt watch;
       watch.output(dst);
    }
    

    das umbauen zur funktion hat auch weitere vorteile: es gammeln nicht mehr so
    viele attribute in der klasse herum.

    dazu kopiere ich den ganzen konstruktorcode mal in die output-funktion und lösche die
    klasse und mache danach die fehler stück für stück weg.

    #include <iostream> 
    #include <ctime> 
    #include <cstring> 
    #include <new> 
    #include <fstream> 
    #include <cstdlib> 
    #include <conio.h> 
    
    using namespace std; 
    
    char* getDayOfWeekName(int dayOfWeek)
    {
    	static char* names[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
    	return names[dayOfWeek];
    }
    
    char* getMonthName(int month)
    {
    	static char* names[]={"Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"};
    	return names[month];
    }
    
    void watchOutput(char *str) 
    { 
        time(&sec_1970); 
        date=localtime(&sec_1970); 
    
        //date 
        day_of_month=(*date).tm_mday; 
        month_of_year=(*date).tm_mon+=1; 
        year=(*date).tm_year+=1900; 
        day_of_week=(*date).tm_wday; 
    
        //time 
        hour=(*date).tm_hour; 
        minute=(*date).tm_min; 
        second=(*date).tm_sec; 
    
        //strings 
        strcpy(str_time_date,getDayOfWeekName(day_of_week)); 
        strcat(str_time_date,", "); 
    
        if(day_of_month<10) 
            strcat(str_time_date,"0"); 
    
        strcat(str_time_date,_itoa(day_of_month,temp,10)); 
        strcat(str_time_date,". "); 
        strcat(str_time_date,getMonthName(month_of_year));
        strcat(str_time_date,". "); 
        strcat(str_time_date,_itoa(year,temp,10)); 
    
        strcat(str_time_date,", "); 
    
        if(hour<10) 
            strcat(str_time_date,"0"); 
        strcat(str_time_date,_itoa(hour,temp,10)); 
        strcat(str_time_date,":"); 
    
        if(minute<10) 
            strcat(str_time_date,"0"); 
        strcat(str_time_date,_itoa(minute,temp,10)); 
        strcat(str_time_date,":"); 
    
        if(second<10) 
            strcat(str_time_date,"0"); 
        strcat(str_time_date,_itoa(second,temp,10)); 
    
        str_time_date[27]='\n'; 
    
        str_time_date[28]='\0'; 
    
        strcpy(str,str_time_date); 
    } 
    
    int main() 
    { 
    
        class dt watch; 
    
        const char root[]="d:\\source\\test2\\"; 
    
        const char file[]="watch.log"; 
        char str_dat[20][30]; 
    
        unsigned short int length; 
        unsigned short int i, j; 
        unsigned short int max=10; // 0<max<=20 
    
        length=strlen(root)+strlen(file); 
    
        char *path=new char[length]; 
    
        strcpy(path,root); 
        strcat(path,file); 
    
        ifstream log_in(path, ios_base::in); 
    
        for(i=0;i<max;i++) 
        { 
            log_in.get(str_dat[i],30,'\0'); 
    
        } 
    
        log_in.close(); 
    
        for(j=(max-1);j>0;j--) 
        { 
    
            strcpy(str_dat[j],str_dat[j-1]); 
        } 
    
        watch.output(&str_dat[0][0]); 
    
        for(int m=0;m<max;m++) 
        { 
    
            cout<<str_dat[m]; 
        } 
    
    /*    ofstream log_out(path,ios_base::out | ios_base::trunc); 
    
        for(k=0;k<max;k++) 
        { 
    
            log_out<<str_dat[k]; 
    
        } 
    
        log_out.close(); */
    
        getch(); 
    
        return 0x1; 
    }
    

    dabei versuche ich bereits, variablen immer so spät wie möglich anzulegen.
    dadurch hängen keine uninitialisierten variablen herum und besser lesbar wird es auch.

    void watchOutput(char *str) 
    { 
    	time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        //date 
        int day=(*date).tm_mday; 
        int month=(*date).tm_mon+1; 
        int year=(*date).tm_year+1900; 
        int dayOfWeek=(*date).tm_wday; 
    
        //time 
        int hour=(*date).tm_hour; 
        int minute=(*date).tm_min; 
        int second=(*date).tm_sec;
    

    und nutzloses unsigned short habe ich weggelassen.
    statt (*a).b kann man a->b schreiben.

    void watchOutput(char *str) 
    { 
    	time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        //date 
        int day=date->tm_mday; 
        int month=date->tm_mon+1; 
        int year=date->tm_year+1900; 
        int dayOfWeek=date->tm_wday; 
    
        //time 
        int hour=date->tm_hour; 
        int minute=date->tm_min; 
        int second=date->tm_sec;
    

    funktion funktioniert

    #include <iostream> 
    #include <ctime> 
    #include <cstring> 
    #include <new> 
    #include <fstream> 
    #include <cstdlib> 
    #include <conio.h> 
    
    using namespace std; 
    
    char* getDayOfWeekName(int dayOfWeek)
    {
    	static char* names[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
    	return names[dayOfWeek];
    }
    
    char* getMonthName(int month)
    {
    	static char* names[]={"Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"};
    	return names[month];
    }
    
    void watchOutput(char *str) 
    { 
    	time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        //date 
        int day=date->tm_mday; 
        int month=date->tm_mon+1; 
        int year=date->tm_year+1900; 
        int dayOfWeek=date->tm_wday; 
    
        //time 
        int hour=date->tm_hour; 
        int minute=date->tm_min; 
        int second=date->tm_sec; 
    
        //strings 
    	char str_time_date[30];
    	char temp[5];
    	strcpy(str_time_date,getDayOfWeekName(dayOfWeek)); 
        strcat(str_time_date,", "); 
    
        if(day<10) 
            strcat(str_time_date,"0"); 
    
        strcat(str_time_date,_itoa(day,temp,10)); 
        strcat(str_time_date,". "); 
        strcat(str_time_date,getMonthName(month));
        strcat(str_time_date,". "); 
        strcat(str_time_date,_itoa(year,temp,10)); 
    
        strcat(str_time_date,", "); 
    
        if(hour<10) 
            strcat(str_time_date,"0"); 
        strcat(str_time_date,_itoa(hour,temp,10)); 
        strcat(str_time_date,":"); 
    
        if(minute<10) 
            strcat(str_time_date,"0"); 
        strcat(str_time_date,_itoa(minute,temp,10)); 
        strcat(str_time_date,":"); 
    
        if(second<10) 
            strcat(str_time_date,"0"); 
        strcat(str_time_date,_itoa(second,temp,10)); 
    
        str_time_date[27]='\n'; 
    
        str_time_date[28]='\0'; 
    
        strcpy(str,str_time_date); 
    } 
    
    int main() 
    { 
        const char root[]="d:\\source\\test2\\"; 
        const char file[]="watch.log"; 
        char str_dat[20][30]; 
    
        unsigned short int length; 
        unsigned short int i, j; 
        unsigned short int max=10; // 0<max<=20 
    
        length=strlen(root)+strlen(file); 
    
        char *path=new char[length]; 
    
        strcpy(path,root); 
        strcat(path,file); 
    
        ifstream log_in(path, ios_base::in); 
    
        for(i=0;i<max;i++) 
        { 
            log_in.get(str_dat[i],30,'\0'); 
    
        } 
    
        log_in.close(); 
    
        for(j=(max-1);j>0;j--) 
        { 
    
            strcpy(str_dat[j],str_dat[j-1]); 
        } 
    
        watchOutput(&str_dat[0][0]); 
    
        for(int m=0;m<max;m++) 
        { 
    
            cout<<str_dat[m]; 
        } 
    
    /*    ofstream log_out(path,ios_base::out | ios_base::trunc); 
        for(k=0;k<max;k++) 
        { 
    
            log_out<<str_dat[k]; 
    
        } 
        log_out.close(); */
    
        getch(); 
    
        return 0x1; 
    }
    

    und sie bringt sogar noch den gleichen fehler, wie das originalprogramm.
    die übersetzung war also fehlerfrei.

    das mit dem auffüllen der nullen, um zweistellige ausgabe zu machen, wurmt mich.
    zu viel if im code. das muss in ne funktion raus.

    zu diesem zwecke erfinde ich zuerst mal ne funktion, die mir

    strcat(str_time_date,_itoa(day,temp,10));
    

    abnimmt.
    ich nenne sie mal strcatNumber.

    void strcatNumber(char* dst,int num)
    {
    	char tmp[10];
    	_itoa(num,tmp,10);
    	strcat(dst,tmp); 
    }
    

    und die baue ich erstmal überall ein.

    void watchOutput(char *str) 
    { 
    	time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        //date 
        int day=date->tm_mday; 
        int month=date->tm_mon+1; 
        int year=date->tm_year+1900; 
        int dayOfWeek=date->tm_wday; 
    
        //time 
        int hour=date->tm_hour; 
        int minute=date->tm_min; 
        int second=date->tm_sec; 
    
        //strings 
    	char str_time_date[30];
    	strcpy(str_time_date,getDayOfWeekName(dayOfWeek)); 
        strcat(str_time_date,", "); 
    
        if(day<10) 
            strcat(str_time_date,"0"); 
    
        strcatNumber(str_time_date,day); 
        strcat(str_time_date,". "); 
        strcat(str_time_date,getMonthName(month));
        strcat(str_time_date,". "); 
        strcatNumber(str_time_date,year); 
    
        strcat(str_time_date,", "); 
    
        if(hour<10) 
            strcat(str_time_date,"0"); 
        strcatNumber(str_time_date,hour); 
        strcat(str_time_date,":"); 
    
        if(minute<10) 
            strcat(str_time_date,"0"); 
        strcatNumber(str_time_date,minute); 
        strcat(str_time_date,":"); 
    
        if(second<10) 
            strcat(str_time_date,"0"); 
        strcatNumber(str_time_date,second); 
    
        str_time_date[27]='\n'; 
    
        str_time_date[28]='\0'; 
    
        strcpy(str,str_time_date); 
    }
    

    ok, der fehler ist noch drin.

    und das viele if kann ich wegmachen mit einer funktion, die nen int an nen string
    hängt und dabei für zweistelligkeit sorgt.

    void strcatNumber2(char* dst,int num)
    {
    	if(num<10) 
    		strcat(dst,"0");
    	char tmp[10];
    	_itoa(num,tmp,10);
    	strcat(dst,tmp); 
    }
    

    und

    void watchOutput(char *str) 
    { 
    	time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        //date 
        int day=date->tm_mday; 
        int month=date->tm_mon+1; 
        int year=date->tm_year+1900; 
        int dayOfWeek=date->tm_wday; 
    
        //time 
        int hour=date->tm_hour; 
        int minute=date->tm_min; 
        int second=date->tm_sec; 
    
        //strings 
    	char str_time_date[30];
    	strcpy(str_time_date,getDayOfWeekName(dayOfWeek)); 
        strcat(str_time_date,", "); 
    
        strcatNumber2(str_time_date,day); 
        strcat(str_time_date,". "); 
        strcat(str_time_date,getMonthName(month));
        strcat(str_time_date,". "); 
        strcatNumber(str_time_date,year); 
    
        strcat(str_time_date,", "); 
    
        strcatNumber2(str_time_date,hour); 
        strcat(str_time_date,":"); 
    
        strcatNumber2(str_time_date,minute); 
        strcat(str_time_date,":"); 
    
        strcatNumber2(str_time_date,second); 
    
        str_time_date[27]='\n'; 
    
        str_time_date[28]='\0'; 
    
        strcpy(str,str_time_date); 
    }
    

    ok, jetzt können die ganzen lokalen int-variablen sterben, denn nachdem der code
    nicht mehr so riesig ist, kann man sich leisten, auch mal date->tm_mday statt day
    zu schreiben.

    merke: um code vereinfachen zu können, muß man ihn vorher vereinfachen.

    void watchOutput(char *str) 
    { 
    	time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        //strings 
    	char str_time_date[30];
    	strcpy(str_time_date,getDayOfWeekName(date->tm_wday));
        strcat(str_time_date,", "); 
    
        strcatNumber2(str_time_date,date->tm_mday);
        strcat(str_time_date,". "); 
        strcat(str_time_date,getMonthName(date->tm_mon));
        strcat(str_time_date,". "); 
        strcatNumber(str_time_date,date->tm_year); 
    
        strcat(str_time_date,", "); 
    
        strcatNumber2(str_time_date,date->tm_hour); 
        strcat(str_time_date,":"); 
    
        strcatNumber2(str_time_date,date->tm_min); 
        strcat(str_time_date,":"); 
    
        strcatNumber2(str_time_date,date->tm_sec); 
    
        str_time_date[27]='\n'; 
        str_time_date[28]='\0'; 
    
        strcpy(str,str_time_date); 
    }
    

    anmerkung: würdest du sprintf benutzen, könntest du die ganze funktion
    wohl auf drei oder vier zeilen zusammenfallen lassen. ich schreibe dazu
    den code mal nicht hin, weil ich die konstruktive vorgehensweise mit
    strcat für tragfähiger halte in deinem weiteren lernplan.

    so, der fehler ist immer noch da. aber er legt nicht an dem code von watchOutput,
    denn den kann ich jetzt lesen und kapieren und er hat offensichtlich keine fehler.
    (naja, deine zahlen 27 und 28 hab ich nicht nachgezählt, das glaube ich einfach mal.)

    also mal die main() betrachten.

    erstmal alle variablen so spät wie möglich anlegen:
    //außer den konstanten

    mööp!

    char *path=new char[length];
    

    sieht falsch aus.
    die abschließende 0 fehlt.

    char *path=new char[length+1];
    

    das war aber auch noch nicht der fehler, also weiter...

    (möp) ios_base::in ist nicht notwendig bei nem istream.

    (möööp!) kein close aufrufen, dafür sind destruktoren da.
    aber kannst die stream-variable lokaler machen, damit sie früher stirbt
    (und im destruktor innendrin dann doch close aufruft).

    (möp?) return 0x01?
    das prog lief fehlerfrei, also return 0!

    int main() 
    { 
        const char root[]="d:\\source\\test2\\"; 
        const char file[]="watch.log"; 
        unsigned short int max=10; // 0<max<=20 
    
        int length=strlen(root)+strlen(file); 
        char *path=new char[length+1];
        strcpy(path,root); 
        strcat(path,file); 
    
        char str_dat[20][30]; 
    
    	{
    		ifstream log_in(path);
    		for(int i=0;i<max;i++) 
    		{ 
    			log_in.get(str_dat[i],30,'\0'); 
    		} 
    	}
    
        for(int j=(max-1);j>0;j--) 
        { 
            strcpy(str_dat[j],str_dat[j-1]); 
        } 
        watchOutput(&str_dat[0][0]); 
        for(int m=0;m<max;m++) 
        { 
            cout<<str_dat[m]; 
        } 
    
    /*  {
    		ofstream log_out(path,ios_base::out | ios_base::trunc); 
    		for(int k=0;k<max;k++) 
    		{ 
    			log_out<<str_dat[k]; 
    		} 
    	}*/
    
        getch(); 
    
        return 0; 
    }
    

    natürlich ist der fehler noch da. das ist ja ne komische sache.
    aber ich muss auch zugeben, daß die main() noch viel zu kompliziert ist,
    als daß man sie einfach so angucken könnte und sagen "jo, die stimmt bestimmt".

    ich kommentier mal das verschieben und dranschreiben aus.

    int main() 
    { 
        const char root[]="d:\\source\\test2\\"; 
        const char file[]="watch.log"; 
        unsigned short int max=10; // 0<max<=20 
    
        int length=strlen(root)+strlen(file); 
        char *path=new char[length+1];
        strcpy(path,root); 
        strcat(path,file); 
    
        char str_dat[20][30]; 
    
    	{
    		ifstream log_in(path);
    		for(int i=0;i<max;i++) 
    		{ 
    			str_dat[i][0]='\0';
    			log_in.get(str_dat[i],30,'\0'); 
    		} 
    	}
    
    /*    for(int j=(max-1);j>0;j--) 
        { 
            strcpy(str_dat[j],str_dat[j-1]); 
        } */
    //    watchOutput(&str_dat[0][0]);
    
        for(int m=0;m<max;m++) 
        { 
            cout<<str_dat[m]; 
        } 
    
    /*  {
    		ofstream log_out(path,ios_base::out | ios_base::trunc); 
    		for(int k=0;k<max;k++) 
    		{ 
    			log_out<<str_dat[k]; 
    		} 
    	}*/
    
        getch(); 
    
        return 0; 
    }
    

    ausgabe:

    Di, 31. Aug. 2004, 08:52:36
    Di, 31. Aug. 2004, 08:26:32
    Di, 31. Aug. 2004, 08:14:31
    Di, 31. Aug. 2004, 08:14:31
    Di, 31. Aug. 2004, 08:14:31
    Di, 31. Aug. 2004, 08:14:29
    Di, 31. Aug. 2004, 08:14:20
    Di, 31. Aug. 2004, 08:14:17
    Di, 31. Aug. 2004, 08:11:57
    Di, 31. Aug. 2004, 08:11:54
    

    jo, noch in ordnung.

    jetzt reaktiviere ich das verschieben:

    Di, 31. Aug. 2004, 08:52:36
    DDi, 31. Aug. 2004, 08:52:36
    Di, 31. Aug. 2004, 08:26:32
    Di, 31. Aug. 2004, 08:14:31
    Di, 31. Aug. 2004, 08:14:31
    Di, 31. Aug. 2004, 08:14:31
    Di, 31. Aug. 2004, 08:14:29
    Di, 31. Aug. 2004, 08:14:20
    Di, 31. Aug. 2004, 08:14:17
    Di, 31. Aug. 2004, 08:11:57
    Di, 31. A
    

    nee, da stimmt irgend was nicht.

    ich ändere die ausgabe, damit sie mir ehrlicher sagt, was passiert mit dem
    allseits beliebten trick, was davon und was danach zu schreiben:

    for(int m=0;m<max;m++) 
        { 
            cout<<'>'<<str_dat[m]<<'<'; 
        }
    
    >Di, 31. Aug. 2004, 08:52:36
    D<>Di, 31. Aug. 2004, 08:52:36
    D<>i, 31. Aug. 2004, 08:26:32
    Di<>, 31. Aug. 2004, 08:14:31
    Di,<> 31. Aug. 2004, 08:14:31
    Di, <>31. Aug. 2004, 08:14:31
    Di, 3<>1. Aug. 2004, 08:14:29
    Di, 31<>. Aug. 2004, 08:14:20
    Di, 31.<> Aug. 2004, 08:14:17
    Di, 31. <>Aug. 2004, 08:11:57
    Di, 31. A<
    

    aha! jeder string ist ein eichen zu lang!

    log_in.get(str_dat[i],29,'\0');
    
    >Di, 31. Aug. 2004, 08:52:36
    <>Di, 31. Aug. 2004, 08:52:36
    <>Di, 31. Aug. 2004, 08:26:32
    <>Di, 31. Aug. 2004, 08:14:31
    <>Di, 31. Aug. 2004, 08:14:31
    <>Di, 31. Aug. 2004, 08:14:31
    <>Di, 31. Aug. 2004, 08:14:29
    <>Di, 31. Aug. 2004, 08:14:20
    <>Di, 31. Aug. 2004, 08:14:17
    <>Di, 31. Aug. 2004, 08:11:57
    <
    

    und reaktivieren der ausgabe:

    >Di, 31. Aug. 104, 19:09:12<>Di, 31. Aug. 2004, 08:52:36
    <>Di, 31. Aug. 2004, 08:26:32
    <>Di, 31. Aug. 2004, 08:14:31
    <>Di, 31. Aug. 2004, 08:14:31
    <>Di, 31. Aug. 2004, 08:14:31
    <>Di, 31. Aug. 2004, 08:14:29
    <>Di, 31. Aug. 2004, 08:14:20
    <>Di, 31. Aug. 2004, 08:14:17
    <>Di, 31. Aug. 2004, 08:11:57
    <
    

    öhm. die ausgabe ist nicht voll korrekt.
    da fehlt noch ein zeilenumbruch.

    aber

    str_time_date[27]='\n';
    

    schreibt doch eindeutig nen zeilenumbruch dahin, oder?
    bin ich blind oder was?

    mal die harte tour versuchen:

    watchOutput(&str_dat[0][0]);
    	strcat(&str_dat[0][0],"\n");
    

    jo, korrekte ausgabe. was soll denn das?

    str_time_date[26]='\n'; 
        str_time_date[27]='\0';
    

    oh, das klappt ja! da hat wohl einer wiedermal 1, 2, 3 gezählt, um auf 28 und 29
    zu kommen.
    wir zählen in c++ aber immer bei 0 los. *grins*

    warum hab ich idiot dir auch geglaubt? hätte ich da oben mal nachgezählt, wäre mir
    vieles erspart geblieben.

    das mit 28 und 29 war eh mist.

    sicherer ist allemal statt

    str_time_date[26]='\n'; 
        str_time_date[27]='\0';
    

    ein hübsches

    strcat(str_time_date,"\n");
    

    da kann man dann vel leichter mal später statt ": " ein " : " einfügen
    und am ende stimmt noch alles.

    jetzt habe ich lange zeit ohne speichern getestet. ich lösche mal die watch.log
    und entauskommentiere das speichern und teste.

    es funktioniert nicht!!!
    *heul*

    einer intuition nachgehend mache ich mal

    log_in.get(str_dat[i],28,'\0');
    

    und ich frage mich natürlich nicht, weshalb man 28 statt 29 oder 30 haben sollte.

    ES FUNKTIONIERT!!!!

    der fertige code:

    #include <iostream> 
    #include <ctime> 
    #include <cstring> 
    #include <new> 
    #include <fstream> 
    #include <cstdlib> 
    #include <conio.h> 
    
    using namespace std; 
    
    char* getDayOfWeekName(int dayOfWeek)
    {
    	static char* names[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
    	return names[dayOfWeek];
    }
    
    char* getMonthName(int month)
    {
    	static char* names[]={"Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"};
    	return names[month];
    }
    
    void strcatNumber(char* dst,int num)
    {
    	char tmp[10];
    	_itoa(num,tmp,10);
        strcat(dst,tmp); 
    }
    
    void strcatNumber2(char* dst,int num)
    {
    	if(num<10) 
    		strcat(dst,"0");
    	char tmp[10];
    	_itoa(num,tmp,10);
    	strcat(dst,tmp); 
    }
    
    void watchOutput(char *str) 
    { 
    	time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        //strings 
    	char str_time_date[30];
    	strcpy(str_time_date,getDayOfWeekName(date->tm_wday));
        strcat(str_time_date,", "); 
    
        strcatNumber2(str_time_date,date->tm_mday);
        strcat(str_time_date,". "); 
        strcat(str_time_date,getMonthName(date->tm_mon));
        strcat(str_time_date,". "); 
        strcatNumber(str_time_date,date->tm_year); 
    
        strcat(str_time_date,", "); 
    
        strcatNumber2(str_time_date,date->tm_hour); 
        strcat(str_time_date,":"); 
    
        strcatNumber2(str_time_date,date->tm_min); 
        strcat(str_time_date,":"); 
    
        strcatNumber2(str_time_date,date->tm_sec); 
    
    	strcat(str_time_date,"\n");
    
        strcpy(str,str_time_date); 
    } 
    
    int main() 
    { 
        const char root[]="d:\\source\\test2\\"; 
        const char file[]="watch.log"; 
        unsigned short int max=10; // 0<max<=20 
    
        int length=strlen(root)+strlen(file); 
        char *path=new char[length+1];
        strcpy(path,root); 
        strcat(path,file); 
    
        char str_dat[20][30]; 
    
    	{
    		ifstream log_in(path);
    		for(int i=0;i<max;i++) 
    		{ 
    			str_dat[i][0]='\0';
    			log_in.get(str_dat[i],28,'\0'); 
    		} 
    	}
    
        for(int j=(max-1);j>0;j--) 
        { 
            strcpy(str_dat[j],str_dat[j-1]); 
        }
        watchOutput(&str_dat[0][0]);
    
        for(int m=0;m<max;m++) 
        { 
            cout<<str_dat[m]; 
        } 
    
    	{
    		ofstream log_out(path,ios_base::out | ios_base::trunc); 
    		for(int k=0;k<max;k++) 
    		{ 
    			log_out<<str_dat[k]; 
    		} 
    	}
    
        getch(); 
    
        return 0; 
    }
    

    es sei angemerkt, daß der code trotzdem kacke ist. es darf einfach nicht sein, daß man
    so lange nach einem fehler suchen muss.

    ps: dieser thread verdient es, daß mal einer, der hübsches c++ kann, ein programm
    baut, das mit <string> und <sstream> und getline() arbeitet und das gleiche macht.

    edit: ich fürchte, dieser thread wirft meinen c++-kurs wiedermal ein halbes jahr zurück.
    ein jeder sagt "programmieren lernt man nur auf die harte tour (durch praxis, durch
    tagelange fehlersuche)". ich würde das auch eigentlich als quatsch abtun, wenn ich nicht
    hume und jester kennen würde. beide außergewöhnlich gründlich denkend und gut informiert, aber ich fürchte, sie codieren nicht flüssig, und es gehört zu meinen wichtigsten
    rätseln, warum die summe aller teile nicht das ganze ergibt. wie kann ich c++ so lehren,
    daß jemand, der aus meiner schule geht, die ganzen anderen platt machen kann?



  • Hi!

    Ich war mal so frei und habe Strings und Streams eingebaut. Der Code funktioniert, habe ihn getestet:

    #include <iostream>
    #include <ctime>
    #include <cstring>
    #include <string>
    #include <sstream>
    #include <new>
    #include <fstream>
    #include <cstdlib>
    #include <conio.h>
    
    using namespace std;
    
    string getDayOfWeekName(int dayOfWeek)
    {
        static string names[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
        return names[dayOfWeek];
    }
    
    string getMonthName(int month)
    {
        static string names[]={"Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"};
        return names[month];
    }
    
    string strcatNumber(int num)
    {
    	ostringstream out;
    	out << num;
    	return out.str();    
    }
    
    string strcatNumber2(int num)
    {
    	ostringstream out;
        if(num<10)
           out << "0";
        out << num;
    	return out.str();   
    }
    
    string watchOutput()
    {
        time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        //strings
        string str_time_date;
        str_time_date+=getDayOfWeekName(date->tm_wday);
        str_time_date+=", ";
    
        str_time_date+=strcatNumber2(date->tm_mday);
        str_time_date+=".";
        str_time_date+=getMonthName(date->tm_mon);
        str_time_date+=".";
        str_time_date+=strcatNumber(date->tm_year);
    
        str_time_date+=", ";
    
        str_time_date+=strcatNumber2(date->tm_hour);
    	str_time_date+=":";
    
        str_time_date+=strcatNumber2(date->tm_min);
        str_time_date+=":";
    
        str_time_date+=strcatNumber2(date->tm_sec);
    
        str_time_date+="\n";
    
        return str_time_date;
    }
    
    int main()
    {
        const char root[]="d:\\source\\test2\\";
        const char file[]="watch.log";
        unsigned short int max=10; // 0<max<=20
    
        size_t length=strlen(root)+strlen(file);
        string path(root);
    	path += file;
    
        string str_dat[20];
    
    	ifstream log_in(path.c_str());
        for(int i=0;i<max;++i)
        {
            getline(log_in, str_dat[i]);
        }
    
        for(int j=(max-1);j>0;--j)
        {
            str_dat[j]=str_dat[j-1];
        }
        str_dat[0] = watchOutput();
    
        for(int m=0;m<max;++m)
        {
            cout<<str_dat[m];
        }
    
    	ofstream log_out(path.c_str(), ios_base::out | ios_base::trunc);
        for(int k=0;k<max;++k)
        {
    		log_out<<str_dat[k];
        }
    
        getch();
    
        return 0;
    }
    

    Code-Hacker



  • Code-Hacker schrieb:

    Ich war mal so frei und habe Strings und Streams eingebaut.

    danke. der code sieht schon sehr lecker aus.
    mir schwant, wenn man in watchOutput auch mit << die sachen zusammenhängen würde, käme noch was tolleres (und performanteres, aber das ist eh eine folge von einfach und toll) heruas.

    ich bitte um weitere verbesserungen, und seien sie noch so klein. lasst und den perfekten code finden.



  • Hi!

    Habe die Methode strcatNumber entfernt (wurde nur 1x aufgerufen), habe strcatNumber2 zu lower10 umbenannt, da hier nur die Zahl auf kleiner 10 geprüft wirde, damit gegebenenfalls eine 0 davor geschrieben wird. Habe unnötige Header entfernt und das getch am Ende wodurch conio.h rausgeflogen ist.
    Außerdem habe ich wachtOutput ein wenig gekürzt, so das hinter jedem Datumswert das Zeichen mit angefügt wird. Sollte es ein wenig übersichtlicher machen. Die Längenermittlung in main am Anfang war auch überflüssig und habe ich ebenfalls entfernt:

    #include <iostream>
    #include <ctime>
    #include <string>
    #include <sstream>
    #include <fstream>
    
    using namespace std;
    
    string getDayOfWeekName(int dayOfWeek)
    {
        static string names[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
        return names[dayOfWeek];
    }
    
    string getMonthName(int month)
    {
        static string names[]={"Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"};
        return names[month];
    }
    
    string lower10(int num)
    {
        ostringstream out;
    	if(num<10) 
    		out << "0";
        out << num;
        return out.str();  
    }
    
    string watchOutput()
    {
        time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        //strings
        ostringstream str_time_date;
        str_time_date << getDayOfWeekName(date->tm_wday) << ", ";
    
        str_time_date << lower10(date->tm_mday) << ".";
        str_time_date << getMonthName(date->tm_mon) << ".";
        str_time_date << date->tm_year << ", ";
    
        str_time_date << lower10(date->tm_hour) << ":";
        str_time_date << lower10(date->tm_min) << ":";
        str_time_date << lower10(date->tm_sec) << "\n";
    
        return str_time_date.str();
    }
    
    int main()
    {
        const char root[]="d:\\source\\test2\\";
        const char file[]="watch.log";
        unsigned short int max=10; // 0<max<=20
    
        string path(root);
        path += file;
    
        string str_dat[20];
    
        ifstream log_in(path.c_str());
        for(int i=0; i<max && !log_in.eof(); ++i) {
            getline(log_in, str_dat[i]);
        }
    
        for(int j=(max-1);j>0;--j)
            str_dat[j]=str_dat[j-1];
    
        str_dat[0] = watchOutput();
    
        for(int m=0;m<max;++m)
            cout<<str_dat[m];
    
        ofstream log_out(path, ios_base::out|ios_base::trunc);
        for(int k=0;k<max;++k)
            log_out<<str_dat[k];
    
        return 0;
    }
    

    Ich bin der Meinung das man bei Jahr 1900 aufaddieren sollte. Wir leben schließlich nicht im Jahr 104. 🙂

    Code-Hacker



  • du machst mich glücklich.
    irgendwas an

    for(int i=0;i<max;++i) { 
            if(log_int.eof()) break; // Falls Datei am Ende, dann lesen abbrechen 
            getline(log_in, str_dat[i]); 
        }
    

    kotzt mich noch an. aber ich fürchte, man kann es nicht toll verbessern.
    lob an dich, daß du zum einigen kotz-code kommentiert hast.
    (den kommentar unten ignoriere ich mal, denn wie beide wissen, daß die
    file-objekte kürzer leben sollten.)

    hast du zufällig mit meinem c++-kurs angefangen? dann würde ich dich als referenz aufführen.

    noch ein paar ganz unbedeutende tips:

    char const* getDayOfWeekName(int dayOfWeek)
    {
        static string names[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
        return names[dayOfWeek];
    }
    

    ist ja genausosicher, und hier müssen wir die performance ja nicht wegwerfen.
    (std::string ist nicht geeignet für solche spielereien, man könnte leicht für diesen zweck eine sorte string basteln, die genau hier performanter als std::string und performanter als char* ist).

    die änderung in lower10 finde ich sehr gut. mein name war zum kotzen. deiner sagt viel deutlicher, was da los ist.

    besonders schön gefällt mir die zeile

    str_dat[0] = watchOutput();
    

    irgendwie habe ich das gefühl, da kann viel weniger schief gehen, als bei

    watch.output(&str_dat[0][0]);
    

    das addieren von 1900 hatte ich irgendwwie vergessen, im original war es mit

    year=(*date).tm_year+=1900;
    

    dabei.

    es sei gesagt, daß man mit obigem code (viel ::new in string::string(...) relativ langsam ist.
    es sei gesagt, daß man mit oberstem code (mit viel ::strcat) relativ langsam ist.
    es sei gesagt, daß man mit obigem code kaum noch fehler machen kann.
    es sei gesagt, daß man optimale performance erreicht, wenn man den strcpy-code leicht pervertiert zu

    //alt
        str_time_date << lower10(date->tm_mday) << ".";
    
    //neu
        writepos=lower10(writepos,date->tm_mday);
        *writepos++='.';
    

    nebst einer lower10, die den zeiger auf die position gibt, wo die terminierende 0 sein sollte (aber von writepos noch nicht gesetzt wurde).

    übrigens sollten strcat und strcpy auch den zeiger auf das ende zurückgeben, damit man damit weiterarbeiten kann. den anfang hat man eh. wir verbuchen das verhalten mal als designfehler. nicht nur die stl hat fehler, man hat in der tat früher damit angefangen (mein beitrag zum entmystifizieren der stl im august 04).

    coole klassen vorausgesetzt, macht man in der tat char* und std::string in dieser anwendung platt. zu nullkosten auf beiden seiten, null performanceverlust gegen char* in der endzeugerzurücggebeversion und null sicherheitsverlust gegen std::string was die anfügungen und so angeht.
    (leider braucht manb ein paar wochen dafür, was mich wieder sehr traurig macht.)



  • Hi!

    Ich versteh eines nicht. Die Datei wird gelsen. Danach wird die 1. Zeile überschrieben indem alle Elemente nach hinten kopiert werden. Diese wird später überschrieben. Wenn man dann aber schreibt würde die letzte Zeile doppelt geschrieben werden. Deswegen würde ich die Schleife entfernen und das Datum und Uhrzeit einfach nur an den Anfang schreiben. Habe mir mal erlaubt mit dem copy-Alogrithmus die Datei zu beschreiben und vorher die Datei auf dem Bildschirm auszugeben. Außerdem habe ich das String-Array durch einen Vektor erstzt. Der Rest ist kommentiert:

    #include <iostream>
    #include <ctime>
    #include <string>
    #include <sstream>
    #include <fstream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    string getDayOfWeekName(int dayOfWeek)
    {
        static string names[]={"So","Mo","Di","Mi","Do","Fr","Sa"};
        return names[dayOfWeek];
    }
    
    string getMonthName(int month)
    {
        static string names[]={"Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"};
        return names[month];
    }
    
    string lower10(int num)
    {
        ostringstream out;
        if(num<10) out << "0";
        out << num;
        return out.str();  
    }
    
    string watchOutput()
    {
        time_t sec_1970=time(0);
        struct tm* date=localtime(&sec_1970);
    
        ostringstream str_time_date;
        str_time_date << getDayOfWeekName(date->tm_wday) << ", ";
    
        str_time_date << lower10(date->tm_mday) << ".";
        str_time_date << getMonthName(date->tm_mon) << ".";
        str_time_date << (date->tm_year+1900) << ", ";
    
        str_time_date << lower10(date->tm_hour) << ":";
        str_time_date << lower10(date->tm_min) << ":";
        str_time_date << lower10(date->tm_sec) << "\n";
    
        return str_time_date.str();
    }
    
    int main()
    {
        string path("c:\\source\\test2\\watch.log"); // root und file zu filepath zusammengefasst und direkt in String geschrieben
        const unsigned short int MAX=10; // 0<max<=20; Kontant gemacht
        vector<string> str_dat(MAX, ""); // 20 durch MAX ersetzt; es sind nicht mehr Elemente nötig als benötigt
    
       {
        ifstream log_in(path.c_str());
    	for(int i=0; i<MAX && !log_in.eof(); ++i) { // Lesen beenden, wenn Datei i>=max oder log_in zu Ende gelesen ist
    		string tmp;
            getline(log_in, tmp);
    		str_dat.push_back(tmp);
    	}
        }
    
        str_dat[0] = watchOutput();
    	copy(str_dat.begin(), str_dat.end(), ostream_iterator<string>(cout)); 
    
    	ofstream log_out(path.c_str(), ios_base::out|ios_base::trunc);
    	copy(str_dat.begin(), str_dat.end(), ostream_iterator<string>(log_out, "\n"));   
    
        return 0;
    }
    

    Code-Hacker



  • Hi!

    Nein, ich kannte deinen Kurs damals noch nicht, als ich mit C++ begonnen habe.
    Ich guck aber zwischendurch in deinen Kurs rein, zumal ich auf das neue gespannt bin, wo ich die ersten Kapitel auch bereits gelesen habe. Beim alten habe ich das gelesen wo mir noch etwas das Verständis fehlte und es durch mehr lesen und beispiele aufbessern wollte. Momentan lese ich "Die C++ Programmiersprache".

    Darfst mich aber trotzdem als Refernez aufführen 😃

    Code-Hacker



  • copy(str_dat.begin(), str_dat.end(), ostream_iterator<string>(cout));
    

    meldet beim mingw studio: ostream_iterator undeclared.



  • habe mal <iterator> inkludiert, ohne das klappts bei mir nicht.

    und ofstream log_out(path.c_str(), ios_base::out|ios_base::trunc);
    

    verbessert zu

    und ofstream log_out(path.c_str());
    

    außerdem repariert, indem ich

    str_time_date << lower10(date->tm_sec) << "\n";
    

    zu

    str_time_date << lower10(date->tm_sec);
    

    machte.

    Deswegen würde ich die Schleife entfernen und das Datum und Uhrzeit einfach nur an den Anfang schreiben.

    ach, deswegen klaptt es nicht mehr.
    nee, das war schon irgendwie nötig, damit man die letzten 10 einträge hat.

    meine erste idee war es, eine std::queue zu nehmen, weil die ja dazu da ist, schnell
    vorne was reinschieben zu können.

    aber eigentlich doof, weil ja gar keiner sagt, daßman das erste element erst nach dem
    lesen der datei reinschieben darf.

    das testen auf eof muß eigentlich direkt nach getline erfolgen, damit kein string gepuht
    wird, der nicht gelesen werden konnte.

    path wollte natürlich const werden.

    und MAX ist kein unsigned short.

    das zusammenfassen habe ich wieder andeutungsweise aufgebrochen, denn
    irgendwarum hat berd das ja gemacht.

    habe im block wieder eingerückt. und bei der ausgabe nen ähnlichen block gemacht.

    habe oben doch const char* zurückgegeben.

    habe const besser plaziert, weil man sonst sowas dickes wie static char const* names[]
    nicht mehr lesen kann.

    habe lower10 weggemacht, weil es mit setw ja auch einigermaßen angenehmn geht.

    #include <iostream> 
    #include <iomanip>
    #include <iterator>
    #include <ctime> 
    #include <string> 
    #include <sstream> 
    #include <fstream> 
    #include <vector> 
    #include <algorithm> 
    
    using namespace std; 
    
    char const* getDayOfWeekName(int dayOfWeek) 
    { 
        static char const* names[]={"So","Mo","Di","Mi","Do","Fr","Sa"}; 
        return names[dayOfWeek]; 
    } 
    
    char const* getMonthName(int month) 
    { 
        static char const* names[]={"Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"}; 
        return names[month]; 
    } 
    
    string watchOutput() 
    { 
        time_t sec_1970=time(0); 
        struct tm* date=localtime(&sec_1970); 
    
        ostringstream str_time_date; 
    
    	str_time_date << setfill('0');
    
        str_time_date << getDayOfWeekName(date->tm_wday) << ", "; 
        str_time_date << setw(2) << date->tm_mday << "."; 
        str_time_date << getMonthName(date->tm_mon) << "."; 
        str_time_date << (date->tm_year+1900) << ", "; 
    
        str_time_date << setw(2) << date->tm_hour << ":"; 
        str_time_date << setw(2) << date->tm_min << ":"; 
        str_time_date << setw(2) << date->tm_sec; 
    
        return str_time_date.str(); 
    } 
    
    int main() 
    { 
        string const path("d:\\source\\test2\\" "watch.log"); // root und file
        size_t const MAX=10; // 0<max<=20;
        vector<string> str_dat;
    
        str_dat.push_back(watchOutput()); 
    
    	{ 
    		ifstream log_in(path.c_str()); 
    		string line;
    		while(str_dat.size()<MAX && getline(log_in, line))
    			str_dat.push_back(line);
    	}
    
        copy(str_dat.begin(), str_dat.end(), ostream_iterator<string>(cout,"\n")); 
    
    	{
    		ofstream log_out(path.c_str()); 
    		copy(str_dat.begin(), str_dat.end(), ostream_iterator<string>(log_out, "\n"));   
    	}
    
        return 0; 
    }
    


  • Danke erst mal für die große Mühe (so einen Aufwand hätte ich nicht erwartet)

    Erst mal habe ich die Vorteile von Strings entdeckt (in meinem C++ Buch wurde sie gar nicht erwähnt), ich habe den Quelltext nun umgeschrieben, die Klasse ist aber geblieben, weil ich sie weiterverwenden will (vielleicht wird sie noch ausgebaut).

    Das Programm arbeitet jetzt ohne Konsole, da man den Programmaufruf nicht merken soll.

    #include <ctime>
    #include <fstream>
    #include <sstream>
    
    using namespace std;
    
    class dt
    {
    private:	
    	//date
    	unsigned short int day_of_month;
    	unsigned short int month_of_year;
    	unsigned long int year;
    	unsigned short int day_of_week;
    
    	char d_o_w[3];
    	char m_o_y[4];
    
    	//time
    	unsigned short int hour;
    	unsigned short int minute;
    	unsigned short int second;
    
    	//string
    	string str_time_date;
    
    	char temp[5];
    
    	//... from <ctime>
    	time_t sec_1970;
    	struct tm *date;
    
    public:
    	dt();
    
    	string output(string *);
    };
    
    dt::dt()
    {	
    	time(&sec_1970);
    	date=localtime(&sec_1970);
    
    	//date
    	day_of_month=(*date).tm_mday;
    	month_of_year=(*date).tm_mon+=1;
    	year=(*date).tm_year+=1900;
    	day_of_week=(*date).tm_wday;
    
    	//time
    	hour=(*date).tm_hour;
    	minute=(*date).tm_min;
    	second=(*date).tm_sec;
    
    	//strings
    	switch(day_of_week)
    	{
    	case 0: strcpy(d_o_w,"So"); break;
    	case 1: strcpy(d_o_w,"Mo"); break;
    	case 2: strcpy(d_o_w,"Di"); break;
    	case 3: strcpy(d_o_w,"Mi"); break;
    	case 4: strcpy(d_o_w,"Do"); break;
    	case 5: strcpy(d_o_w,"Fr"); break;
    	case 6: strcpy(d_o_w,"Sa"); break;
    	default:strcpy(d_o_w,"--"); break;
    	}
    
    	switch(month_of_year)
    	{
    	case 1: strcpy(m_o_y,"Jan"); break;
    	case 2: strcpy(m_o_y,"Feb"); break;
    	case 3: strcpy(m_o_y,"Mar"); break;
    	case 4: strcpy(m_o_y,"Apr"); break;
    	case 5: strcpy(m_o_y,"Mai"); break;
    	case 6: strcpy(m_o_y,"Jun"); break;
    	case 7: strcpy(m_o_y,"Jul"); break;
    	case 8: strcpy(m_o_y,"Aug"); break;
    	case 9: strcpy(m_o_y,"Sep"); break;
    	case 10: strcpy(m_o_y,"Okt"); break;
    	case 11: strcpy(m_o_y,"Nov"); break;
    	case 12: strcpy(m_o_y,"Dez"); break;
    	default: strcpy(m_o_y,"+++"); break;
    	}
    
    	str_time_date=d_o_w;
    	str_time_date+=", ";
    
    	if(day_of_month<10)
    		str_time_date+="0";
    
    	str_time_date+=_itoa(day_of_month,temp,10);
    	str_time_date+=". ";
    	str_time_date+=m_o_y;
    	str_time_date+=". ";
    	str_time_date+=_itoa(year,temp,10);
    
    	str_time_date+=", ";
    
    	if(hour<10)
    		str_time_date+="0";
    
    	str_time_date+=_itoa(hour,temp,10);
    	str_time_date+=":";
    
    	if(minute<10)
    		str_time_date+="0";
    
    	str_time_date+=_itoa(minute,temp,10);
    	str_time_date+=":";
    
    	if(second<10)
    		str_time_date+="0";
    
    	str_time_date+=_itoa(second,temp,10);
    }
    
    string dt::output(string *str)
    {
    	*str=str_time_date;
    
    	return str_time_date;
    }
    
    int main()
    {
    	class dt watch;
    
    	const char root[]="C:\\";
    	const char file[]="watch.log";
    
    	const unsigned short int max=20; // 0<max<=20
    	string str_dat[20];
    
    	unsigned short int length;
    	unsigned short int i, j, k;
    
    	/*
    		Für Visual C++ folgende Linkeroptionen einfügen:
    
    		/entry:"mainCRTStartup" /subsystem:windows
    	*/
    
    	length=strlen(root)+strlen(file);
    
    	char *path=new char[length];
    
    	strcpy(path,root);
    	strcat(path,file);
    
    	//... Datei lesen
    	ifstream log_in(path, ios_base::in);
    
    	if(log_in.good())
    	{
    		for(i=0;i<max;i++)
    		{
    			getline(log_in, str_dat[i]);
    
    			if(str_dat[i]=="end of file")
    				str_dat[i].erase();
    
    			if(log_in.eof())
    				break;
    		}
    
    	}
    	else
    		i=0;
    
    	log_in.close();
    
    	//... Werte tauschem
    	for(j=(max-1);j>0;j--)
    		str_dat[j]=str_dat[j-1];
    
    	//... 0. Element setzen
    	watch.output(&str_dat[0]);
    
    	//.. Datei schreiben
    	ofstream log_out(path,ios_base::out | ios_base::trunc);
    
    	for(k=0;k<max;k++)
    	{
    		log_out<<str_dat[k];
    
    		if(k==(i+1))
    			break;
    
    		log_out<<endl;
    	}
    
    	log_out<<"end of file";
    
    	log_out.close();
    
    	return 0;
    }
    

    Ich habe sogar noch ein paar Verbesserungen eingebaut (es werden keine leeren Zeilen in die Datei geschrieben b.z.w es wird kein enter mehr gepeichert, wenn der string leer ist) und weiterhin wird das Ende der Datei jetzt mit "end of file" gekennzeichnet.

    1. Mir ist aber aufgefallen, das "log_in.getline()" nicht mehr geht? müsste man das mit "str_dat[i].c_str()" nicht beheben können?

    2. Gibt es irgendwo eine hübsche Übersicht über alle stream Klassen, und deren Abhängigkeit von einander? Wenn möglich sogar eine Grafik?

    berd



  • switch(day_of_week)
        {
        case 0: strcpy(d_o_w,"So"); break;
        case 1: strcpy(d_o_w,"Mo"); break;
        case 2: strcpy(d_o_w,"Di"); break;
        case 3: strcpy(d_o_w,"Mi"); break;
        case 4: strcpy(d_o_w,"Do"); break;
        case 5: strcpy(d_o_w,"Fr"); break;
        case 6: strcpy(d_o_w,"Sa"); break;
        default:strcpy(d_o_w,"--"); break;
        }
    
        switch(month_of_year)
        {
        case 1: strcpy(m_o_y,"Jan"); break;
        case 2: strcpy(m_o_y,"Feb"); break;
        case 3: strcpy(m_o_y,"Mar"); break;
        case 4: strcpy(m_o_y,"Apr"); break;
        case 5: strcpy(m_o_y,"Mai"); break;
        case 6: strcpy(m_o_y,"Jun"); break;
        case 7: strcpy(m_o_y,"Jul"); break;
        case 8: strcpy(m_o_y,"Aug"); break;
        case 9: strcpy(m_o_y,"Sep"); break;
        case 10: strcpy(m_o_y,"Okt"); break;
        case 11: strcpy(m_o_y,"Nov"); break;
        case 12: strcpy(m_o_y,"Dez"); break;
        default: strcpy(m_o_y,"+++"); break;
        }
    

    klopf>>wand(ja man muss die richtigen oepratoren nehmen 😃 )
    wir haben hier ne perfekte lösung zu dem wirrwar da oben gepostet, und du nimmst immernoch die switch blöcke 🙄



  • otze schrieb:

    klopf>>wand(ja man muss die richtigen oepratoren nehmen 😃 )
    wir haben hier ne perfekte lösung zu dem wirrwar da oben gepostet, und du nimmst immernoch die switch blöcke 🙄

    Wir müssen berd sofort ausschalten. Mit seinem apokalyptischen Programmierstil, diesem Gekröse des Abseitigen, wird er ghoulische Mutanten heraufbeschwören und sehr, sehr böse Dinge tun.



  • Was ist denn jetzt daran noch unübersichtlich? Man kann doch alles erkennen, und die Klasse und die main() Funktion sind logisch nachvollziehbar.

    Außerdem, was hat das denn mit falschen Operatoren zu tun? Es sind doch alle richtig, und ich gehe mal stark davon aus, das mein Debuger mir das schon berichten wird, wenn ich nen Fehler mache.

    berd


Log in to reply