[C]Webinhalt downloaden | Zeitfunktionen | sscanf()?

Chriss3000

Grünschnabel

Hallo an Alle erstmal.

Bin ein relativer Neuling auf dem Gebiet der Programmierung. Habe im Zuge einer Uni-Übung "Blut geleckt" und bin jetzt dabei meine Kenntnisse etwas am ausbauen.
Falls es jemanden interessieren sollte. Ich arbeite mit Windows XP und dem Bloodshed Dev-C++ Compiler.

Derzeit wollte ich ein kleines Projekt für den Clan in dem ich spiele realisieren.
Es geht darum in regelmäßigen Abständen eine Verbindung zu dem Webinterface eines Spieleservers aufzubauen und dann die auftauchende Seite / den html- Quelltext nach bestimmten Infos auszuwerten.

Zur Zeit habe ich 2 wesentliche Probleme (Kann sein, dass ich noch mehr habe! Aber die sind mir als Laie jetzt erstmal bewußt! ;-) ):


1) Ich würde inmein Programm gerne eineSchleife einbauen, die ale 30 sec automatisch das Haupprogramm startet und oben beschriebene Abfrage startet.
Sicher lässt sich das mit einer "While"-Schleife und einer "localtime"-Abfrage realisieren.

-> Gibt es da eine elegantere Lösung?
-> Kann ich verhindern, dass mein PC dann 95% der CPU-Kapazität darauf verwendet ständig die aktuelle Uhrzeit abzufragen?

2) Ich habe den Quelltext des Webinterfaces mal manuell runtergeladen (Kämpfe noch mit der Socket-Programmierung) und das Programm soweit vorbereitet, dass es die benötigten Daten bereits aus dem html-Quelltext extrahiert. Wennich nun die Zahlenanteile als Strings behandle geht alles wunderbar und die Ausgabe ist korrekt. transformiere ich die Zahlen aber eben in ein Zahlen Format, dann wird immer nur die Speicheradresse ausgegeben. Meine Vermutung geht in die Richtung, dass ich micht in der Pointer-Anwendung etwas verlaufen habe.:rolleyes:

Bei der Ausgabe auf dem Bildschirm ist es ja egalob ich einen String oder eine Zahl habe, aber das ganze soll dann später noch in eine Datenbank. Da weiß ich jetzt eben nicht, ob es da dann als Zahl eingeschrieben werden muss.


Variante Code 1: Das ist mal im wesentlichen mein Code-Aufbau (bissel abgespeckt)

Es wirdeuch sicher gleich auffallen, dass ich die Variable erst mit Leerzeichen beschrieben habe. Das liegt daran, das mir im Falle des "Nicknamens" Immer teile des ersten verarbeiteten Nicks mit ausgegeben wurden wenn der zweite verarbeitete Nickname weniger Zeichn hatte. Ist bei den Daethvielleicht nicht sooo relevant aber ich habs dann einfach mal übernommen.
Im html-Code siehts soaus,das immer vorund nach der für mich relevanten Informationen einige überflüssige Zeichen stehen, die leider bedingt durch die Funktionsweise von fscanf mit auf meine Variablegeschrieben werden.

Code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>

int main ()
{
char Death_falsch[100], Death_richtig[10];
char *Pointer1_Death, *Pointer2_Death;
double Death; 
char Death_richtig_richtig[10];
//double Death_richtig_richtig;
int Laenge_Death;


fscanf (Quelle, "%s", Death_falsch);                          
                          while (!feof(Quelle))
                                {   
                                /* Beschreiben der Variablen mit " "!*/ 
                                sprintf(Death_richtig, "          ")
                                size_t Laenge_Death_falsch;
                                
                                /*Bestimmen derLänge des eingelsenen Strings*/
                                Laenge_Death_falsch = strlen(Death_falsch);
                                
                                /*Pointer auf den Anfang des Speicherbereiches der Variablen*/
                                Pointer1_Death = Death_falsch;
                                
                                /*Pointer auf den Anfang des für mich interessanten Teils des abgelegten Strings */
                                Pointer2_Death = Pointer1_Death + 15 /*15 sind die Zeichen des html-Codes die vor dem für mich interessanten Bereich stehen*/;
                                
                                /*Bestimmen der Länge des für mich interessanten String-teils*/                     
                                Laenge_Death = Laenge_Death_falsch - 23/*23 sind die Zeichen des html-Codes die immer zuviel sind*/;
                                
                                /* Kopieren des für mich interessanten Teils*/
                                strncpy(Death_richtig, Pointer2_Death, Laenge_Death);
                                
                                /* Scannen des Strings da sscanf bis zum ersten Leerzeichen liest*/
                                /* So werden die überflüssigen oben auf die Variable geschriebenen Leerzeichen abgeschnitten.*/
                                sscanf(Death_richtig, "%s", Death_richtig_richtig);
                                
                                Ausgabe der Variablen als Zahl
                                printf ("Death_r=%s\n\n", Death_richtig_richtig);
                                printf ("Death=%s\n\n", Death_richtig);
                             

system ("PAUSE");
return 0;
}

Ergebnis: "Death_r = 0.00
Death 0.00" So soll es eigendlich auch aussehen.


Variante 2:

Code:
char *Pointer1_Death, *Pointer2_Death;
char Death_richtig_richtig[10];
double Death2;
...
                                sscanf(Death_richtig, "%s", Death_richtig_richtig);
                                sprintf(&Death2, "%d", Death_richtig_richtig);
                                
                                
                                Ausgabe der Variablen als String
                                printf ("Death2=%d\n\n", Death2);
                                printf ("Death=%s\n\n", Death_richtig);
                                ...

Ergebnis: "Death2 = 825831936
Death = 0.00"

Warscheinlich ist das Ganze auch nicht besonders elegant. Aber es stammt von mir selbst(*stolzsei ;-)) und es läuft soweit.

Sicher sind meine Fragen für Profis kein wirkliches Problem, aber ich steh da trotz Suchfunktionen schon wirklich wie ein "Ochs vorm Berg!".

Daher bin ich für jede Hilfe dankbar.

Gruß

Chris
 
Zuletzt bearbeitet:
AD 1) Programmunabhängig?
AD 2) Der Ausschnitt ist nicht vollständig.
Beschreib mal ohne diesen Code und dessen komischen Variablennamen, was du machen willst. Vllt. kann man das anderes eleganter (wesentlich!) und performanter Lösen.
 
Hallo,

1) Dafür kannst du irgendeine Schleife nehmen, gerne auch "while". Die Uhrzeitabfrage ist nicht nötig, da du ja nur eine Pause zwischen den Abfragen benötigst. Dafür reicht die Sleep()-Funktion. Die hat außerdem noch den Vorteil, dass während der Ausführung keine CPU-Last erzeugt wird.
Beispiel:
C++:
while( 1 )
{
    // Was zu tun ist
    
    Sleep(30000); // 30 Sek. Pause
}
2) Zum Herunterladen einer Datei kannst du die API-Funktion URLDownloadToFile() verwenden. Die Beschreibung dazu gibt's in der MSDN.

Zu deiner Konvertierung: sprintf() ist die falsche Funktion. Du benötigst atof() von Text zu Numerisch.

Gruß
MCoder
 
Zuletzt bearbeitet:
"Sleep" -Funktion)
Ja danke schonmal für den Tipp mit der Sleep-Funktion. Ist genau das was ich gebraucht hab. Zudem auch noch äußerst Bediener freundlich. ;-)

atof())
Das mit atof ()klappt auch. Obwohl ich etwas verwirrt bin, dass ich nicht einfach meine Zielvariable für atof() als "double" definieren und dann mit printf ("%d", Variable) ausgaben kann. Da kommt nur Mißt bei raus (Keine Nachkommastellen, falsche Werte).
Es geht nur wenn ich es als float definiere und dann als printf ("%6.2lf", Variable) ausgebe!?

URLDownloadToFile())
Mhh. Soweit ich sehe scheint das ja recht unkompliziert zu sein. Leider muss ich mich im Web-Interface aber erst mit "Benutzername" und "Passwort" einloggen bevor ich mein Ziel erreichen kann. Auf den ersten Blickscheint mir das mit oben genanntem Befehl nicht möglich zu sein.


In aller Kürze mal mein Vorhaben:

1) Verbinden zum Webinterface des Gameservers.
2) Herauslesen der für mich interessanten Informationen aus dem html-Code des Interfaces.
3) Speichern der Daten in eine mysql- Datenbank.


Mein derzeiteger Programmablauf:

1) Verbinden mit dem Webinterface des Game-Servers.
2) Download des html Codes.
3) Zwischenspeichern in einer Textdatei.
4) Einscannen der Textdatei. Bzw. der einzelnen, Leerzeichen-getrennten html-Code-Blöcke. Zunächst wirBlock für Blockeingescannt.
5) Da mir der Aufbau des html-codes bekannt ist, ist es mir möglich einen String zu definieren, der genau dem entspricht welcher in dem Code-Block vor dem für mich interessanten Abschnitt steht. Genau das gleiche für den Abschnitt nach dem für mich interessanten Inhalt.
6) Die eingescannten Code-Blöcke werden also mittels "strcmp" auf ihre Entsprechung mit den von mir definierten "Anfangs"- und "End" -Strings verglichen.
7) Sobald der Anfangsstring auftaucht liest das Programm die ganze folgende Zeile, wieder mittes "fscanf" in verschiedene Strings ein. Neben den für mich wichtigen Variablen werden hier auch einige "Müll"-Variablen beschrieben die ich dann einfach nicht weiter verwende.
8) Da fscanf ja immer bis zum nächst folgenden Leerzeichen einliest, wird leider auch noch html-Code mit eingelesen, der die mir wichtigen Daten einschließt.
Daher habe ich im Folgenden versucht über Pointer die überflüssigen Zeichen abzuschneiden.
9) Dazu habe ich nun ersteinmal die Länge des eingescannten Strings bestimmt. (" strlen")
10) Meinen ersten Pointer habe ich dann auf den Anfang des Speicherbereiches gesetzt auf dem mein Datenblock abgelegt wurde.
11) Dann habe ich den zweiten Pointer um die Anzahl Zeichen nach hinten verschoben, die an html-Code zuviel vor meinen Daten stehen.
12) Anschließend habe ich von der Länge meines Strings die Anzahl der überflüssigen html-Code Zeichen abgezogen.
13) Von den Daten die am Pointer2 abgelegt wurden habe ich dann ein "strncpy" mit der Länge von Punkt 12 durchgeführt.
-> Das Ergebnis ist ein String der nur die für mich interessanten Zeichen enthält.

14) Allerdings wurden an meine Aktuellen Daten immer noch die letzten Zeichen des Strings ausgegeben der vorher auf dem Zielort des "strncpy" von Punkt 13 gestanden hatte. Natürlich nur, wenn der zweite String kürzer als der erste war.
Daher habe ich die entsprechende Variable vorher mit Leerzeichen beschrieben und dannach mittels "sscanf" die überflüssigen Leerzeichen abgeschnitten.


15) Nun muss ich die Zeichen des Strings von Punkt 14 noch in ein Zahlen Format bringen und an mysql übergeben.

Punkte 4-14 klappen derzeit schonmal einwandtfrei.
 
Zuletzt bearbeitet:
Also, zu deinem Programmablauf:
(1) Warum speicherst du das vorher nochmal in eine Datei?

Dann zu deiner Stringterminierung:
'\0' kennzeichnet das Ende eines Strings. Vllt. bringt dich das zum entscheidenen Anstoß.
 
Aus dem Stehgreif habe ich so meine Schwierigkeiten mit dem automatischen Download/ dem automatischen Einlesen des html-Codes direkt aus dem Webinterface. :rolleyes:
Daher hab ichs mal erst manuell gespeichert um dennoch weiter probieren zu können.

Sobald sich mir erschloßen hat wie man das Zwischenspeichern umgehen kann bin ich gerne bereit darauf zu verzichten. :)


Dass das"\0" das String-/Zeilenende codiert kam mir schon zu Ohren hatte mir aber noch keine so großen Gedanken drüber gemacht.
Aber dann könnte ich mit nem dritten pointer ja einfach ein "\0" einfügen und mir so vermutlich das Beschreiben mit Leerzeichen, das scanf, sowie das strncpy sparen. Werde das morgen mal versuchen umzusetzen. *Danke* ;-)

Einen Befehl dem ich direkt sagen kann kopieren aus der Variable den Bereich von Zeichen 4 bis Zeichen gibt es soweit ich weiß ja nicht. Oder? DAs geht nur über das setzen verschiedener Pointer und/oder über diese "Token"-Geschichte (was aber bei mir ungünstig wäre, da ich nicht ausschließen kann, das Zeichen die im Html-Code vorkommen nicht auch in den für mich relevanten Teilen verwendet werden).
 
Zuletzt bearbeitet:
Das mit atof ()klappt auch. Obwohl ich etwas verwirrt bin, dass ich nicht einfach meine Zielvariable für atof() als "double" definieren und dann mit printf ("%d", Variable) ausgaben kann. Da kommt nur Mißt bei raus (Keine Nachkommastellen, falsche Werte).
Es geht nur wenn ich es als float definiere und dann als printf ("%6.2lf", Variable) ausgebe!?
Du kannst deine Zielvariable durchaus als double deklarieren. Die Ausgabe ist dann wieder ein anderes Thema. Schaue dir dazu nochmal die Formatspezifikationen von printf() an. Mit "%d" werden keine Gleitkommazahlen angezeigt. Dafür benötigst du "%f".

Leider muss ich mich im Web-Interface aber erst mit "Benutzername" und "Passwort" einloggen bevor ich mein Ziel erreichen kann. Auf den ersten Blickscheint mir das mit oben genanntem Befehl nicht möglich zu sein.
Das wird dann vermutlich etwas komplizierter werden. Mit welchen Protokoll läuft denn die Kommunikation, mit HTTP? Wie funktioniert die Anmeldung?

Gruß
MCoder
 
C++:
const char* my_string="Das ist ein Auto!";
char sample[5];
strncpy(my_string + 5, 4, sample);
... vllt hilft dir das ...
 
"Sorry" Erstmal für meine Abwesenheit. Musste wieder in meinen Studienort reisen.

@devDevil: Ich tue mich noch etwas schwer mit dem zuweisen/definieren direkt in der Funktion. Habs bisher immer so aufgeschrieben wie ich es gedacht hab. War dann einfach leichter umzusetzen. Aber ich seh ein das man sich da einiges an Code sparen kann. Sollte da wohl auch mal umdenken. ;-)

@MCoder: Stimmt. Habe "printf( "%d")" irgendwie falsch verinnerlicht.
Mit "%.2f" gehts deutlich besser. ;-)
Die URL beginnt mit "http://..." also sollte das dann wenn mich nicht alles täuscht auch das gesuchte Protokoll sein.
Die Anmeldung läuft so ab, dass ich auf die mir bekannte URL anwähle und dann ein seperates "Windows"-Benutzeranmeldungsfenster aufgeht.
Gefragt ist Benutzername und Passwort. Bestätiggt wird dann mit "Ok". Das Passwort kann gespeichert werden. Der Beschreibungstext beinhaltet folgende Zeilen:

"Warnung: Dieser Server fordert das Senden von Benutzernamen und Kennwort auf unsichere Art an (Basisauthentifizierung ohne eine sichere Verbindung)."

Wenn mich nicht alles täuscht habe ich bereits ein Socket erzeugt welches auf "http" basiert. Wie genau ich das jetzt getan habe kann ich mir zwar noch nicht genau erklären, aber die Codeschnippsel die ich aus dem Internet zusammengeschnitten habe geben mir schonmal die Meldung: "Socket wurde erfolgreich erzeugt." aus.

Nochmal ne Frage bezüglich dem "\0":

Wenn ich das dann mal beispielhaft mit möglichst wenig Code ausnutzen wollte, dann käme das hier dabei raus:
Code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
char *Pointer1, *Pointer2;
char string[20];

sprintf(string, "HalloWelt");

Pointer1 = string;
//Pointer2 = Pointer1 + 5;
//*Pointer2 ="\0";
*(Pointer1 + 5)= "\0";
sscanf (string, "%s", string);
printf("%s\n", string);
system("PAUSE");
return 0;    
}
Ich habe dabei mal versucht auf die Definition des Pointers2 zu verzischten und das ganze mittels einer Rechnung "*(Pointer1 + 5)=" zu realisieren. Allerdings wird mir jetzt ne Warnung ausgegeben ( "[Warning] assignment makes integer from pointer without a cast"). Diese Warnug bezieht sich auf eben dese Zeile. Das Ergebnis stimmt aber. Sollte ich dennoch lieber erst den zweiten Pointer definieren um diese Warnung weg zu bekommen?
 
Zuletzt bearbeitet:
Man man man du hastn Stil :D

C++:
char string[20];
char* ptr_begin = string;

sprintf(string, "HalloWelt");

*(ptr_begin + 5)= '\0';
Das wichtige dabei ist. '\0' (entspricht 0) ist ein Zeichen, d.h. ' und nicht " (für String).
 
Zurück