kennt sich jemand mit C aus?
thomas
- sonstiges
Guten Tag,
meine Aufgabenstellung lautet:
1. Geben sie Text zeichenweise aus von Konsole ein (getchar, getch) und speichern sie die Zeichen in einem char-Feld. Terminieren sie den Text und geben sie ihn zur Kontrolle auf Konsole aus.
2. Ermitteln sie selbst die Textlänge und kontrollieren sie das Ergebnis mit strlen.
soweit kein problem nur am 3. scheiterts dann:
3. Zählen sie, wie oft ein gegebens Zeichen (Konsoleingabe) in dem gespeicherten Text vor kommt.
Ich sitze nun schon mehrere Stunden vor dieser Aufgabe und komme einfach nicht weiter, kann mir jemand helfen? hier ist ein Ausschnitt aus dem Programm:
#include <stdio.h>
#include <string.h>
#include <conio.h>
#define ANZ 20
void zeichenausgabe(void)
{
int x;
char string[ANZ+1] , c;
printf("STRING\n");
printf("-------\n");
printf("Eingabe ");
x=0;
do{
c = getch();
if(x<ANZ && x!=13)
{
putchar(c);
string[x] = c;
++x;
}
}while(c!=13);
string[x-1] = '\0';
printf("\n\nString %s \n", string);
printf("Laenge %d\n\n", strlen(string));
printf("\n\n\n\n");
getch();
}
for (int Counter=0; Counter<Length; Counter++)
{
if (String[Counter] == Character) Indikator++;
}
Hab das jetzt so mal ohne zu testen runtergetippt.
String ist deine Zeichenkette, sie kann ruhig vom Typ string sein, aber wenn du eckige Klammern verwendest, kannst du einzelne Zeichen ansprechen. Das ist wohl das was du nicht gewußt hast.
Character ist das zu suchende Zeichen.
Indikator ist die int-Variable, die du erhöst, wenn ein Zeichen übereinstimmt.
Gruß Giovanni
PS, nicht C, C++!
erstmal danke für die recht schnelle antwort!
nicht C, C++!
^^doch es ist C ;-)
erstmal danke für die recht schnelle antwort!
nicht C, C++!
^^doch es ist C ;-)
Also so weit ich weiß, gehören strings zu C++ und die gibt es nicht in C. Möchte man in C mit strings arbeiten, muss man Charfelder verwenden. Sprich, du arbeitest doch mit C++. C hat nur einen sehr beschränkten Befehlsumfang. Wenn ich mich richtig errinere sind es glaub nur 27.
Ich könnte mich auch in 0-n Punkten irren. Aber ich glaub das stimmt schon so wie ich es geschrieben hab.
Gruß Giovanni
你好 Giovanni,
Also so weit ich weiß, gehören strings zu C++ und die gibt es nicht in C.
Möchte man in C mit strings arbeiten, muss man Charfelder verwenden.
Du verwechselst da was. std::string gehoert zu C++, ja. Aber auch C hat
Strings (0-terminierte char-Felder).
Sprich, du arbeitest doch mit C++.
Nein, er arbeitet mit C -- ein std::string habe ich in seinem Quelltext
naemlich nicht gesehen :) Geschweige denn ein anderes C++-Konstrukt.
C hat nur einen sehr beschränkten Befehlsumfang. Wenn ich mich richtig
errinere sind es glaub nur 27.
Du meinst reservierte Woerter. Reservierte Woerter hat C genau 33. C++ hat
uebrigens nur wenig mehr: 50.
再见,
CK
Okay!
Ich habe mich dann also in n Punkten geiirt, wobei n=gesamte Anzahl ist!
Gruß Giovanni
ich hatte noch eine frage gestellt :-s
你好 thomas,
soweit kein problem nur am 3. scheiterts dann:
3. Zählen sie, wie oft ein gegebens Zeichen (Konsoleingabe) in dem
gespeicherten Text vor kommt.
Du hast mehrere Moeglichkeiten. Am einfachsten duerfte es sein, einen
unsigned char-Array mit der Groesse 256 zu bauen, den mit 0 zu
initialisieren und dann bei jedem eingelesenen Zeichen die entsprechende
Stelle im Array hochzuzaehlen:
void zeichenausgabe(void) {
int x;
unsigned char string[ANZ+1] , c;
unsigned char field[256];
printf("STRING\n");
printf("-------\n");
printf("Eingabe ");
for(x=0;x<256;++x) field[x] = 0;
x = 0;
do {
c = getch();
if(x<ANZ && x!=13) {
putchar(c);
string[x] = c;
++x;
field[c]++;
}
} while(c!=13);
string[x-1] = '\0';
printf("\n\nString %s \n", string);
printf("Laenge %d\n\n", strlen(string));
printf("\n\n\n\n");
}
Wie du das jetzt ausgibst bleibt dir ueberlassen ;-)
再见,
CK
你好 thomas,
soweit kein problem nur am 3. scheiterts dann:
3. Zählen sie, wie oft ein gegebens Zeichen (Konsoleingabe) in dem
gespeicherten Text vor kommt.
Oh, verlesen, ich hatte gelesen, wie oft jedes einzelne Zeichen vorkommt.
In dem Fall ist natuerlich Giovannis Loesung vorzuziehen.
再见,
CK
#include <stdio.h>
#include <conio.h>
void tabelle(void);
void ASCII(void);
void taschenrechner(void);
void zeichenausgabe(void);
int main(void)
{
int z;
do{
printf("Waehlen Sie ein Programm aus\n\n");
printf("Programm 1 - Datentypen\n");
printf("Programm 2 - ASCII-Tabelle\n");
printf("Programm 3 - Taschenrechner\n");
printf("Programm 4 - Zeichenausgabe\n");
printf("Exit 5\n");
printf("\nEingabe ");
z = 0;
scanf("%d", &z);
printf("\n\n");
if( z==1) tabelle();
else if(z==2) ASCII();
else if(z==3) taschenrechner();
else if(z==4) zeichenausgabe();
}while(z==1 || z==2 || z==3 || z!=5);
return 0;
}
was fehlt jetzt noch? wie gebe ich das genau aus?
sorry bin anfänger in der materie
int main(void)
wieso Rückgabewert int? Brauchst du doch in deinem Programm gar nicht!
{
int z;do{
printf("Waehlen Sie ein Programm aus\n\n");
printf("Programm 1 - Datentypen\n");
printf("Programm 2 - ASCII-Tabelle\n");
printf("Programm 3 - Taschenrechner\n");
printf("Programm 4 - Zeichenausgabe\n");
printf("Exit 5\n");
printf("\nEingabe ");z = 0;
scanf("%d", &z);printf("\n\n");
if( z==1) tabelle();
else if(z==2) ASCII();
else if(z==3) taschenrechner();
else if(z==4) zeichenausgabe();
Nimm lieber Switch, Case, ich würde bei 4 Abfragen if nicht mehr unbedingt verwenden. Aber vergess die break nicht!
}while(z==1 || z==2 || z==3 || z!=5);
}
was fehlt jetzt noch?
Hmmmmm, also dieses Menü würde so meiner Meinung nach schon funktionieren.
Wie gebe ich das genau aus?
Was willst du ausgeben? Zum Ausgeben kannst du wie oben z. B. printf ()verwenden, oder cout << "Test";
sorry bin anfänger in der materie
Das errinert mich an meine Anfangszeit. Da habe ich auch, so zielmich das gleiche gemacht wie du jetzt.
Gruß Giovanni
你好 Giovanni,
int main(void)
wieso Rückgabewert int? Brauchst du doch in deinem Programm gar nicht!
In C _muss_ die main()-Funktion int zurueckgeben. Ist so definiert, per
Standard.
再见,
CK
Aha, hab mich nur mit C++ beschäftigt. Hoffe hab dir dennoch helfen können!
Zum Ausgeben kannst du wie oben z. B. printf ()verwenden, oder cout << "Test";
cout << "Test"; läßt sich aber nicht mit einem C-Compiler übersetzen und nach Aufgabenstellung soll das Programm wohl in C und nicht in C++ geschrieben werden.
Gruß, rob
Hi,
ah, soweit isser doch schon ;-)
int main(void)
{
int z;do{
Warum machst Du hier eine Schleife mit Bedingung, die Du ehe schon in der Schleife abfragst?
printf("Waehlen Sie ein Programm aus\n\n");
[...]
printf("\nEingabe ");
z = 0;
scanf("%d", &z);
scanf() gibt im Fehlerfalle etwas zurück und setzt errno entsprechend. Bitte nutzen. Wenn keine Nummer sondern ein Buchstabe eingegeben wurde gibt scanf() z.B. 0 zurück. Abfangen wie im anderem Posting beschrieben.
printf("\n\n");
Das ist hier etwas zu früh. Aber egal.
if( z==1) tabelle();
else if(z==2) ASCII();
else if(z==3) taschenrechner();
else if(z==4) zeichenausgabe();
}while(z==1 || z==2 || z==3 || z!=5);
Wenn Du nun statt Deines Konstruktes folgendes genommen hättest:
switch(z){
case 1: tabelle();
break;
case 2: ASCII();
break;
case 3: taschenrechner();
break;
case 4: zeichenausgabe();
break;
case 5: exit(EXIT_SUCCESS);
default: puts("Nein, eine Zahl zwischen 1 und 5 bitte");
break;
}
} while(true);
return 0;
}
was fehlt jetzt noch? wie gebe ich das genau aus?
Gute Frage, was möchtest Du denn noch gerne ausgeben?
sorry bin anfänger in der materie
Ja, das ist eine typische Übungsaufgabe. Sogar richtig typisch, denn um den Standard kümmert sich mal wieder keine Sau, Fehler werden nicht abgefangen, es wird eigentlich zuviel verlangt usw.
Ja, ich weiß:"Dann mach's doch besser!", aber ist ja schon in Arbeit also verkneift euch das <I> ;-)
so short
Christoph Zurnieden
Hi,
Da Dir hier Hilfe ohne Erklärung zuteil wurde (kommt eher selten vor, wundert mich eigentlich), mach ich mich mal dran. Auch wenn das wahrscheinlich mal wieder kein Schwein liest ;-)
Verlangt wird Standard-C, ja?
#include <stdio.h>
#include <string.h>
#include <conio.h>
conio.h ist nicht im Standard enthalten.
#define ANZ 20
Hier fehlt der kurze Kommentar, was diese Nummer machen soll.
void zeichenausgabe(void)
Eigentlich sollte eien Funktion, in der etwas schiefgehen kann, auch immer etwas zurückgeben. Aber gut, will nicht _zu_ kleinlich sein.
{
Geschweifte Klammern auf eine neue Zeile zu setzen kann zu Unfällen führen. War erst neulich hier im Forum.
int x;
In stdint.h sind passende Typen für alle Zwecke aufgeführt. Nimm diese anstatt einfach nur int.
#include <stdint.h>
char string[ANZ+1] , c;
Man sollte die Variablen vorbelegen (nicht immer, aber das kommt erst sehr viel später. Richtig falsch ist aber nie):
uint8_t x = 0;
char string[ANZ+1], c=(char)(0); // oder c = '\0'
memset(string,'\0',ANZ+1);
printf("STRING\n");
printf("-------\n");
printf("Eingabe ");
Kannst Du zusammenfassen (printf() ist teuer)
printf("STRING\n-------\nEingabe ");
x=0;
Kann hier wegfallen, da oben bereits initialisiert.
do{
c = getch();
getch() ist nicht im Standard, getc(FILE *stream) ist es. Es gibt auch noch getchar(), das ist äquivalent zu getc(stdin).
c = getchar();
if(c == EOF){ // unter Linux und der Bash kann man EOF mit STRG+d erzeugen
printf("getchar(): %25.25s\n",strerror(errno));
}
if(x<ANZ && x!=13)
Was versteckt sich hinter der 13? Versuchst Du die Entertaste zu erwischen? Laut Deinem Code testest Du aber nur darauf, ob schon der 13. Buchstabe eingegeben wurde. Ein for-Loop wäre hier sinnvoller. Du kannst, was Du wahrscheinlich nicht wußtest, auch mehrere Bedingungen hineinpacken:
for(; x<ANZ && x!=13;x++){ ...
{
putchar(c);
string[x] = c;
++x;
}
}while(c!=13);
Hier testest Du darauf, ob ein Zeichen mit der Nummer 13 eingegeben wurde. Du scheinst die 13 zu mögen, was? ;-)
BTW: ein cast wäre hier eigentlich angesagt:
}while(c!=(char)(13));
Und 13 ist \r. Wenn Du das Zeilenende erwartest, dann benutze auch das entsprechende Zeichen. Leider ist das nicht portabel, da es eine Menge Zeichen für dsa Zeilenende gibt. Selbst wenn man es auf die gängigsten 3 reduziert wird unangenehm: Apple hat '\r', MS hat '\r\n', Unix hat '\n'.
string[x-1] = '\0';
Brauchst Du nicht, da weiter oben schon im Gesamten auf '\0' gesetzt.
printf("\n\nString %s \n", string);
printf("Laenge %d\n\n", strlen(string));
printf("\n\n\n\n");
Auch hier kannst Du zusammenfassen (\t ist der Tabulator):
printf("\nString\t%s\nLaenge\t%d\n",string, strlen(string));
so short
Christoph Zurnieden
Hallo Christoph,
sehr schön ausgeführt, für meinen Geschmack schon etwas *zu* schulmeisterlich, aber das ist Geschmackssache.
#define ANZ 20
Hier fehlt der kurze Kommentar, was diese Nummer machen soll.
"Fehlt" ist ziemlich stark formuliert. Da könnte man meinen, der Kommentar sei Pflicht. Sinnvoll und sehr empfehlenswert ist er aber allemal.
{
Geschweifte Klammern auf eine neue Zeile zu setzen kann zu Unfällen führen. War erst neulich hier im Forum.
Ich weiß jetzt nicht, auf welchen Fall du ansprichst. Aber ich persönlich setze die öffnende und die schließende geschweifte Klammer IMMER in eine neue Zeile. Ich finde das übersichtlicher. Wenn ich fremden Programmcode durchgehen muss, gibt es für mich kaum was Schlimmeres, als eine öffnende Klammer, die noch so unauffällig am Zeilenende steht. Da übersehe ich sie nämlich leicht.
char string[ANZ+1], c=(char)(0); // oder c = '\0'
Die Typen char und int sind zuweisungskompatibel, deswegen halte ich die Schreibweise '\0' eigentlich für unnötig kompliziert, genauso wie einen type cast zwischen int und char.
memset(string,'\0',ANZ+1);
Wenn schon, dann:
char string[ANZ+1] = "";
Selbst das ist Standard. Arrayelemente (in diesem Fall chars), die bei der Initialisierung nicht explizit einen Wert erhalten, werden mit 0 belegt (oder '\0' oder NULL, je nachdem was dir am liebsten ist).
BTW: ein cast wäre hier eigentlich angesagt:
}while(c!=(char)(13));
Überflüssig. Macht die Sache IMHO nur schwerer zu lesen.
Und 13 ist \r. Wenn Du das Zeilenende erwartest, dann benutze auch das entsprechende Zeichen. Leider ist das nicht portabel, da es eine Menge Zeichen für dsa Zeilenende gibt. Selbst wenn man es auf die gängigsten 3 reduziert wird unangenehm: Apple hat '\r', MS hat '\r\n', Unix hat '\n'.
ACK (nur das mit dem Apple wusste ich noch nicht).
Aber die getchar()-Funktion liefert unabhängig davon den "reinen" ASCII-Code, der der Taste zugeordnet ist. Bei der Enter-Taste ist das generell '\r' (oder 13 oder '\x0D'). Erst wenn man das jetzt auch noch ausgeben will, muss man aufpassen, weil putchar() das Zeichen uninterpretiert ausgibt. Hier kann man also beim gleichen Zeichen plattformabhängig verschiedene Ergebnisse erhalten. Bei printf() ist es wieder anders: Hier wird '\n' (oder 10 oder '\x0A') automatisch in das Zeichen oder die Zeichenfolge konvertiert, die auf dem jeweiligen System eine neue Zeile erzeugt. Unter MS-Betriebssystemen also in "\r\n".
Ich hoffe, du fühlst dich jetzt nicht angegriffen oder so; ich wollte nur deutlich machen, dass manches, was du hier empfohlen hast, eigentlich übervorsichtig ist - oder eben Geschmackssache. ;)
Schönen Abend noch,
Martin
Hi,
sehr schön ausgeführt, für meinen Geschmack schon etwas *zu* schulmeisterlich, aber das ist Geschmackssache.
Es ist recht eng hier im Forum, da bleibt wenig Raum für so ausführliche Anmerkungen, wie man es eigentlich gerne schriebe. Da entsteht gerne Mal der Eindruck der Beckmesserei, der ist aber keineswegs beabsichtigt.
#define ANZ 20
Hier fehlt der kurze Kommentar, was diese Nummer machen soll.
"Fehlt" ist ziemlich stark formuliert. Da könnte man meinen, der Kommentar sei Pflicht. Sinnvoll und sehr empfehlenswert ist er aber allemal.
Wenn Du mit anderen Leuten zusammenarbeitest, ob jetzt oder in Zukunft, oder den Code einfach nur veröffentlichst, oder in ein paar Jahren selber noch verstehen möchtest, dann ist das einfach Pflicht. Da beschwert sich kein Compiler oder Lint, nur derjenige, der sich die Daten mühselig zusammensuchen muß, aber auch sowas nenne ich Pflicht.
{
Geschweifte Klammern auf eine neue Zeile zu setzen kann zu Unfällen führen. War erst neulich hier im Forum.
Ich weiß jetzt nicht, auf welchen Fall du ansprichst.
Bin jetzt zu faul zum Suchen, aber das war ungefähr so:
for(int i=0;i<100;i++);
{
printf("Inner Loop\n");
}
"Der gibt nix aus, woran liegt's?" war ungefähr die Frage.
Nur das im Loop halt noch sehr viel mehr als nur ein printf() ausgeführt wurde.
Kannst ja mal im Archiv nach meinem Namen und "Indian Hill Style" (am Besten in Variationen;-) suchen. Ist vielleicht zwei Wochen her.
Wenn ich fremden Programmcode durchgehen muss, gibt es für mich kaum was Schlimmeres, als eine öffnende Klammer, die noch so unauffällig am Zeilenende steht. Da übersehe ich sie nämlich leicht.
Dann wechsle Deinen Editor.
Nein, wirklich: Blöcke, Semantik im Allgemeinem, sollte ein Editor gut darstellen können, sonst taugt er nicht viel.
char string[ANZ+1], c=(char)(0); // oder c = '\0'
Die Typen char und int sind zuweisungskompatibel, deswegen halte ich die Schreibweise '\0' eigentlich für unnötig kompliziert, genauso wie einen type cast zwischen int und char.
Ja, wenn das alles so einfach wäre ;-)
So funktioniert das nur auf einem PC o.ä., wenn Du auf "exotischere" Platformen umschwenkst kannst Du damit ganz gewaltig auf die Schnauze fallen.
Ein Byte ist nicht überall 8 Bit lang, ein int nicht überall 32 Bit, aber ein char entspricht einem Byte und ein Byte ist groß genug ein Zeichen der jeweiligen Umgebung zu halten:
3.4
1 byte
addressable unit of data storage large enough to hold any member of the basic characterset of the execution environment
2 NOTE 1 It is possible to express the address of each individual byte of an object uniquely.
3 NOTE 2 A byte is composed of a contiguous sequence of bits, the number of which is implementation defined. The least significant bit is called the low order bit; the most significant bit is called the highorder bit.
Was Du meinst ist wahrscheinlich "integer promotions", d.h. das Du z.B. zwei chars einfach addieren kannst.
Nebenbei: was ist mit dem Unterschied von uchar und char? Du kann sowas machen: char c = 'ä', aber was dabei rauskommt ist fraglich, wenn es nicht bereits eine Compilerwarnung bekommt.
memset(string,'\0',ANZ+1);
Wenn schon, dann:
char string[ANZ+1] = "";
Selbst das ist Standard.
Ja, stimmt, ist wohl alte Gewohnheit bei mir ;-)
Arrayelemente (in diesem Fall chars), die bei der Initialisierung nicht explizit einen Wert erhalten, werden mit 0 belegt (oder '\0' oder NULL, je nachdem was dir am liebsten ist).
Nein, das stimmt wieder nicht.
6.7.8 Initialization
[...]
10 If an object that has automatic storage duration is not initialized explicitly,its value is indeterminate. If an object that has static storage duration is not initialized
explicitly, then:
---if it has pointer type, it is initialized to a null pointer;
---if it has arithmetic type, it is initialized to (positive or unsigned) zero;
---if it is an aggregate, every member is initialized (recursively) according to these rules;
---if it is a union, the first named member is initialized (recursively) according to these rules.
[...]
14 An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
Also
char string[ANZ+1] = "";
entspricht nach neuem Standard
char string[ANZ+1];
memset(string,'\0',ANZ+1);
was ich mir noch nicht so ganz angewöhnt habe, jedoch
char string[ANZ+1];
alleine reicht dafür nicht.
BTW: ein cast wäre hier eigentlich angesagt:
}while(c!=(char)(13));Überflüssig. Macht die Sache IMHO nur schwerer zu lesen.
Ich finde eher das Gegenteil. Hier macht das nix, aber wenn der Loop recht lang ist, wäre so ein cast schon hilfreich.
BTW: ganz vergessen, das hier die 13 als kommentiertem #define besser aufgehoben gewesen wäre. So eine nackte Zahl sagt wenig, aber z.B. RETURNKEY o.ä. ist recht aussagekräftig und kann vor allem auch einfach nachgesucht werden (find, grep u. Konsorten)
Aber die getchar()-Funktion liefert unabhängig davon den "reinen" ASCII-Code, der der Taste zugeordnet ist.
Nein, definitiv nicht. getchar() ist nix anderes als getc(stdin), was nix anderes als fgetc(stdin) ist. Es wird also nur ein char (genauer: ein auf _unsigned_ char gecasteter int!) zurückgegeben, das aus dem Dateistrom namens "stdin" gelesen wurde. Das kann durchaus ASCII-Code sein, oder 8-Bit Codierung oder wwi. Es muß noch nicht einmal eine Taste gedrückt worden sein, davon hat C eh keine Ahnung.
Bei der Enter-Taste ist das generell '\r' (oder 13 oder '\x0D').
Das sagt wer? Wo steht das? In meinem C-99 Standard steht nix davon.
Erst wenn man das jetzt auch noch ausgeben will, muss man aufpassen, weil putchar() das Zeichen uninterpretiert ausgibt. Hier kann man also beim gleichen Zeichen plattformabhängig verschiedene Ergebnisse erhalten.
Ja, da kann ich nur beipflichten, aber das ist rein gar kein Unterschied zu getchar(), der macht das Gleiche.
Bei printf() ist es wieder anders: Hier wird '\n' (oder 10 oder '\x0A') automatisch in das Zeichen oder die Zeichenfolge konvertiert, die auf dem jeweiligen System eine neue Zeile erzeugt. Unter MS-Betriebssystemen also in "\r\n".
So sollte es sein, so steht es im Standard, ja.
Nur gilt das (vid. 5.2.2 Character display semantics) nicht nur für printf() sondern z.B. logischerweise auch für scanf(). Das ist dann aber eines der Dinge auf die ich mich nicht unbedingt blind verlassen würde ;-)
(Geht auch erfahrungsgemäß in die Hose sowas)
Ich hoffe, du fühlst dich jetzt nicht angegriffen oder so; ich wollte nur deutlich machen, dass manches, was du hier empfohlen hast, eigentlich übervorsichtig ist - oder eben Geschmackssache. ;)
Üebr Geschmack läßt sich trefflich streiten, ja, aber als übervorsichtig würde ich mich nicht sehen. Standard-C ist nunmal die portabelste Sprache und wird jetzt wieder zunehmend für embedded Systems modern. Da kann man sich keine Nachlässigkeiten leisten, da muß man Standard-C oder sogar ANSI-C schreiben. Wenn das nicht eh schon direkt baut, so reichen doch stets einige wenige Handgriffe zur Anpassung.
Deshalb sollte der Anfänger Standard-C lernen und kein Windows-C, DOS-C, Linux-C oder was weiß ich alles. Das ist auch einfach zu lernen, da das nicht sehr viel ist. Wenn das dann sitzt, dann und wirklich erst dann kann man damit anfangen systemspezifische Erweiterungen einzuführen.
so short
Christoph Zurnieden
Guten Abend nochmal!
[Kommentar]
Wenn Du mit anderen Leuten zusammenarbeitest, [...] aber auch sowas nenne ich Pflicht.
Gut, wenn du es so siehst, stimme ich unbedingt zu.
for(int i=0;i<100;i++);
{
printf("Inner Loop\n");
}"Der gibt nix aus, woran liegt's?" war ungefähr die Frage.
Ey, ein Semikolon hinter einer for-Anweisung ist ja auch schon verdächtig. Auch wenn manche Programmierer -mich selbst eingeschlossen- bei kurzen Loops manchmal alles in die Klammer packen. Dann wäre das okay.
Aber das hat meiner Ansicht nach nichts mit der Frage zu tun, ob eine Klammer am Zeilenende oder am Zeilenanfang stehen sollte.
Dann wechsle Deinen Editor.
Nein, wirklich: Blöcke, Semantik im Allgemeinem, sollte ein Editor gut darstellen können, sonst taugt er nicht viel.
Ach so...? ich hab noch nie einen Editor mit Syntax-Highlighting oder sowas benutzt. Oder... doch, ja, aber das ist lange her. Und bei dem hab ich das ziemlich schnell wieder abgestellt, weil ich es nervig fand. Ansichtssache, da haben wir's wieder. ;)
char string[ANZ+1], c=(char)(0); // oder c = '\0'
Die Typen char und int sind zuweisungskompatibel, deswegen halte ich die Schreibweise '\0' eigentlich für unnötig kompliziert, genauso wie einen type cast zwischen int und char.
Ja, wenn das alles so einfach wäre ;-)
Das ist es auch!
So funktioniert das nur auf einem PC o.ä., wenn Du auf "exotischere" Platformen umschwenkst kannst Du damit ganz gewaltig auf die Schnauze fallen.
Ich habe auch schon Embedded-Anwendungen auf diversen µC's gebastelt. Ha, da war ein int noch 8bit wert!
Ein Byte ist nicht überall 8 Bit lang, ein int nicht überall 32 Bit, aber ein char entspricht einem Byte und ein Byte ist groß genug ein Zeichen der jeweiligen Umgebung zu halten:
Selbstverständlich. Der Auszug aus dem Standard, den du zitierst, sagt allerdings nichts zur char/int-Verwandtschaft. Ich kenne den Standard zwar nicht in der Theorie, aber aus der Anwendung. Und da sind nun mal char und int nichts weiter als zwei Varianten eines Integer-Grundtyps und somit zuweisungskompatibel.
Nur mit dem Vorzeichen muss man dann und wann aufpassen. Das kann man aber recht gut vermeiden, indem man -soweit möglich- unsigned-Typen verwendet. Oft kann man das sogar ohne Einschränkung machen.
Nebenbei: was ist mit dem Unterschied von uchar und char? Du kann sowas machen: char c = 'ä', aber was dabei rauskommt ist fraglich, wenn es nicht bereits eine Compilerwarnung bekommt.
Sag ich doch: Wenn ein Vorzeichen ins Spiel kommt, muss man aufpassen. Aber das Vorzeichen ist eh nur Illusion: Ein gesetztes MSB, das nur bei ein paar wenigen Operationen (>>-Operator, Ausgabe über eine der printf-Funktionen) überhaupt eine besondere Rolle spielt.
Arrayelemente (in diesem Fall chars), die bei der Initialisierung nicht explizit einen Wert erhalten, werden mit 0 belegt (oder '\0' oder NULL, je nachdem was dir am liebsten ist).
Nein, das stimmt wieder nicht.
Dein Auszug aus dem Standard beschreibt nur, was der Compiler daraus machen soll, wenn der Programmierer seine Variablen *nicht* explizit initialisiert.
Ich meine mich aber zu erinnern, dass es irgendwo eine Regel gibt, nach der strukturierte Datentypen (und dazu gehören ja auch Arrays) mit Nullwerten aufgefüllt werden, wenn sie *nur teilweise* initialisiert werden, so wie z.B.
unsigned long pp[40] = { 2, 1, 0 };
Hier werden die 37 nicht genannten Elemente implizit mit 0 belegt.
Also
char string[ANZ+1] = "";
entspricht nach neuem Standard
char string[ANZ+1];
memset(string,'\0',ANZ+1);
was ich mir noch nicht so ganz angewöhnt habe, jedoch
char string[ANZ+1];
alleine reicht dafür nicht.
Das hab ich auch nicht gesagt. Diese Zeile ist ja auch nur eine Deklaration, keine Initialisierung.
Bei der Enter-Taste ist das generell '\r' (oder 13 oder '\x0D').
Das sagt wer? Wo steht das? In meinem C-99 Standard steht nix davon.
Sorry, da bin ich jetzt ganz selbstverständlich von der PC-üblichen Implementierung ausgegangen. War wohl ein Satz mit X.
[scanf()] Das ist dann aber eines der Dinge auf die ich mich nicht unbedingt blind verlassen würde ;-)
(Geht auch erfahrungsgemäß in die Hose sowas)
Ja, das hat was...
Deshalb sollte der Anfänger Standard-C lernen und kein Windows-C, DOS-C, Linux-C oder was weiß ich alles.
Richtig. Die Spezialisierung auf eine bestimmte Plattform kommt erfahrungsgemäß von ganz allein im Lauf der Zeit.
Ciao,
Martin
Hi,
for(int i=0;i<100;i++);
[...]
Ey, ein Semikolon hinter einer for-Anweisung ist ja auch schon verdächtig.
Aber sehr schnell gemacht, da hinter fast jeder Zeile ein Semikolon steht. Da ensteht mit der Zeit ein gewisser Automatismus. Obiger Fehler ist auch teilweise schlecht zu sehen, da ein Semikolon am Zeilenende nicht auffällt. Es ist ja mehrheitlich durchaus in Ordnung und wenn doch nicht, wird ein Syntaxfehler produziert.
Auch wenn manche Programmierer -mich selbst eingeschlossen- bei kurzen Loops manchmal alles in die Klammer packen. Dann wäre das okay.
Aber das hat meiner Ansicht nach nichts mit der Frage zu tun, ob eine Klammer am Zeilenende oder am Zeilenanfang stehen sollte.
Weil
for(int i=0;i<100;i++){;
kein Problem dargestellt hätte?
Aber ich werde einen Teufel tun, und mich auf eine Diskussion über Style einlassen. Bis auf diese eine Stelle wüßte ich auch weiter nichts, was über reine Geschmacksache hinausginge. Und "Einer ist Keiner" wie's so schön heißt, oder? :-)
Halt, nein, einen gibt's noch: man sollte bei Vergleichen mit Konstanten eigentlich die Konstante voranstellen
if(INTEGER_CONSTANT == variable)
Damit der typische Fehler
if(INTEGER_CONSTANT = variable)
eine Syntaxfehler ergibt. Aber daran kann ich mich dann wieder nicht gewöhnen ;-)
So funktioniert das nur auf einem PC o.ä., wenn Du auf "exotischere" Platformen umschwenkst kannst Du damit ganz gewaltig auf die Schnauze fallen.
Ich habe auch schon Embedded-Anwendungen auf diversen µC's gebastelt. Ha, da war ein int noch 8bit wert!
Ich rede von exotischen Architekturen. So ein 8-Bit-PIC von Conrad-Elektronik ist noch lange nicht exotisch ;-)
(Viele Maschinenbauaer haben in den Anfangstagen ihr eigenes Süppchen gekocht. Wenn man da auf eine PDP-11 als Embeded Prozessor stieß, war man noch glücklich dran. Da wurden Sachen entwickelt, das glaubst Du noch nicht einmal wenn Du's siehst ;-)
Ein Byte ist nicht überall 8 Bit lang, ein int nicht überall 32 Bit, aber ein char entspricht einem Byte und ein Byte ist groß genug ein Zeichen der jeweiligen Umgebung zu halten:
Selbstverständlich. Der Auszug aus dem Standard, den du zitierst, sagt allerdings nichts zur char/int-Verwandtschaft.
Da gibt es auch außer dem Hinweis auf die "integer promotion" (man kann mit char Typen Integerberechnungen ausführen) nichts zu.
Ich möchte aber diese Stelle - denn sie ist genau so gut, wie jede andere - auch dazu nutzen folgendes festzustellen: der C-Standard ist keineswegs perfekt, der hat auch seine Macken, ist aber im großem und ganzem in Ordnung und gebrauchsfähig.
Es ist also durchaus möglich, das er hier eine seiner Macken zeigt.
Ich kenne den Standard zwar nicht in der Theorie, aber aus der Anwendung.
Aus den Implementationen? Also als Microsoft-C, Borland-C, Gnu-C usw?
Und da sind nun mal char und int nichts weiter als zwei Varianten eines Integer-Grundtyps und somit zuweisungskompatibel.
Da der Standard das aber nicht festgelegt hat, ist das nur implementationsabhängig. Würde ich kein sauberes Hemd dran aufhängen wollen, kann bei der nächsten Version schon anders sein und dann liegt das gute Linnen im Dreck.
Nur mit dem Vorzeichen muss man dann und wann aufpassen. Das kann man aber recht gut vermeiden, indem man -soweit möglich- unsigned-Typen verwendet. Oft kann man das sogar ohne Einschränkung machen.
Das haut aber meistens gegen die Deklarationen der Lib-C. Aber diese Deklarationen sollten auch mal so langsam angepaßt werden, das ist einfach nicht mehr zeitgemäß, nur mit char zu arbeiten. ASCII alleine reicht irgendwie nicht so wirklich ;-)
Sag ich doch: Wenn ein Vorzeichen ins Spiel kommt, muss man aufpassen. Aber das Vorzeichen ist eh nur Illusion: Ein gesetztes MSB,
Das Vorzeichen muß nicht unbedingt im MSB sein, das kann auch woanders und sogar gleich etwas ganz anderes sein.
Aber wie Du schon ganz richtig sagst...
das nur bei ein paar wenigen Operationen (>>-Operator, Ausgabe über eine der printf-Funktionen) überhaupt eine besondere Rolle spielt.
... soviele Fallen gibt es da nicht und die sind auch alle bekannt.
Und wer schreibt auch heutzutage noch für 'ne alte Vax oder 'ne PDP-11 o.ä. ;-)
Dein Auszug aus dem Standard beschreibt nur, was der Compiler daraus machen soll, wenn der Programmierer seine Variablen *nicht* explizit initialisiert.
Ich hatte eigentlich _beides_ kopiert?
Ah, Mißverständnis, wie ich hier unten sehe, sorry.
Ich meine mich aber zu erinnern, dass es irgendwo eine Regel gibt, nach der strukturierte Datentypen (und dazu gehören ja auch Arrays) mit Nullwerten aufgefüllt werden, wenn sie *nur teilweise* initialisiert werden, so wie z.B.
unsigned long pp[40] = { 2, 1, 0 };
Dazu habe ich nichts gefunden, zumindest nichts deutliches, scheint implementationsabhängig zu sein.
char string[ANZ+1];
alleine reicht dafür nicht.Das hab ich auch nicht gesagt. Diese Zeile ist ja auch nur eine Deklaration, keine Initialisierung.
Wer beckmessert jetzt hier? ;-)
Deshalb sollte der Anfänger Standard-C lernen und kein Windows-C, DOS-C, Linux-C oder was weiß ich alles.
Richtig. Die Spezialisierung auf eine bestimmte Plattform kommt erfahrungsgemäß von ganz allein im Lauf der Zeit.
Na, ich hoffe doch nicht!
Lieber nix von allem wissen, als alles über nix ;-)
so short
Christoph Zurnieden
gudn tach!
Auch wenn das wahrscheinlich mal wieder kein Schwein liest ;-)
*grunz* ;-)
{
Geschweifte Klammern auf eine neue Zeile zu setzen kann zu Unfällen führen. War erst neulich hier im Forum.
oh, das interessiert mich. wo war das?
prost
seth
Hi Leute
Geschweifte Klammern auf eine neue Zeile zu setzen kann zu Unfällen führen. War erst neulich hier im Forum.
oh, das interessiert mich. wo war das?
Das möchte ich auch gerne wissen. Ich habe mir das nämlich der Übersicht halber so für Funktionen und Klassen angewöhnt (bei darin enthaltenen Codeblöcken jedoch nicht) und war immer sehr zufrieden damit. Kann jemand der dabei war kurz den Link posten?
FG
Tom2
gudn tach!
Geschweifte Klammern auf eine neue Zeile zu setzen kann zu Unfällen führen. War erst neulich hier im Forum.
oh, das interessiert mich. wo war das?
Das möchte ich auch gerne wissen. Ich habe mir das nämlich der Übersicht halber so für Funktionen und Klassen angewöhnt (bei darin enthaltenen Codeblöcken jedoch nicht) und war immer sehr zufrieden damit. Kann jemand der dabei war kurz den Link posten?
ach soooo, es ging wohl um http://forum.de.selfhtml.org/archiv/2004/12/t96004/. aber da ist ja dem programmierer ein fehler unterlaufen wie er auch bei if(i=1) (= statt ==) haette passieren koennen. das zaehlt imho nicht.
es bleibt also dabei, jeder setzt klammern wie es ihm passt. die einen finden
foo(bar){
baz
}
uebersichtlicher, besser und toller; die anderen eben
foo(bar)
{
baz
}
und andere wieder
foo (bar) {
baz
}
und ganz andere
foo(bar)
{
baz
}
wieder andere (Kernighan & Ritchie) mixen die schreibweisen... usw. usf.
und keiner hat recht oder unrecht, auch wenn ueber K&R anderes behauptet wird. ;-)
prost
seth
Hi,
ach soooo, es ging wohl um http://forum.de.selfhtml.org/archiv/2004/12/t96004/.
Ja, genau den, Danke.
aber da ist ja dem programmierer ein fehler unterlaufen wie er auch bei if(i=1) (= statt ==) haette passieren koennen. das zaehlt imho nicht.
Ja, dem Programmierer ist ein Fehler unterlaufen. Bei anderer Formatierung hätten diese Fehler aber keine Auswirkung gehabt. Wieso also zählt das nicht?
"Es schmeckt mir sorum besser!" ist ein gutes Argument für einen Restaurantgast, aber nicht für einen Programmierer. Normalerweise sollte der doch in der Lage sein, seine Entscheidungen objektiv zu begründen, oder nicht? ;-)
so short
Christoph Zurnieden
gudn tach Christoph Zurnieden!
aber da ist ja dem programmierer ein fehler unterlaufen wie er auch bei if(i=1) (= statt ==) haette passieren koennen. das zaehlt imho nicht.
Ja, dem Programmierer ist ein Fehler unterlaufen. Bei anderer Formatierung hätten diese Fehler aber keine Auswirkung gehabt.
doch, denn auch
foreach($dateiinhalt as $login);{
fuehrt zum gleichen ergebnis.
Wieso also zählt das nicht?
sonst koennte man auch sagen, dass turbo pascal besser sei, weil man da das vergleichsproblem if(i=1) (= statt ==) nicht hat.
es hat eben alles seine vor- und nachteile.
"Es schmeckt mir sorum besser!" ist ein gutes Argument für einen Restaurantgast, aber nicht für einen Programmierer. Normalerweise sollte der doch in der Lage sein, seine Entscheidungen objektiv zu begründen, oder nicht? ;-)
falls die ironie nur auf den letzten aber nicht den vorletzten satz bezogen war: doch, das argument des besser schmeckens gibt es auch bei der code-formatierung. so wie dem einen pilze schmecken und der andere sich schon beim anblick uebergeben koennte, so finden die einen eben einen absatz nach der klammer der uebersicht dienend und die anderen eben gerade nicht. (u.a. hat es auch etwas damit zu tun, mit welchem editor man code editiert.)
deshalb gibt es diesbezueglich ja auch mehrere und nicht bloss einen standard.
das indent-manual sagt z.b.:
"There are several common styles of C code, including the GNU style, the
Kernighan & Ritchie style, and the original Berkeley style."
astyle hat z.b. folgende fertigen styles:
--style=ansi
ANSI style formatting/indenting.
--style=kr
Kernighan&Ritchie style formatting/indenting.
--style=gnu
GNU style formatting/indenting.
--style=java
Java mode, with standard java style formatting/indenting.
--style=linux
Linux mode (i.e. 8 spaces per indent, break definition-block
brackets but attach command-block brackets.
und das alles bringt mir kaum was, denn --style=seth fehlt noch immer. ;-)
prost
seth
Hi,
Ja, dem Programmierer ist ein Fehler unterlaufen. Bei anderer Formatierung hätten diese Fehler aber keine Auswirkung gehabt.
doch, denn auch
foreach($dateiinhalt as $login);{
fuehrt zum gleichen ergebnis.
Das ist eher selten, da "Semikolon am Ende" drin ist. Sonst wäre das ja auch ursprünglich gar nicht passiert, wenn sich besagtes "Semikolon am Ende" nicht schon zum Reflex ausgebildet hätte.
Hey, _Du_ hast das Beckmesser zuerst blank gezogen! ;-)
Wieso also zählt das nicht?
sonst koennte man auch sagen, dass turbo pascal besser sei, weil man da das vergleichsproblem if(i=1) (= statt ==) nicht hat.
Die Syntax verschiedener Sprachen bergen ihre Fallen, ja.
deshalb gibt es diesbezueglich ja auch mehrere und nicht bloss einen standard.
Es gibt genau: gar keinen.
astyle hat z.b. folgende fertigen styles:
[...]
und das alles bringt mir kaum was, denn --style=seth fehlt noch immer. ;-)
Im Paket ist eine Datei namens "astyle.html", da steht alles nötige drin. Wenn Du da hintergestiegen bist, kannst Du in bool parseOption(ASFormatter &formatter, const string &arg, const string &errorInfo) in astyle_main.cpp eine Option namens "style=seth" einbauen. Code ist an o.a. Stelle fast schon selbsterklärend.
Wenn Du mir sagst was Du möchtest _und_ wie ich im westlichem Ruhrgebiet an originales tchechisches Bier herankomme (_nicht_ diese Exportplörre!), dann mache ich Dir das sogar noch höchstselbst.
so short
Christoph Zurnieden
gudn tach!
puh, noch mal glueck gehabt, dass der thread noch nicht ins archiv gewandert ist. ich versuche naemlich schon seit tagen, mit meinem rechner von nicht-zu-hause ins netz zu gehen. klappt aber alles nedd so wie's soll. naja, wenigstens gibt es hier noch andere rechner mit internetzugang...
Hi,
Ja, dem Programmierer ist ein Fehler unterlaufen. Bei anderer Formatierung hätten diese Fehler aber keine Auswirkung gehabt.
doch, denn auch
foreach($dateiinhalt as $login);{
fuehrt zum gleichen ergebnis.Das ist eher selten, da "Semikolon am Ende" drin ist. Sonst wäre das ja auch ursprünglich gar nicht passiert, wenn sich besagtes "Semikolon am Ende" nicht schon zum Reflex ausgebildet hätte.
Hey, _Du_ hast das Beckmesser zuerst blank gezogen! ;-)
hmm, musste erstmal google fragen, was "beckermesser" bedeutet.
astyle hat z.b. folgende fertigen styles:
[...]
und das alles bringt mir kaum was, denn --style=seth fehlt noch immer. ;-)Im Paket ist eine Datei namens "astyle.html", da steht alles nötige drin. Wenn Du da hintergestiegen bist, kannst Du in bool parseOption(ASFormatter &formatter, const string &arg, const string &errorInfo) in astyle_main.cpp eine Option namens "style=seth" einbauen. Code ist an o.a. Stelle fast schon selbsterklärend.
Wenn Du mir sagst was Du möchtest
tja, wenn ich das wuesste, haette ich mir schon selbst ein tool dafuer gebastelt. aber es kommt immer auf verschiedene sachen an, wie ich einen code gerne haette. je nach kontext ist mir mal
switch foo
case bar:{quux} break;
case baz:{quuux} break;
und mal
switch foo
case bar:{
quux
}break;
case baz:{
quuux
}break;
lieber.
_und_ wie ich im westlichem Ruhrgebiet an originales tchechisches Bier herankomme (_nicht_ diese Exportplörre!)
was meinst du mit "exportploerre"? sobald du ein tschechisches bier hier kaufst, wuerde jeder tscheche sagen, dass das bier exportiert worden sei. ;-)
allgemein ist es jedenfalls wohl am geschicktesten, eine brauerei direkt anzuschreiben und zu fragen, wo man in seinem umkreis deren bier kaufen kann oder an wen (z.b. getraenkegrosshandel) man sich wenden muss.
zudem kann es nuetzlich sein in foren/boards, die sich mit bier beschaeftigen, zu fragen, ob einem jemand tipps geben koenne.
dann mache ich Dir das sogar noch höchstselbst.
wie gesagt: da ich leider nicht mal genau spezifizieren kann, wie mir code am besten gefaellt, waere das zum scheitern verurteilt. aber ich werde mir, wenn ich mal wieder mehr zeit hab, die src-files von astyle anschauen.
prost
seth
Hi,
Hey, _Du_ hast das Beckmesser zuerst blank gezogen! ;-)
hmm, musste erstmal google fragen, was "beckermesser" bedeutet.
Ja, gehört das denn nicht zur "teutsch'n Leitkultur"? >;->
Wenn Du mir sagst was Du möchtest
tja, wenn ich das wuesste, haette ich mir schon selbst ein tool dafuer gebastelt. aber es kommt immer auf verschiedene sachen an, wie ich einen code gerne haette. je nach kontext ist mir mal
Dann versuch doch mal den Kontext näher zu definieren.
_und_ wie ich im westlichem Ruhrgebiet an originales tchechisches Bier herankomme (_nicht_ diese Exportplörre!)
was meinst du mit "exportploerre"? sobald du ein tschechisches bier hier kaufst, wuerde jeder tscheche sagen, dass das bier exportiert worden sei. ;-)
Ah, ich sehe, Du hast den Begriff "Beckmesser" gut verstanden ;-)
Nein, ich habe festgestellt, das manche Marken für den deutschen Markt hergerichtet werden. Dies betrift aber nur die großen Marken, die kleinen haben dafür nicht die Möglichkeiten. Leider sind diese kleinen Marken hier natürlich nicht zu finden und da Du hier mit einer Bierdatenbank wirbst dachte ich mir: frag' doch einfach mal ganz unverblümt ;-)
so short
Christoph Zurnieden