Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-09-01 Diskussionsfäden Ernst May-Jung

Hallo,

Einspruch:

Am 29.08.2010 11:06, schrieb Bernhard Guillon:

 Mit dem Klassiker Programmieren in C von Kernighan/Ritchie kann man 
 als Anfänger wahrscheinlich nicht ganz so viel anfangen. 

Genau mit dem Buch habe ich C Programmieren gelernt. Ich hatte davor
Kenntnisse in Logo und Basic.

Das Buch fängt bei Hello World an und lässt sich von Anfang bis Ende
durcharbeiten.


Objektorientierte Programmierung in C++ wäre dann der nächste Schritt.

Gruß
 Ernst
--

PUG - Penguin User Group Wiesbaden - http://www.pug.org


Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-08-31 Diskussionsfäden Bernhard Guillon

On 31.08.2010 12:59, lano wrote:


Zum Schluss, punkte 3 und 4, musste ich noch recht kämpfen, denn einen 
string zusammensetzen ist in c anscheint wieder was ganz anderes als 
in perl.

mit url = server + datei; funktioniert es jedenfalls nicht.
ich bewerkstellige das nun so:

char url[300];
strcpy(url, quotenpage);
strcat(url, ?user=);
strcat(url, user);
strcat(url, channel=);
strcat(url, channel);


Ja weil C keine Strings kennt. Wenn du + bei Pointern verwendest 
rechnest du Adressen zusammen. Warscheinlich kommt dabei keine 
brauchbare heraus :)


Du solltest den Speicher hier umbedingt ausrechnen und mit malloc 
reservieren oder aber überprüfen ob der Puffer groß genug ist um beide 
Strings aufzunehmen. Wenn die beiden Strings zusammen größer als 300 
werden hast du sonst einen Buffer Overflow. strnFOO ist dafür besser 
geeignet, da z.B. strcpy einfach so lange in den Speicher schreibt bis 
ein Terminierungszeichen \0 kommt strncpy aber nur maximal so lange wie 
du angibst.
jetzt müssen nur noch einige feinheiten rein, da bin ich aber erstmal 
am überlegen wie es am cleversten wäre.
die datei vom server holen und die url an den server senden mache ich 
mit ein und der selben funktion.


HTTP_downloadFile( quotenserver, 80, url, /dev/null, 0, 1);


die Funktion macht im Moment allerdings nix anderes als wget mit den 
ensprechenden parametern aufzurufen. Interessant wäre es ob es zb. mit 
deiner Funktion Ressourcen schonender wäre.

(im gegensatz zum shell script frist das c progämmchen so gut wie nix)
Allerdings wollt ich
a) weder das rad ständig neu erfinden
b) sollte das programm so klein wie möglich sein, mir stehen nur 556kb 
flash zur verfügung, von denen ich möglichst so wenig wie möglich 
benutzen sollte.

im moment ist das programm ca 13 kb groß gestiped sinds nur noch 5,8kb :)




Libcurl ist zwar schon ein bisschen größer als alles selber zu schreiben 
aber dafür sollte es machen was du willst. Du kannst es statisch linken 
dann hast du es beim cross compiling einfacher. Was für eine Toolchain 
verwendest du für die Dreambox? Das mit dem wget ist sonst auch nicht so 
schlimm.


Gruß
Bernhard
--

PUG - Penguin User Group Wiesbaden - http://www.pug.org


Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-08-30 Diskussionsfäden Nathanael Schweers
On Mon, 30 Aug 2010 13:09:43 +0200
lano mail4l...@web.de wrote:

 Nathanael Schweers schrieb:
  In perl ist ein string ein scalar, in C nicht. 
  C kennt keinen eigenen typ für strings, sondern strings sind einfach
  nur Arrays (listen) von chars. Um das Ende zu markieren bekommt das
  letzte Element den wert 0 (== '\0'). Das ist nicht das Zeichen '0'!
  Wenn du nun nen string hast und return Text; schreibst ist damit die
  Adresse des ersten Elements des Arrays gemeint. Darum brauchst du
  auch einen char * als Rückgabewert, sonst bekommst du bloß ein
  Zeichen (und einen Kompilerfehler). 
  Da du kein Array zurückgeben kannst, sondern nur die Anfangsadresse
  dessen musst du auch vorher das Array an einer Stelle ablegen die
  beim verlassen der Funktion nicht ungültig wird. Alle lokalen
  Variablen werden ja schließlich wieder freigegeben - und damit eben
  auch die Variable Text. Ich schreib mal ein kleines bisschen code
  hier hin (und verzichte mal um die Verwirrung niedrig zu halten
  absichtlich auf Fehlerbehandlung):
 
  char *buffer=malloc(BUFSIZE+1); /* +1 für das 0-byte am
  ende */
 

 ich hab nun folgendes was auch funktioniert:
 
 char *read_file(char *file_name) {
 
 FILE *datei;
 char *buffer=malloc(BUFSIZE+1);
 buffer[0]=0;
 
 if( (datei=fopen(file_name,r)) == NULL) {
 fprintf(stderr,Kann %s nicht oeffnen\n,file_name);
 return EXIT_FAILURE;
 }
 
 fgets(buffer,BUFSIZE,datei);
 
 return buffer;
 }
 
 geh ich jetzt recht in der annahme das ein free(buffer) nach dem 
 aufrufen der funktion den speicher dann wieder frei gibt?
 ca so:
 
 printf(Kanal: %s, read_file(/tmp/currentChannel));
 free(buffer);
 
Ja, genau so ist das richtig. 
Gruß, Nathanael

 
 
 -Sven-
 
 --
 
 PUG - Penguin User Group Wiesbaden - http://www.pug.org

--

PUG - Penguin User Group Wiesbaden - http://www.pug.org


Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-08-30 Diskussionsfäden Nathanael Schweers
On Mon, 30 Aug 2010 14:36:09 +0200
lano mail4l...@web.de wrote:

 Moin,
 könnt mir nochmal jemand erklärend helfen, ich dreh hier auf kurz oder
 lang durch.
 Da denkste da haste was verstanden, nix ist, und try`n error nervt
 langsam.
 
 *---net.c--*
 #include stdio.h
 #include string.h
 #include net/if.h
 #include netinet/in.h
 #include sys/ioctl.h
 
 #define BUFSIZE 60
 
 unsigned char *get_mac(void) {
 int sd;
 struct ifreq ifr;
 char *buffer=malloc(BUFSIZE+1);
 buffer[0]=0;
 
 
 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
 if (sd  0) {
 perror(socket);
 exit(1);
 }
 
 strncpy(ifr.ifr_name, eth0, IFNAMSIZ);
 
 if (ioctl(sd, SIOCGIFHWADDR, ifr)  0) {
 perror(ioctl SIOCGIFHWADDR);
 exit(1);
 }
 
 buffer = (unsigned char *) ifr.ifr_hwaddr.sa_data;
 
 //printf(%02x:%02x:%02x:%02x:%02x:%02x\n,
 buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]);
 *--- Wenn ich printf auskommentiere wird die mac auch
 angezeigt--* return buffer;
 }
 
 *--net.h--*
 #ifndef __NET_H__
 #define __NET_H__
 
 unsigned char *get_mac(void);
 
 #endif
 
 *---main.c--*
 #include net.h
 char *buffer;
 int main(int argc, char **argv) {
 printf(Mac: %s\n, get_mac());
 free(buffer);
 return 0;
 }
 
 
 
 Was mach ich da wieder fürn blödsinn?
 Buch lesen ist ja ganz nett, aber nen buch kann ich keine fragen
 stellen. Das deprimiert dermaßen, hab langsam echt kein bock mehr.
 
 trotzdem vielen dank für eure hilfe und die bemühungen.
 
 -Sven- --- der sich jetzt erstmal abreagieren muss
Ich hab ehrlich gesagt Sowas noch nie gemacht, aber ... was genau ist
denn da dein Problem?

Gruß, Nathanael
--

PUG - Penguin User Group Wiesbaden - http://www.pug.org


Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-08-30 Diskussionsfäden Bernhard Guillon

On 30.08.2010 18:44, lano wrote:
Ok, soweit kann ich dir folgen. Jetzt würde ich denken, schreibe ich 
struct ifreq ifr;

außerhalb der funktion dann wäre es ja global. tuts aber auch nicht.

Globale Variablen sind an sich keine gute Idee...
Hier etwas das bei deinem Beispiel besser geeignet ist:
Da malloc Speicher vom Heap reserviert ist er nach dem Funktionsaufruf 
noch vorhanden. Du kannst die MAC in den von dir reservierten 
Speicherbereich schreiben/kopieren. Meistens macht man aber call by 
reference. Deswegen meinte ich ja es ist eine gute Idee die zwei 
Varianten call by reference und call by value mal genauer zu untersuchen :)



Laut Buch und google handelt es sich wohl um eine Struktur.

ifr.ifr_hwaddr.sa_data;

müsste dann nicht irgendwo etwas wie:

struct ifreq  {
  char ifr_hwaddr;
};

struct ifreq ifr;

stehn? aber was hatt es dann mit sa_data auf sich?

Such mal in den Includes, die du angegeben hast danach dort sind die 
ganzen Sachen deklariert.





*g* ich hab schon eine woche gebraucht bis Hallo Welt funktioniert hat.
Eigendlich geht es insgesamt nur darum
1. eine datei vom einem http-server laden
2. das was in der datei steht in eine variable stecken
2. die mac in eine variable bekommen
3. daraus eine url basteln
4. die url an den http-server senden

das ganze hab ich schon mit einem shell script getestet, dafür hab ich 
15min gebraucht.
problem, das script frist zuviel power. Also hab ich gedacht, 
versuchstes mal mit c.
Eigentlich hatt ich gedacht wäre das schon eine einfache sache, das es 
so kommt konnt ich ja nicht ahnen.


Warscheinlich hast du für das Shellskript curl verwendet? Wenn ja 
solltest du dich recht schnell mit libcurl [1] zurecht finden. Hier ist 
ein Beispiel dazu [2].


Was genau braucht bei dem Skript eigentlich so viel Power? Von der 
Beschreibung her sollte es länger dauern die Seite vom Server zu 
bekommen bzw die da hin zu schicken. Das wird mit C auch nicht 
schneller. Vieleicht kann man auch nur einen speziellen Teil des 
Skriptes optimieren, statt das ganze in C zu schreiben.


Gruß
Bernhard

1 http://curl.haxx.se/libcurl/
2 http://curl.haxx.se/libcurl/c/simple.html
--

PUG - Penguin User Group Wiesbaden - http://www.pug.org


Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-08-29 Diskussionsfäden Bernhard Guillon

On 29.08.2010 02:59, lano wrote:


nun möchte ich von einem weiteren main.c die funktion print_hallo 
nutzen.

Wie funktioniert das.
Ich hab schon 2 nächte nach try'n'error halb google durch, aber ich komm
nicht da hinter.
Könnte mir da jemand freundlicher weise erklären wie das funktioniert,
aber bitte ganz ganz einfach. Ein ganz ganz einfaches beispiel wäre nett
von dem ich mir das prinzip abschaun kann und dann darauf aufbaun.




/*--- main.c */
#include net.h

int main() {
print_hallo();
return 0;
}

/*net.h*/
/*wenn noch nicht definiert
 *wichtig da dies nur einmal Aufgerufen werden darf
 */
#ifndef NET_H //
#define NET_H // definiere
int print_hallo(); //Prototyp von deiner Funktion
#endif //ende der Bedingung


/*--- net.c */
#include stdio.h
#include stdlib.h

#include net.h
int print_hallo() {
printf(Hallo Welt\n);
return 0;
}

/*
Die main darf es nur einmal geben deswegen ist sie hier auskommentiert ;)
int main() {
print_hallo();
return 0;
}
*/

Compilieren mit:
gcc -o net main.c net.c


Wenn was unklar ist sag bescheid.

Gruß
Bernhard
--

PUG - Penguin User Group Wiesbaden - http://www.pug.org


Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-08-29 Diskussionsfäden Bernhard Guillon

On 29.08.2010 10:58, Bernhard Guillon wrote:

On 29.08.2010 02:59, lano wrote:


nun möchte ich von einem weiteren main.c die funktion print_hallo 
nutzen.

Wie funktioniert das.
Ich hab schon 2 nächte nach try'n'error halb google durch, aber ich komm
nicht da hinter.


Ach ja ein gutes, preiswertes Anfängerbuch das sich nicht an 
Informatiker richtet ist C Programieren von Anfang an vom rororo 
Verlag. Ein recht gutes Buch das man auch online ansehen kann ist C von 
A bis Z [1]


Mit dem Klassiker Programmieren in C von Kernighan/Ritchie kann man 
als Anfänger wahrscheinlich nicht ganz so viel anfangen.


Gruß
Bernhard

1 http://openbook.galileocomputing.de/c_von_a_bis_z/
--

PUG - Penguin User Group Wiesbaden - http://www.pug.org


Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-08-29 Diskussionsfäden Nathanael Schweers
On Sun, 29 Aug 2010 13:06:02 +0200
lano mail4l...@web.de wrote:

 Bernhard Guillon schrieb:
  Wenn was unklar ist sag bescheid.
 bescheid.
 
 Ich wollt nun, nachdem das mit hallo welt so gut geklappt hat eine
 datei auslesen.
 google an und ein beispiel genommen. wieder eine extra datei genommen 
 file.c und file.h
 
 *---file.h---*
 #ifndef FILE_H //
 #define FILE_H // definiere
 
 
 char read_file(char *file_name); //Prototyp von deiner Funktion
 
 
 #endif //ende der Bedingung
 
 
 *file.c*
 #include stdio.h
 #include stdlib.h
 
 #include file.h
 
 int f;
/* du brauchst kein int, sondern ein (FILE *). int ist für file
deskriptoren, fgets und fopen aber benutzen zeiger auf FILE (ist ein
wrapper um filedeskriptoren, da ist sogar ein puffer mit drin). */
 char Text[600];
 
 char read_file(char *file_name) {
/* du willst vermutlich nicht char, sondern char * zurückgeben*/
 f = fopen(file_name,r);
 while( fgets(Text, sizeof(Text), f) !=0 )
/* was machst du da? das sieht so aus als würdest du solange fgets !=0
zurückgibt die datei schließen, und das ganze auch noch in den immer
gleichen puffer schreiben (die alten daten gehen also verloren). */
 fclose(file_name);
 return Text;
/* return Text; wird vermutlich nichtmal übersetzt, da von (char *)
nach char konvertiert wird. */
 }
 
 *---main.c---*
 #include stdio.h
 #include plugin.h
 #include http.h // HTTP Client
 #include file.h // Liest eine Datei
 
 char channel[30];
 
 // Starten des Plugins
 void plugin_exec(PluginParam *par) {
 
 // Aktuellen Kanal holen und speichern
 HTTP_downloadFile(localhost, 80, /control/getonidsid, 
 /tmp/currentChannel, 0, 1);
 //read_file(/tmp/currentChannel);
 
 printf(Kanal: %c\n, read_file(/tmp/currentChannel));
 
 
 return;
 }
 
 
 *ENDE*
 
 Das mit HTTP_downloadFile funktioniert wunderbar, also wurde ich ein 
 wenig übermütig, datei lesen klappt nicht.
 bei der printf Anweisung, wofür ist %s %c %l und was weis ich was es
 da noch gibt, habs erst mit %s versucht, dann hab ich gedacht ok ist
 ja nen char versuchstes mit %c :)
 
 meine mal gelesen zu haben das void nix zurück gibt, int ne zahl, und 
 char nen zeichen.
siehe man 3 printf oder man 3p printf dazu.
%s sagt printf dass hier ein string reinkommt. %c ein zeichen, %l steht
für long. Davon gibt's ne menge mehr, z.b. auch für floating point. 
 
 Perl ist wesendlich einfacher :)
Perl ist auf ne andere art obskur ;)
Aber stimmt schon, C ist für neulinge nicht gerade einfach, und ich
finde dass die standard bibliothek es einem neuling nicht gerade
einfacher macht. 
 
 -Sven-

Ich hoffe dass Ich dich nicht zu sehr verwirrt habe. 

Gruß, Nathanael

--

PUG - Penguin User Group Wiesbaden - http://www.pug.org


Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-08-29 Diskussionsfäden Nathanael Schweers
Etwas im vorraus (viele wissen das leider nicht: mit open(2) meine ich
man 2 open)

Ich versuch nochmal den sachverhalt zu erklären:
fgets und Konsorten benutzen nicht den filedeskriptor (fd) den du z.b.
von open(2) bekommst, sondern einen Zeiger (daher der '*') auf eine
Struktur namens FILE. Diese kapselt u.a. den fd und einen Puffer. Nun
kannst du mit fgets in einen Speicherbereich schreiben lassen. 
fgets nimmt dafür zunächst den Puffer (char*), in deinem Fall heißt der
'Text', dann die Anzahl der bytes die gelesen werden sollen (das hast
du richtig), und dann einen Zeiger auf die datei (FILE*). 

Bei der Rückgabe des strings musst du leider auch noch etwas beachten:
Du hast den Puffer lokal, also auf dem Stack deklariert. Das heißt dass
der Speicher nachdem die Funkion zurückgekehrt ist ungültig ist. Also
musst du den speicher mit malloc(3) allokieren und nachdem du den
string nicht mehr brauchst (das wird außerhalb der Funktion sein) den
wieder mit free(3) freigeben. 

Ich kann übrigens das Buch 'C von A bis Z' welches online gratis
gelesen werden kann sehr empfehlen. 

Gruß, Nathanael
--

PUG - Penguin User Group Wiesbaden - http://www.pug.org


Re: [PUG] OT: c Programmierung für ganz anfängli che Anfänger

2010-08-29 Diskussionsfäden Nathanael Schweers
On Sun, 29 Aug 2010 14:59:26 +0200
lano mail4l...@web.de wrote:

 Nathanael Schweers schrieb:
  int f;
  
  /* du brauchst kein int, sondern ein (FILE *). int ist für file
  deskriptoren, fgets und fopen aber benutzen zeiger auf FILE (ist ein
  wrapper um filedeskriptoren, da ist sogar ein puffer mit drin). */

 Ah ja, macht sinn. Das mit * zeigt dann auf eine adresse wo die daten 
 dann abgelegt sind, wobei mich bei einer variablen die adresse ja
 nicht interessiert.
 in perl hätt ich ja ein filehandle, von daher versteh ich schon warum 
 int völlig falsch ist.
 Hab ich das halbwegs richtig verstanden?
Denke ich schon, ja. 
  char Text[600];
 
  char read_file(char *file_name) {
  
  /* du willst vermutlich nicht char, sondern char * zurückgeben*/

 hier im grunde das selbe, das was die funktion zurück gibt wird in
 der adresse xy gespeichert, ich will also nur die adresse wissen wo
 ich dann die daten finde. warum das so ist ist mir zwar völlig
 unklar, ich nehms aber mal so hin.
  f = fopen(file_name,r);
  while( fgets(Text, sizeof(Text), f) !=0 )
  
  /* was machst du da? das sieht so aus als würdest du solange
  fgets !=0 zurückgibt die datei schließen, und das ganze auch noch
  in den immer gleichen puffer schreiben (die alten daten gehen also
  verloren). */ 
 Mein got ja, jetzt raff ichs aber erst, das fclose(file_name) gehört
 ja noch zur while schleife.
 ; hab ich völlig übersehn.
  fclose(file_name);
  return Text;
  
  /* return Text; wird vermutlich nichtmal übersetzt, da von (char *)
  nach char konvertiert wird. */

 Das versteh ich nun nicht mehr, mal angenommen ich scheibe die daten
 in Text, geb ich dann mit return Text nicht die daten wieder aus?
 müsst ich *Text zurück geben, also die adresse wo die daten liegen?
 
 in perl kann ich einfach:
 $text = hallo;
 return $text;
In perl ist ein string ein scalar, in C nicht. 
C kennt keinen eigenen typ für strings, sondern strings sind einfach
nur Arrays (listen) von chars. Um das Ende zu markieren bekommt das
letzte Element den wert 0 (== '\0'). Das ist nicht das Zeichen '0'!
Wenn du nun nen string hast und return Text; schreibst ist damit die
Adresse des ersten Elements des Arrays gemeint. Darum brauchst du auch
einen char * als Rückgabewert, sonst bekommst du bloß ein Zeichen (und
einen Kompilerfehler). 
Da du kein Array zurückgeben kannst, sondern nur die Anfangsadresse
dessen musst du auch vorher das Array an einer Stelle ablegen die beim
verlassen der Funktion nicht ungültig wird. Alle lokalen Variablen
werden ja schließlich wieder freigegeben - und damit eben auch die
Variable Text. Ich schreib mal ein kleines bisschen code hier hin (und
verzichte mal um die Verwirrung niedrig zu halten absichtlich auf
Fehlerbehandlung):

#include stdio.h
#include stdlib.h

#define BUFSIZE 600

char *read_file(char *filename) {
FILE *f=fopen(filename);
char *buffer=malloc(BUFSIZE+1); /* +1 für das 0-byte am ende */
buffer[0]=0; /*stringende an den anfang setzen, manche
Funktionen reagieren sonst komisch und schreiben nicht an den
Anfang*/
while(strlen(buffer)BUFSIZE) {
if(fgets(buffer+strlen(buffer),BUFSIZE-strlen(buffer),f)==0)
{
fclose(f);
return buffer;
}
}
fclose(f);
return buffer;
}

Ich bin mir nicht 100%ig sicher ob das richtig ist, ich hab fgets und
konsorten nicht viel benutzt und hab das grad schnell hingeklatscht. 
Falls also jemand einen Fehler findet darf er gerne korrigiert werden ;)
Aber wie gesagt, ich empfehle sehr dringend dazu ein Buch zu lesen. 

 
 machen, und die funktion gibt hallo zurück
  bei der printf Anweisung, wofür ist %s %c %l und was weis ich was
  es da noch gibt, habs erst mit %s versucht, dann hab ich gedacht
  ok ist ja nen char versuchstes mit %c :)
 
  
  siehe man 3 printf oder man 3p printf dazu.
  %s sagt printf dass hier ein string reinkommt. %c ein zeichen, %l
  steht für long. Davon gibt's ne menge mehr, z.b. auch für
  floating point. 
 Ok, hab ich kapiert.
  Perl ist wesendlich einfacher :)
  
  Perl ist auf ne andere art obskur ;)

 Hmm, ich komm da eigendlich gut mit zurecht.
  Aber stimmt schon, C ist für neulinge nicht gerade einfach, und ich
  finde dass die standard bibliothek es einem neuling nicht gerade
  einfacher macht.
 Ich hatte c mal in der berufsschule, ist schon 15 Jahre her, das sah 
 dann so aus das der Lehrer die Tafel in 5 min vollgeschrieben hat,
 ich war noch halbwegs interessiert aber all meine fragen konnt er mir
 nicht beantworten, weil das so ist war seine standard Antwort,
 warum konnt er mir in keinem fall erklären, nach 6 Monaten hab ich
 aufgegeben zu fragen und wie alle anderen gewartet bis ich den
 lösungszettel bekomme und hab einfach abgeschrieben.
  Ich hoffe dass Ich dich nicht zu sehr verwirrt habe. 
 

 Geht so ;) ich hoffe ihr habt was