Frage nach Programmierstil
-
Infernal Hails!
Ich hab' mit 12 Jahren angefangen zu programmieren (MS QBasic) und bin (sprachbedingt) bald an grenzen gestoßen. Hab' nen Freund gefragt, womit er programmiert - er war damals an der HTL Salzburg(Höhere Technische Lehranstalt, für nicht-Österreicher) und hat gemeint 'C' wäre wohl das Mittel der Wahl. Also hab ich ihn gebeten, mir seine Borland C/C++ IDE (Version 3.1) zu kopieren (Das waren damals 14 3,5'' Discs ;)). Voller euphorie installiert und geproggt...
Inzwischen bin ich auch schon in die weiten Welten der WinAPI und zu Visual Basic vorgestoßen und das sogar mit einigem Erfolg - das ganze autodidakt.Ich frag' mich nun, ob mein Programmierstil etwas eigenwillig ist...
Vielleicht findet sich unter euch jemand, der bereit ist, nachfolgende Sources zu kritisieren - wenns auch ein bisschen viel zu lesen ist.vicilog.h [VICI Logical Extensions]
#if !defined(__VICILOG_H) #define __VICILOG_H __VICILOG_H unsigned int CountDigits(long ulNumber) { unsigned int uiDigits = 0; do { ulNumber = ulNumber / 10; uiDigits ++; }while(ulNumber!=0); return uiDigits; } unsigned int DayOfWeek(int iYear, int iMonth, int iDay) { int h[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; iYear -= iMonth < 3; return ((iYear + iYear/4 - iYear/100 + iYear/400 + h[iMonth-1] + iDay) % 7); } #endif
vicimsg.h [VICI Standard Messages]
#if !defined(__VICIMSG_H) #define __VICIMSG_H __VICIMSG_H #define VICI_TERMINATED "Terminated!" #define VICI_INI_TRYTOLOAD "Trying to open initialisation file..." #define VICI_INI_LOADED "Initialisation file loaded." #define VICI_INI_NOT_FOUND "Initialisation file could not be loaded!" #define VICI_INI_LENGTH_INFO "Length of initialisation file: %i Bytes." #endif
vici.cpp [VICI Main Program File]
#include <dos.h> #include <conio.h> #include <stdio.h> #include <alloc.h> #include <string.h> #include <process.h> #include <io.h> #include <fcntl.h> #include "vicilog.h" #include "vicimsg.h" enum INIVALUES{INVALID=0, NAME=2, FULLNAME=3, VERSION=4}; char *DAYOFWEEK[] = {"Sunday", "Monday", "Tuesday", "Wensday", "Thuesday", "Friday", "Saturday"}; typedef int HANDLE; typedef unsigned int UINT; class VICI { private: char *cpName; char *cpFullName; char *cpVersion; public: VICI(); void TellName(void); void TellVersion(void); void TellDateTime(void); void ExplainName(void); void Tell(char *cpWhat); }; void VICI::TellDateTime(void) { date d; time t; getdate(&d); gettime(&t); cprintf("Today it's %s, %02u/%02u/%04u at %02u:%02u:%02u.%02u\r\n", DAYOFWEEK[DayOfWeek(d.da_year, d.da_mon, d.da_day)], d.da_day, d.da_mon, d.da_year, t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund); } void VICI::TellVersion(void) { cprintf("This is version %s!\r\n", VICI::cpVersion); } void VICI::Tell(char *cpWhat) { cprintf("%s\r\n", cpWhat); } void VICI::TellName(void) { cprintf("My name is %s.\r\n", VICI::cpName); } void VICI::ExplainName(void) { cprintf("%s means %s.\r\n", VICI::cpName, VICI::cpFullName); } VICI::VICI() { HANDLE hVICIiniFile; char *cpTemp = NULL; VICI::cpName = NULL; VICI::cpVersion = NULL; VICI::cpFullName = NULL; clrscr(); hVICIiniFile = open("VICI.INI", O_RDWR|O_TEXT); if(hVICIiniFile==-1) { VICI::Tell(VICI_INI_NOT_FOUND); VICI::Tell(VICI_TERMINATED); exit(0); } cpTemp = (char*)malloc((strlen(VICI_INI_LENGTH_INFO) +CountDigits(filelength(hVICIiniFile))-2)*sizeof(char)); sprintf(cpTemp, VICI_INI_LENGTH_INFO, filelength(hVICIiniFile)); VICI::Tell(cpTemp); free(cpTemp); cpTemp = NULL; char cBuffer; char *cpVariable = NULL; char *cpValue = NULL; int iCounter = 0; do { read(hVICIiniFile, &cBuffer, 1); if(cBuffer=='#') { do { read(hVICIiniFile, &cBuffer, 1); } while(!(cBuffer==10||eof(hVICIiniFile))); } else { lseek(hVICIiniFile, -1, SEEK_CUR); iCounter = 0; do { read(hVICIiniFile, &cBuffer, 1); iCounter++; } while(!(cBuffer=='='||eof(hVICIiniFile))); free(cpVariable); cpVariable = NULL; cpVariable = (char*)malloc(iCounter*sizeof(char)); lseek(hVICIiniFile, -iCounter, SEEK_CUR); read(hVICIiniFile, cpVariable, iCounter); cpVariable[iCounter-1] = '\0'; iCounter = 0; do { read(hVICIiniFile, &cBuffer, 1); iCounter++; }while(!(cBuffer==';'||eof(hVICIiniFile))); free(cpValue); cpValue = NULL; cpValue = (char*)malloc(iCounter*sizeof(char)); lseek(hVICIiniFile, -iCounter, SEEK_CUR); read(hVICIiniFile, cpValue, iCounter-1); cpValue[iCounter-1]='\0'; read(hVICIiniFile, &cBuffer, 1); read(hVICIiniFile, &cBuffer, 1); INIVALUES iv = INVALID; if(stricmp(cpVariable, "Name")==0) { iv = NAME; } if(stricmp(cpVariable, "FullName")==0) { iv = FULLNAME; } if(stricmp(cpVariable, "Version")==0) { iv = VERSION; } switch(iv) { case VERSION: VICI::cpVersion = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpVersion, cpValue); break; case NAME: VICI::cpName = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpName, cpValue); break; case FULLNAME: VICI::cpFullName = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpFullName, cpValue); break; case INVALID: cprintf("Unrecognized variable: %s!\r\n", cpVariable); break; } } } while(!eof(hVICIiniFile)); close(hVICIiniFile); VICI::Tell(VICI_INI_LOADED); VICI::TellName(); VICI::TellDateTime(); } void main(void) { VICI v; }
VICI.INI [Vici Initialisation File]
#VIKI.INI #VIKI Initialisation file version=0.9; fullname=Virtual Interactive Creative Intelligence; name=VICI;
kind regards,
SwordfishP.S.
- Compilierbar mit Borland C++ V3.1
- Falls es replies gibt: *thxia*
- Falls ich vom Admin gekillt werde (aufgrund länge des posts): *rip*¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
"I've just downloaded some programs that crashed M$ Windows!!"
"Hm, I got these programs with the operating system - *for free* ;)"
-
Swordfish schrieb:
Vielleicht findet sich unter euch jemand, der bereit ist, nachfolgende Sources zu kritisieren
Auf jeden Fall.
void main(void)
Kommentarlos.
Sachen wie
#if !defined(__VICILOG_H)
kann man kurz
#ifndef __VICILOG_H
schreiben.
In C++ kannst du void als Funktionsargument weglassen, denn ein
void foo(void)
ist exakt das gleiche wie
void foo()
#define VICI_TERMINATED "Terminated!"
Konstanten lieber mit const definieren, es sei denn du hast vor, noch spezielle Aktionen damit zu machen, zB compile-time widen.
char *DAYOFWEEK[] = {"Sunday", "Monday", "Tuesday", "Wensday", "Thuesday", "Friday", "Saturday"};
String-Literale sind read-only, also besser so
const char *DAYOFWEEK[] = {"Sunday", "Monday", "Tuesday", "Wensday", "Thuesday", "Friday", "Saturday"};
typedef int HANDLE; typedef unsigned int UINT;
Komplett grossgeschriebene Nicht-Makro Bezeichner find ich persönlich hässlich, ist aber Geschmackssache.
cpTemp = (char*)malloc(...)
Verwende keine C-Casts in C++, also besser so (auch wenn's länger ist)
cpTemp = reinterpret_cast<char*>(malloc(...))
HANDLE hVICIiniFile; ... hVICIiniFile = open("VICI.INI", O_RDWR|O_TEXT);
Definiere Variablen erst dort, wo du sie brauchst.
HANDLE hVICIiniFile = open("VICI.INI", O_RDWR|O_TEXT);
Ansonsten hast du mehr einen C/C++ Mix als wirklich sauberes C++. Ich will jetzt aber nur über den Programmierstil lästern und nicht den Inhalt.
So, das solls erstmal sein. Vielleicht fallen mir ja noch ein paar Sachen auf.
Aber noch ein guter Rat zum Schluss, gewöhn dir die ungarische Notation ab. Nur in wenigen Fällen ist eine spezielle Markierung von Variablen sinnvoll, zB bei Member-Variablen.
-
Danke groovemaster!
Aber zu deiner Kritik:
ad 1)
Ok, machen wir mal ANSI C draus...
int main(int argc, char *argv[]) [ VICI c; }
Siehe da, ja - er kann es ABER:
- Ich hatte nie vor, Parameter zu prüfen.
- Die DOS-Box von Windows 2003 Server schert sich 'nen Dreck um nen Rückgabewert.
ad 2)
Ok, es geht natürlich auch kürzer, ist aber Geschmackssache.
#ifndef __VICILOG_H #define __VICILOG_H __VICILOG_H ... #endif
ad 3)
Nicht zwingend falsch -> Angewohnheit wie
void main(void)
.
ad 4)
Wie zum teufel soll man...
#define VICI_TERMINATED "Terminated!"
zur compile-time verändern können!?
#define ist eine Präprozessordirektive, die - wenn vom Präprozessor abgearbeitet - nichts anderes macht als einen Textersatz auf Sourceebene.
Verrat mir also: Wie, zum Teufel!?ad 5)
Ok, haste recht:
const char *DAYOFWEEK[] = {"Sunday", "Monday", "Tuesday", "Wensday", "Thuesday", "Friday", "Saturday"};
ad 6)
Wie du schon sagst: Geschmackssache
Für meine Geschmäcker ist es schon grausam auch nur an Makros *würg* zu denkenad 7)
Hast du eine leise Ahnung, was mein lieber bcc (v 3.1 wie oben erwähnt) mit mir macht, wenn ich
cpTemp = reinterpret_cast<char*>(malloc(...))
mache!?
Ich hab's jetzt nicht ausprobiert, aber ich tipp mal scharf auf- Undefined symbol 'reinterpret_cast'
- expression syntax
.
ad
Jup, hast recht
HANDLE hVICIiniFile = open("VICI.INI", O_RDWR|O_TEXT);
is übersichtlicher.
ad 9)
groovemaster schrieb:
Ich will jetzt aber nur über den Programmierstil lästern und nicht den Inhalt.
Hm, was hast du denn 'Inhaltlich' verstanden??
In anderen Worten: Was denkst du sollte das mal werden?ad 10)
Ungarisch gefällt mir persönlich ganz gut... :p
Danke für diese Antwort! Hat mich sehr gefreut.
Aber ich würd' über jede weitere mindestens nochmal so sehr freuen!kind regards
Swordfish
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
"I've just downloaded some programs that crashed M$ Windows!!"
"Hm, I got these programs with the operating system - *for free* ;)"
-
Swordfish schrieb:
Ok, machen wir mal ANSI C draus...
int main(int argc, char *argv[]) [ VICI c; }
Siehe da, ja - er kann es ABER:
- Ich hatte nie vor, Parameter zu prüfen.
- Die DOS-Box von Windows 2003 Server schert sich 'nen Dreck um nen Rückgabewert.
Du musst auch keine Parameter prüfen.
int main(void)
reicht vollkommen aus. Und wenn der Rückgabewert egal ist, dann ist ein
return 0;
üblich. Deinem Programm kann es doch egal sein, was das BS damit macht.
Swordfish schrieb:
ad 3)
Nicht zwingend falsch
Wenn du C programmierst, was ich deinem Code nicht wirklich entnehmen konnte, da du mit Klassen arbeitest, dann vergiss meinen Kommentar zu diesem Punkt. Denn ein
void foo(void)
ist in C tatsächlich etwas anderes als
void foo()
Swordfish schrieb:
Wie zum teufel soll man...
#define VICI_TERMINATED "Terminated!"
zur compile-time verändern können!?
#define ist eine Präprozessordirektive, die - wenn vom Präprozessor abgearbeitet - nichts anderes macht als einen Textersatz auf Sourceebene.
Verrat mir also: Wie, zum Teufel!?Wie ich schon sagte, kannst du zB widen. Bsp
#define WIDEN(x) L##x #define VICI_TERMINATED "Terminated!" #define VICI_TERMINATED_W WIDEN(VICI_TERMINATED)
VICI_TERMINATED_W ist nun ein Wide-String mit dem Inhalt von VICI_TERMINATED.
Definiert man hingegen VICI_TERMINATED als echte Konstanteconst char* VICI_TERMINATED = "Terminated!";
funktioniert das dann nicht mehr.
Swordfish schrieb:
Hast du eine leise Ahnung, was mein lieber bcc (v 3.1 wie oben erwähnt) mit mir macht, wenn ich
cpTemp = reinterpret_cast<char*>(malloc(...))
mache!?
OK, ist schon Ewigkeiten her, dass ich Borland C++ 3.1 verwendet hab. Aber mal nebenbei gefragt, hast du denn keine andere IDE bzw. anderen Compiler. Das ist doch uralt. Und einige aktuelle Sachen gibts auch kostenlos. Mehr dazu findest du oben rechts unter [ Compiler ].
Swordfish schrieb:
Hm, was hast du denn 'Inhaltlich' verstanden??
In anderen Worten: Was denkst du sollte das mal werden?"Inhaltlich verstanden"? Nun, so genau hab ich mir den Code nicht angeschaut. Ich meinte nur, dass für C++ Verhältnisse nicht gerade eine sinnvolle Funktionalität verwendet wird. ZB verwendet man kein malloc und auch manuelles Reservieren von Speicher ist wenig effektiv. Man greift dann eher zu fertigen Containern wie std::vector oder std::string. Aber das sind wie gesagt inhaltliche Fragen und hat mit Programmierstil nichts zu tun.
Swordfish schrieb:
Ungarisch gefällt mir persönlich ganz gut... :p
Zu meiner Schande hab ich diese Notation auch mal verwendet. Vor langer Zeit hab ich mir das aber abgewöhnt und muss sagen, dass mir diesbzgl. nichts fehlt. Im Gegenteil, der Code wird einfacher und lesbarer und man selbst damit effektiver.
-
groovemaster schrieb:
Swordfish schrieb:
Ungarisch gefällt mir persönlich ganz gut... :p
Zu meiner Schande hab ich diese Notation auch mal verwendet. Vor langer Zeit hab ich mir das aber abgewöhnt und muss sagen, dass mir diesbzgl. nichts fehlt. Im Gegenteil, der Code wird einfacher und lesbarer und man selbst damit effektiver.
Könnt ihr mich bitte aufklären: Was meint ihr mit "Ungarisch"?
-
Hmmm
int main(void) ist doch eindeutig overhead, oder... *lol*
Ok, ich hätt nie im Leben daran gedacht an #defines mit Macros runzuspielen... Dann doch besser const
Doch, ich hab auch andere Compiler:
Microsoft .NET Framework Version 1.0.3705
Microsoft Visual C++ .NET 55605-652-0000007-18751
Microsoft Visual C# .NET 55605-652-0000007-18751
Microsoft Visual Basic .NET 55605-652-0000007-18751und auch ne IDE dazu:
Microsoft Development Environment 2002 Version 7.0.9514
DevC++ in einer 4er-Version hab ich glaub ich noch irgendwo rumliegenaber ich denk nicht im Traum daran nen ewig alten Source von BorlandC nach VC oder gar C# zu portieren - wir haben doch keine Zeit!!
Hm. Das ganze sollte damals 'n Shellersatz für meine gehasste Command.com werden. Ich hab aber irgendwann aufgegeben.
@someCoder:
ungarisch nennt man die Notation, in welcher der Variablentyp als Präfix for die Variable gestellt wird. So z.B:
int iEinInt; unsigned int uiEinUnsignedInt; char cCharacter; // oder bByte falls man den Speicherbedarf betonen will aClass cEineKlasse; bool blnEinBoolean (...)
natürlich ist dies nur eine _mögliche_ Auswahl. Es gibt da die unterschiedlichsten 'Dialekte'...
-
hab' auch noch was:
- mach eine leerzeile zwischen zwischen zeilen, die einen zusammenhang bilden, auch zwischen funktionen, structs usw.
- ein paar kommentare wären auch nicht schlecht
- die '{' an's ende einer zeile zu schreiben macht's auch nicht gerade übersichtlicher. lieber in die nächste zeile damit (ist aber auch, wie vieles andere, geschmackssache)
-
Hi!
Es gibt mittlerweile den BCC 5.5 gratis auf der Borland-SeiteInhaltlich:
da du Klassen verwendest, betrachte ich dein Programm als C++ Programm. Allerdings ist dein Programm sehr C-lastig, d.h. du machst viele Sachen, die in C ueblich sind, in C++ aber nur ungern gesehen sind bzw. zum schlechten Stil gehoeren.#include <dos.h> #include <conio.h> #include <stdio.h> #include <alloc.h> #include <string.h> #include <process.h> #include <io.h> #include <fcntl.h>
verwendest du ziemlich viel C-Zeugs. In C++ gehts leichter, wenn du z. B. statt normalen char-Arrays die Klasse string benutzt.
VICI::cpFullName = (char*) malloc(strlen(cpValue)*sizeof(char));
malloc in C++ verwenden ist vollkommen out! in C++ verwendet man new, new[] und delete, delete[]
ansonsten haben eh andere schon das meiste gesagt
was ich nochmal hervorheben moecht:
* lieber const als #define
* Klassennamen und typedefs alle in GROSSBUCHSTABEN hat nur Microsoft in der WinAPI, sonst niemand. Ist zwar Geschmackssache, hat sich in C++ aber fast schon eingebuergert das NICHT so zu machen. Grossgeschrieben werden im Normalfall Makros und Konstanten(ist wie gesagt persoenlicher Geschmack, aber sehr, sehr weit verbreitet)
* gleiches gilt fuer Ungarische Notation. Die mag in C zwar gang & gebe sein, in C++ ist sie aber verpoehnt: Eine der Neuerungen von C++ ist ja gerade, dass man "neue" Datentypen definieren und untereinander austauschen kann. Was machst du, wenn du den Typ einer Variable aenderst? Den Variablennamen ueberall mitveraendern? Unpraktisch und Fehleranfaellig IMOWas mir sonst noch im Code auffaellt:
class VICI { private: char *cpName; char *cpFullName; char *cpVersion; public: VICI(); void TellName(void); void TellVersion(void); void TellDateTime(void); void ExplainName(void); void Tell(char *cpWhat); }; // ... [snip] ... VICI::Tell(VICI_INI_LOADED); VICI::TellName(); VICI::TellDateTime();
Das kann kein C++ Compiler akzeptieren, der was auf sich haelt. Die Funktionen sind nicht static, die brauchen eine Instanz um aufgerufen zu werden funktionieren. Das duerfte gar nicht compilieren
BTW solltest du Klassendefinitionen und -deklarationen in eigene Dateien auslagern
-
Danke für deinen Kommentar 'net'!
net schrieb:
- die '{' an's ende einer zeile zu schreiben macht's auch nicht gerade übersichtlicher. lieber in die nächste zeile damit (ist aber auch, wie vieles andere, geschmackssache)
Ich frag' mich inzwischen, ob ich mir nicht doch eine etwas mehr professionelle version a la:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Function: [FunctionName] */ /* */ /* * Preconditions: */ /* char* pString :0: Terminated String */ /* char* pResult empty Buffer */ /* int iBuffer size of pBuffer */ /* */ /* * Postcondition: */ /* pString unchanged */ /* pResult encoded version of pString */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void foobar(char *pString, char* pResult, int iBuffer) { (... ...) }
angewöhnen sollte
-
Swordfish schrieb:
Danke für deinen Kommentar 'net'!
gern gescheh'n
Swordfish schrieb:
Ich frag' mich inzwischen, ob ich mir nicht doch eine etwas mehr professionelle version a la....
lässte nur noch die ungarische notation wech und dann isses perfekt
-
Blue-Tiger schrieb:
Hi!
Es gibt mittlerweile den BCC 5.5 gratis auf der Borland-SeiteAn neueren IDEs / Compilern hapert's nicht
Blue-Tiger schrieb:
VICI::cpFullName = (char*) malloc(strlen(cpValue)*sizeof(char));
ging mir damals recht schnell von der Hand! Die Alternative wär in BC++ gewesen, sich eine allfällige cString selbst zu bauen, was mir in hinsicht Aufwand/Nutzen nicht gerechtfertigt schien.
Blue-Tiger schrieb:
malloc in C++ verwenden ist vollkommen out! in C++ verwendet man new, new[] und delete, delete[]
<= glaub mir, _mir_ wär's symphatisch gewesen - BC jedoch nicht
Blue-Tiger schrieb:
Was mir sonst noch im Code auffaellt:
class VICI { private: [...] public: VICI(); void TellName(void); void TellVersion(void); void TellDateTime(void); void ExplainName(void); void Tell(char *cpWhat); }; // ... [snip] ... VICI::Tell(VICI_INI_LOADED); VICI::TellName(); VICI::TellDateTime();
Das kann kein C++ Compiler akzeptieren, der was auf sich haelt. Die Funktionen sind nicht static, die brauchen eine Instanz um aufgerufen zu werden funktionieren. Das duerfte gar nicht compilieren
Just once to make you even more confused
#include "stdafx.h" enum INIVALUES{INVALID, NAME, FULLNAME, VERSION, PROMPT}; const char *DAYOFWEEK[] = {"Sunday", "Monday", "Tuesday", "Wensday", "Thuesday", "Friday", "Saturday"}; const int MAX_COMMAND_LENGTH = 80; typedef enum{TRUE=1, FALSE=0} BOOL; typedef int HANDLE; typedef unsigned int UINT; class VICI { private: char *cpName; char *cpFullName; char *cpVersion; char *cpPrompt; BOOL bExit; public: VICI(); BOOL Exit(void); void Prompt(char *cpCommand); void ParseCommand(char *cpCommand); void TellName(void); void TellVersion(void); void ExplainName(void); void Tell(char *cpWhat); }; BOOL VICI::Exit(void) { return bExit; } void VICI::ParseCommand(char *cpCommand) { if(cpCommand[0]=='\0') { return; } if(stricmp(cpCommand, "exit")==0) { bExit=TRUE; return; } if(strcmpi(cpCommand, "who are you")==0|| stricmp(cpCod, "who are u")==0|| stricmp(cpCommand, "who are you?")==0|| stricmp(cpCommand, "who are u?")==0) { VICI::TellName(); return; } if(strcmpi(cpCommand, "vici")==0|| stricmp(cpCommand, "vici?")==0) { VICI::ExplainName(); return; } cprintf("Unrecognized Command!\r\n"); } void VICI::Prompt(char *cpCommand) { char buffer[MAX_COMMAND_LENGHT+3]; buffer[0] = MAX_COMMAND_LENGHT + 1; cprintf("%s", VICI::cpPrompt); strcpy(cpCommand, cgets(buffer)); cprintf("\r\n"); } void VICI::TellVersion(void) { cprintf("This is version %s!\r\n", VICI::cpVersion); } void VICI::Tell(char *cpWhat) { cprintf("%s\r\n", cpWhat); } void VICI::TellName(void) { cprintf("My name is %s.\r\n", VICI::cpName); } void VICI::ExplainName(void) { cprintf("%s means %s.\r\n", VICI::cpName, VICI::cpFullName); } VICI::VICI() { HANDLE hVICIiniFile; bExit = FALSE; char *cpTemp = NULL; VICI::cpName = NULL; VICI::cpVersion = NULL; VICI::cpFullName = NULL; VICI::cpPrompt = NULL; VICI::bExit = FALSE; hVICIiniFile = open("VICI.INI", O_RDWR|O_TEXT); if(hVICIiniFile==-1) { VICI::Tell(VICI_INI_NOT_FOUND); VICI::Tell(VICI_TERMINATED); exit(0); } cpTemp = (char*)malloc((strlen(VICI_INI_LENGTH_INFO)+CountDigits(filelength(hVICIiniFile))-2)*sizeof(char)); sprintf(cpTemp, VICI_INI_LENGTH_INFO, filelength(hVICIiniFile)); VICI::Tell(cpTemp); free(cpTemp); cpTemp = NULL; char cBuffer; char *cpVariable = NULL; char *cpValue = NULL; int iCounter = 0; do { read(hVICIiniFile, &cBuffer, 1); if(cBuffer=='#') { do { read(hVICIiniFile, &cBuffer, 1); } while(!(cBuffer==10||eof(hVICIiniFile))); } else { lseek(hVICIiniFile, -1, SEEK_CUR); iCounter = 0; do { read(hVICIiniFile, &cBuffer, 1); iCounter++; } while(!(cBuffer=='='||eof(hVICIiniFile))); free(cpVariable); cpVariable = NULL; cpVariable = (char*)malloc(iCounter*sizeof(char)); lseek(hVICIiniFile, -iCounter, SEEK_CUR); read(hVICIiniFile, cpVariable, iCounter); cpVariable[iCounter-1] = '\0'; iCounter = 0; do { read(hVICIiniFile, &cBuffer, 1); iCounter++; }while(!(cBuffer==';'||eof(hVICIiniFile))); free(cpValue); cpValue = NULL; cpValue = (char*)malloc(iCounter*sizeof(char)); lseek(hVICIiniFile, -iCounter, SEEK_CUR); read(hVICIiniFile, cpValue, iCounter-1); cpValue[iCounter-1]='\0'; read(hVICIiniFile, &cBuffer, 1); read(hVICIiniFile, &cBuffer, 1); INIVALUES iv = INVALID; if(stricmp(cpVariable, "Prompt")==0) { iv = PROMPT; } if(stricmp(cpVariable, "Name")==0) { iv = NAME; } if(stricmp(cpVariable, "FullName")==0) { iv = FULLNAME; } if(stricmp(cpVariable, "Version")==0) { iv = VERSION; } switch(iv) { case PROMPT: VICI::cpPrompt = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpPrompt, cpValue); break; case VERSION: VICI::cpVersion = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpVersion, cpValue); break; case NAME: VICI::cpName = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpName, cpValue); break; case FULLNAME: VICI::cpFullName = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpFullName, cpValue); break; case INVALID: cprintf("Unrecognized variable: %s!\r\n", cpVariable); break; } } } while(!eof(hVICIiniFile)); close(hVICIiniFile); VICI::Tell(VICI_INI_LOADED); VICI::TellName(); // VICI::TellDateTime(); } void main(void) { VICI v; char cCommand[80]; do { v.Prompt(cCommand); v.ParseCommand(cCommand); }while(!v.Exit()); }
<= compiliert sogar unter VC7!
(etwas abgeändert da eindeutig(VC!=BC)).Blue-Tiger schrieb:
BTW solltest du Klassendefinitionen und -deklarationen in eigene Dateien auslagern
Wäre das Progrämmchen über die 'quick-and-dirty'-Phase hinausgekommen, hätt ich das gemacht
-
Blue-Tiger schrieb:
Hi!
Es gibt mittlerweile den BCC 5.5 gratis auf der Borland-SeiteAn neueren IDEs / Compilern hapert's nicht
Blue-Tiger schrieb:
VICI::cpFullName = (char*) malloc(strlen(cpValue)*sizeof(char));
ging mir damals recht schnell von der Hand! Die Alternative wär in BC++ gewesen, sich eine allfällige cString selbst zu bauen, was mir in hinsicht Aufwand/Nutzen nicht gerechtfertigt schien.
Blue-Tiger schrieb:
malloc in C++ verwenden ist vollkommen out! in C++ verwendet man new, new[] und delete, delete[]
<= glaub mir, _mir_ wär's symphatisch gewesen - BC jedoch nicht
Blue-Tiger schrieb:
Was mir sonst noch im Code auffaellt:
class VICI { private: [...] public: VICI(); void TellName(void); void TellVersion(void); void TellDateTime(void); void ExplainName(void); void Tell(char *cpWhat); }; // ... [snip] ... VICI::Tell(VICI_INI_LOADED); VICI::TellName(); VICI::TellDateTime();
Das kann kein C++ Compiler akzeptieren, der was auf sich haelt. Die Funktionen sind nicht static, die brauchen eine Instanz um aufgerufen zu werden funktionieren. Das duerfte gar nicht compilieren
Just once to make you even more confused
#include "stdafx.h" enum INIVALUES{INVALID, NAME, FULLNAME, VERSION, PROMPT}; const char *DAYOFWEEK[] = {"Sunday", "Monday", "Tuesday", "Wensday", "Thuesday", "Friday", "Saturday"}; const int MAX_COMMAND_LENGTH = 80; typedef enum{TRUE=1, FALSE=0} BOOL; typedef int HANDLE; typedef unsigned int UINT; class VICI { private: char *cpName; char *cpFullName; char *cpVersion; char *cpPrompt; BOOL bExit; public: VICI(); BOOL Exit(void); void Prompt(char *cpCommand); void ParseCommand(char *cpCommand); void TellName(void); void TellVersion(void); void ExplainName(void); void Tell(char *cpWhat); }; BOOL VICI::Exit(void) { return bExit; } void VICI::ParseCommand(char *cpCommand) { if(cpCommand[0]=='\0') { return; } if(stricmp(cpCommand, "exit")==0) { bExit=TRUE; return; } if(strcmpi(cpCommand, "who are you")==0|| stricmp(cpCommand, "who are u")==0|| stricmp(cpCommand, "who are you?")==0|| stricmp(cpCommand, "who are u?")==0) { VICI::TellName(); return; } if(strcmpi(cpCommand, "vici")==0|| stricmp(cpCommand, "vici?")==0) { VICI::ExplainName(); return; } cprintf("Unrecognized Command!\r\n"); } void VICI::Prompt(char *cpCommand) { char buffer[MAX_COMMAND_LENGHT+3]; buffer[0] = MAX_COMMAND_LENGHT + 1; cprintf("%s", VICI::cpPrompt); strcpy(cpCommand, cgets(buffer)); cprintf("\r\n"); } void VICI::TellVersion(void) { cprintf("This is version %s!\r\n", VICI::cpVersion); } void VICI::Tell(char *cpWhat) { cprintf("%s\r\n", cpWhat); } void VICI::TellName(void) { cprintf("My name is %s.\r\n", VICI::cpName); } void VICI::ExplainName(void) { cprintf("%s means %s.\r\n", VICI::cpName, VICI::cpFullName); } VICI::VICI() { HANDLE hVICIiniFile; bExit = FALSE; char *cpTemp = NULL; VICI::cpName = NULL; VICI::cpVersion = NULL; VICI::cpFullName = NULL; VICI::cpPrompt = NULL; VICI::bExit = FALSE; hVICIiniFile = open("VICI.INI", O_RDWR|O_TEXT); if(hVICIiniFile==-1) { VICI::Tell(VICI_INI_NOT_FOUND); VICI::Tell(VICI_TERMINATED); exit(0); } cpTemp = (char*)malloc((strlen(VICI_INI_LENGTH_INFO)+CountDigits(filelength(hVICIiniFile))-2)*sizeof(char)); sprintf(cpTemp, VICI_INI_LENGTH_INFO, filelength(hVICIiniFile)); VICI::Tell(cpTemp); free(cpTemp); cpTemp = NULL; char cBuffer; char *cpVariable = NULL; char *cpValue = NULL; int iCounter = 0; do { read(hVICIiniFile, &cBuffer, 1); if(cBuffer=='#') { do { read(hVICIiniFile, &cBuffer, 1); } while(!(cBuffer==10||eof(hVICIiniFile))); } else { lseek(hVICIiniFile, -1, SEEK_CUR); iCounter = 0; do { read(hVICIiniFile, &cBuffer, 1); iCounter++; } while(!(cBuffer=='='||eof(hVICIiniFile))); free(cpVariable); cpVariable = NULL; cpVariable = (char*)malloc(iCounter*sizeof(char)); lseek(hVICIiniFile, -iCounter, SEEK_CUR); read(hVICIiniFile, cpVariable, iCounter); cpVariable[iCounter-1] = '\0'; iCounter = 0; do { read(hVICIiniFile, &cBuffer, 1); iCounter++; }while(!(cBuffer==';'||eof(hVICIiniFile))); free(cpValue); cpValue = NULL; cpValue = (char*)malloc(iCounter*sizeof(char)); lseek(hVICIiniFile, -iCounter, SEEK_CUR); read(hVICIiniFile, cpValue, iCounter-1); cpValue[iCounter-1]='\0'; read(hVICIiniFile, &cBuffer, 1); read(hVICIiniFile, &cBuffer, 1); INIVALUES iv = INVALID; if(stricmp(cpVariable, "Prompt")==0) { iv = PROMPT; } if(stricmp(cpVariable, "Name")==0) { iv = NAME; } if(stricmp(cpVariable, "FullName")==0) { iv = FULLNAME; } if(stricmp(cpVariable, "Version")==0) { iv = VERSION; } switch(iv) { case PROMPT: VICI::cpPrompt = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpPrompt, cpValue); break; case VERSION: VICI::cpVersion = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpVersion, cpValue); break; case NAME: VICI::cpName = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpName, cpValue); break; case FULLNAME: VICI::cpFullName = (char*) malloc(strlen(cpValue)*sizeof(char)); strcpy(VICI::cpFullName, cpValue); break; case INVALID: cprintf("Unrecognized variable: %s!\r\n", cpVariable); break; } } } while(!eof(hVICIiniFile)); close(hVICIiniFile); VICI::Tell(VICI_INI_LOADED); VICI::TellName(); // VICI::TellDateTime(); } void main(void) { VICI v; char cCommand[80]; do { v.Prompt(cCommand); v.ParseCommand(cCommand); }while(!v.Exit()); }
<= compiliert sogar unter VC7!
(etwas abgeändert da eindeutig(VC!=BC)).Blue-Tiger schrieb:
BTW solltest du Klassendefinitionen und -deklarationen in eigene Dateien auslagern
Wäre das Progrämmchen über die 'quick-and-dirty'-Phase hinausgekommen, hätt ich das gemacht
-
hab ich wirlich auf 'Absenden' geklickt *rotwerd*
wär mir sehr recht falls n Moderator einen meiner letzten beiden Beiträge killn könnt...
-
Swordfish schrieb:
Wie gesagt: du koenntest dir
<= compiliert sogar unter VC7!
(etwas abgeändert da eindeutig(VC!=BC)).ok, sorry, mein Fehler, hab in der Eile nicht gesehen, dass die Methoden innerhalb anderer Klassenmethoden aufgerufen werden
Das
VICI:: vor den Namen find ich sehr verwirrend
-
Blue-Tiger.giveAbsolution();
Is doch passend, ich mein zu Ostern...
-
Swordfish schrieb:
int main(void) ist doch eindeutig overhead, oder...
Was meinst du mit Overhead?
Der Punkt ist einfach der, dass in C++ int als Rückgabetyp von main vorgeschrieben ist. Ein 'void main(void)' ist deshalb kein korrektes C++. Einige pedantische Compiler werden das auch bemängeln. In C sieht das übrigens nicht viel anders aus.
-
War nur 'n späßchen...
int main(void);
ist natürlich Korrekt, Verpflichtet jedoch zu 'unnötigem' Datentransport von main() an das aufrufende Environment.