Liste durch loopen...

lano

Mitglied
Moin.

Ich hab ne Funktion die mehrere Argumente haben möchte.
Jetz wollt ich mir eigentlich sowas wie ne Tabelle anlegen und die dann durchgehen und an die Funktion übergeben.
Ich stolpere allerdings schon darüber wie ich die Tabelle quasi anlegen soll.
Ich war schon drauf und dran ne sqlite datenbank zu missbrauchen, was ich wieder verworfen hab.
Dann kam ich auf die idee nen array mit structs anzulegen und die sachen da rein zu packen.

Wie macht man sowas sinniger weise?

Ich hätte sowas wie:
Name; Hardware; Version; Build; OEM
Und davon so 200 Einträge.

Ideen ?
 

german

Aktives Mitglied
devCommunity-Experte
Willst du die Daten hart im Code haben, oder zur Laufzeit bauen? Und was meinst du mit durchgehen? Einfach Datensatz für Datensatz? Oder musst du filtern und suchen, oder womöglich einfügen und löschen?
 

lano

Mitglied
Willst du die Daten hart im Code haben, oder zur Laufzeit bauen?
Das ist mir relativ egal.

Und was meinst du mit durchgehen? Einfach Datensatz für Datensatz?
Ja ganz simple.

for (....

machwas(Name,HW,OEM,...)

}



Oder musst du filtern und suchen, oder womöglich einfügen und löschen?
Suchen wäre noch ne Möglichkeit. Dann wäre sowas wie getHWbyName() drin.
Ja sowas brauch ich.

Struct und verkettete Liste ?
 

german

Aktives Mitglied
devCommunity-Experte
Struct und verkettete Liste ?
Eine Möglichkeit.
Arrays lassen sich aber besser sortieren und somit besser durchsuchen. Gibt qsort und bsearch im stdlib.h. Für beide brauchst du genau eine Vergleichsfunktion (pro Member der Struktur für die du eine Suche brauchst) zu schreiben, die dann als Callback aufgerufen wird.
 

Lowl3v3l

Mitglied
devCommunity-Experte
Naja "verkettete Liste" ist der Oberbegriff, welche tatsächliche Struktur du verwendest hängt davon ab was du tun willst, und das effizient intern zu machen ist eine nichttriviale Aufgabe. Einer der Gründe warum ich immer C++ empfehle, wenn es keine zwingenden Gründe für reines C gibt(idR. sind die einzigen "zwingenden Gründe" : "Ich will unbedingt lernen das in reinem C selbst zu machen", "Jemand zwingt mich, C zu verwenden" und "Ich programmiere auf einer der ganz wenigen Plattformen, für die es keine C++-Compiler gibt").

Neben "klassischen" Listen gibt es auch noch Möglichkeiten wie doppelt verkettete Listen, die vorne und hinten anfügen können, und intern sortierte Strukturen die Inserts und Reads können, ohne im schlimmsten Fall über das ganze Ding iterieren zu müssen(für die meisten Fälle sind Rot-Schwarz-Bäume eine gute Idee). Was die optimale dynamische Datenstruktur ist hängt natürlich davon ab, was genau du tun willst, wie du es tun willst, und wie die Daten beschaffen sind : standardmäßig würde man in der Liste auch Pointerelemente halten, aber wenn die Struct klein genug ist, kann man sie auch komplett in den Listenknoten lagern. Dann ist die Frage mit der Allokation : allokziert man einzeln für jedes Element Speicher oder lieber gleich für einen Haufen und riskiert , etwas Speicher zu verschwenden? Verwendet man geleerten Speicher erneut?

Generell ist eine Struct, die ein Element einer einfach verketteten Liste darstellt sehr einfach : ein Pointer auf die Struktur die es repräsentiert, ein Pointer aufs Nächste Element oder NULL wenn es das letzt ist, und irgendwo im Programm einen Pointer auf das erste Element speichern. Bei doppelt verketteten Listen auch noch ein Pointer auf das vorhergehende Element.

So ein Paar Probleme auf die du vielleicht schauen willst, falls du es selbst implementieren willst, was definitiv eine Übung ist, die jeder C-Programmierer mal gemacht haben sollte.

mfg,
Lowl3v3l
 

lano

Mitglied
Arrays lassen sich aber besser sortieren
Gib mir mal nen Beispiel. Arrays hab ich ausgeschlossen. Ok, in Perl hab ich das so gemacht. Aber in c wüsste ich jetzt nicht wie.

Die Daten sind ca so:
"FRITZ!Box Fon","58","avm",
"FRITZ!Box Fon 5050","72","avm",
"FRITZ!Box Fon 5124","126","avm",
"FRITZ!Box Fon 5140","111","avm",
"FRITZ!Box 2031","113","avm",
"FRITZ!Box 2070","84","avm",
"FRITZ!Box 2110","133","avm",
"FRITZ!Box 2170","119","avm"

Neben "klassischen" Listen gibt es auch noch Möglichkeiten wie doppelt verkettete Listen
Das würde zu weit führen.
 

lano

Mitglied
Es geht eigentlich um das hier:
C:
/* juisck */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>

#define BUF 4096

char *extract(const char *const string, const char *const left, const char *const right) {
    char  *head;
    char  *tail;
    size_t length;
    char  *result;

    if ((string == NULL) || (left == NULL) || (right == NULL))
        return NULL;
    length = strlen(left);
    head   = strstr(string, left);
    if (head == NULL)
        return NULL;
    head += length;
    tail  = strstr(head, right);
    if (tail == NULL)
        return tail;
    length = tail - head;
    result = malloc(1 + length);
    if (result == NULL)
        return NULL;
    result[length] = '\0';

    memcpy(result, head, length);
    return result;
}


int main (int argc, char **argv) {

    int tsocket;
    char *HTTPbuffer = malloc (BUF);
    char *XMLbuffer = malloc (BUF);
    char *MASTERbuffer = malloc (BUF);
    struct sockaddr_in address;
    struct hostent *he;
    int size;

    char *url = "/Jason/UpdateInfoService";
    char *server = "jws.avm.de";

    char *fb_name = "FRITZ!Box 7590";
    char *fb_hw = "226";
    unsigned int fb_major = 154;
    unsigned int fb_minor = 1;
    unsigned int fb_patch = 1;
    unsigned int fb_build = 10000;
    char *fb_type = "1";
    char *fb_serial = "0000000000";
    char *fb_oem = "avm";
    char *fb_lang ="de";
    char *fb_country = "049";
    char *fb_annex = "B";
    char *fb_flags; // ToDo
    unsigned int fb_updateconfig = 3;
    char *fb_provider = "vodafone2_vdsl";
    char *fb_provider_name = "Vodafone";


    snprintf(MASTERbuffer, BUF,
    "<e:BoxInfoMeshMaster xmlns:e=\"http://juis.avm.de/updateinfo\" xmlns:q=\"http://juis.avm.de/request\">"
        "<q:Name>FRITZ!Box 7590</q:Name>"
        "<q:HW>226</q:HW>"
        "<q:Major>154</q:Major>"
        "<q:Minor>7</q:Minor>"
        "<q:Patch>19</q:Patch>"
        "<q:Buildnumber>77204</q:Buildnumber>"
        "<q:Buildtype>1001</q:Buildtype>"
        "<q:Serial>989BCB312396</q:Serial>"
        "<q:OEM>avm</q:OEM>"
        "<q:Lang>de</q:Lang>"
        "<q:Country>049</q:Country>"
        "<q:Annex>B</q:Annex>"
        "<q:Flag>crashreport</q:Flag>"
        "<q:Flag>avm_acs</q:Flag>"
        "<q:Flag>myfritz_letsencrypt</q:Flag>"
        "<q:Flag>medium_dsl</q:Flag>"
        "<q:Flag>mesh_master</q:Flag>"
        "<q:UpdateConfig>3</q:UpdateConfig>"
        "<q:Provider>vodafone2_vdsl</q:Provider>"
        "<q:ProviderName>Vodafone</q:ProviderName>"
    "</e:BoxInfoMeshMaster>");


    snprintf(XMLbuffer, BUF,
    "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:soap-enc= \"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:e=\"http://juis.avm.de/updateinfo\" xmlns:q=\"http://juis.avm.de/request\">\n"
    "<soap:Header/>\n"
    "<soap:Body>\n"
    "<e:BoxFirmwareUpdateCheck>\n"
        "<e:RequestHeader>\n"
            "<q:Nonce>ixwoteLGzmKa4AefeGbO8w==</q:Nonce>\n"
            "<q:UserAgent>Box</q:UserAgent>\n"
            "<q:ManualRequest>true</q:ManualRequest>\n"
        "</e:RequestHeader>\n"
        "<e:BoxInfo>\n"
            "<q:Name>%s</q:Name>\n"
            "<q:HW>%s</q:HW>\n"
            "<q:Major>%d</q:Major>\n"
            "<q:Minor>%d</q:Minor>\n"
            "<q:Patch>%d</q:Patch>\n"
            "<q:Buildnumber>%d</q:Buildnumber>\n"
            "<q:Buildtype>%s</q:Buildtype>\n"
            "<q:Serial>%s</q:Serial>\n"
            "<q:OEM>%s</q:OEM>\n"
            "<q:Lang>%s</q:Lang>\n"
            "<q:Country>%s</q:Country>\n"
            "<q:Annex>%s</q:Annex>\n"
            "<q:Flag>crashreport</q:Flag>\n"
            "<q:Flag>avm_acs</q:Flag>\n"
            "<q:Flag>myfritz_letsencrypt</q:Flag>\n"
            "<q:Flag>medium_dsl</q:Flag>\n"
            "<q:Flag>mesh_master</q:Flag>\n"
            "<q:UpdateConfig>%d</q:UpdateConfig>\n"
            "<q:Provider>%s</q:Provider>\n"
            "<q:ProviderName>%s</q:ProviderName>\n"
        "</e:BoxInfo>\n"
    "</e:BoxFirmwareUpdateCheck>\n"
    "</soap:Body>\n"
    "</soap:Envelope>",fb_name,fb_hw,fb_major,fb_minor,fb_patch,fb_build,fb_type,fb_serial,fb_oem,fb_lang,fb_country,fb_annex,fb_updateconfig,fb_provider,fb_provider_name);

    snprintf(HTTPbuffer, BUF,
    "POST %s HTTP/1.1\r\n"
    "Host: %s:80\r\n"
    "Content-Length: %d\r\n"
    "Content-Type: text/xml; charset=\"utf-8\"\r\n\r\n%s",url,server,strlen(XMLbuffer),XMLbuffer);


  he = gethostbyname(server);
    if (he == NULL){
    exit(1);
    }



    if ((tsocket=socket(AF_INET, SOCK_STREAM, 0)) > 0) {
//        printf ("Socket wurde angelegt\n");
    }

    address.sin_family = AF_INET;
    address.sin_port = htons (80);
    address.sin_addr = *((struct in_addr *)he->h_addr);

    if (connect(tsocket, (struct sockaddr *) &address, sizeof(address)) == 0) {
//        printf ("Verbindung mit dem Server (%s) hergestellt\n", inet_ntoa(address.sin_addr));
    }



    send(tsocket, HTTPbuffer, strlen(HTTPbuffer), 0);

    size = recv(tsocket, HTTPbuffer, BUF-1, 0);
      if( size > 0) HTTPbuffer[size] = '\0';
//      printf ("Nachricht erhalten:\n%s\n\n", HTTPbuffer);

    char *value;


    value = extract(HTTPbuffer, "<ns3:Found>", "</ns3:Found>");
    if (value != NULL) {
//        printf("%s\n", value);
    }
    int ret = strcmp (value, "true");
    if(ret != 0) {
      printf("Keine Firmware gefunden!\n");
    exit(1);
    }

    free(value);





    value = extract(HTTPbuffer, "<ns3:Name>", "</ns3:Name>");
    if (value != NULL)
        printf("%s\n", value);
    free(value);

    value = extract(HTTPbuffer, "<ns3:Version>", "</ns3:Version>");
    if (value != NULL)
        printf("%s\n", value);
    free(value);

    value = extract(HTTPbuffer, "<ns3:DownloadURL>", "</ns3:DownloadURL>");
    if (value != NULL)
        printf("%s\n", value);
    free(value);

    value = extract(HTTPbuffer, "<ns3:InfoURL>", "</ns3:InfoURL>");
    if (value != NULL)
        printf("%s\n", value);
    free(value);




  close (tsocket);
return EXIT_SUCCESS;
}
Ich will den Server nach neuen Versionen abfragen. Dazu muss man ihm mitteilen welche Hardware man hat. Name und HWID und Major.
Der Name, hwid und major sind immer zusammen und geben die Hardware an.

Loop jetzt deshalb weil ich nach Firmware für alle Boxen suchen will.

Germans Idee ist in sofern nicht schlecht, weil wenn ich dem Programm jetzt nur die Hardware id übergebe, für ne single Anfrage, es sich selber den Namen irgendwie fischen müsste.
 

Lowl3v3l

Mitglied
devCommunity-Experte
Da die Datenmenge hinreichend klein ist ist die Datenstruktur ziemlich egal denke ich, du könntest wohl sogar nen festen Puffer verwenden und den einfach viel zu groß machen um sicher zu gehen. Wenn jeder der Einträge 100 Byte groß ist und du 1000 verschiedene annimmst ist das immernoch maximal eine Verschwendung von unter 100KB ;) Und statische Arrays sind schneller als Listen.

mfg
 

Lowl3v3l

Mitglied
devCommunity-Experte
Ich hätte eigentlich an einen Array von Structs gedacht, da du da scheinbar ja mehrere zusammengehörige Stings speichern willst. Also nimmst du eine Struct mit 3 hinreichend großen char-Array-Puffern und erstellst davon einen Array. aus der gesamtgröße der Struct und der n-ten Struct ist es dann extrem einfach, auf jedes ihrer Elemente zuzugreifen.
 

german

Aktives Mitglied
devCommunity-Experte
Gib mir mal nen Beispiel.
C:
/*
"FRITZ!Box Fon","58","avm",
"FRITZ!Box Fon 5050","72","avm",
"FRITZ!Box Fon 5124","126","avm",
"FRITZ!Box Fon 5140","111","avm",
"FRITZ!Box 2031","113","avm",
"FRITZ!Box 2070","84","avm",
"FRITZ!Box 2110","133","avm",
"FRITZ!Box 2170","119","avm"
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct foo
{
  const char str1[64];
  const char str2[32];
  const char str3[32];
};

int comp_foo(const void *a, const void *b)
{
  return strcmp(((struct foo*)a)->str1, ((struct foo*)b)->str1);
}

int main(void)
{
  struct foo bar[] =
  {
    {"FRITZ!Box Fon","58","avm"},
    {"FRITZ!Box Fon 5050","72","avm"},
    {"FRITZ!Box Fon 5124","126","avm"},
    {"FRITZ!Box Fon 5140","111","avm"},
    {"FRITZ!Box 2031","113","avm"},
    {"FRITZ!Box 2070","84","avm"},
    {"FRITZ!Box 2110","133","avm"},
    {"FRITZ!Box 2170","119","avm"}
  };

  const size_t length = sizeof(bar) / sizeof(struct foo);


  qsort(bar, length, sizeof(struct foo), comp_foo);


  struct foo search = {"FRITZ!Box Fon 5124","",""};
  struct foo *found = bsearch(&search, bar, length, sizeof(struct foo), comp_foo);
  if (found != NULL)
  {
    puts(found->str1);
    puts(found->str2);
    puts(found->str3);
  }

  return 0;
}
 

lano

Mitglied
struct foo bar[] = { {"FRITZ!Box Fon","58","avm"}, {"FRITZ!Box Fon 5050","72","avm"}, {"FRITZ!Box Fon 5124","126","avm"}, {"FRITZ!Box Fon 5140","111","avm"}, {"FRITZ!Box 2031","113","avm"}, {"FRITZ!Box 2070","84","avm"}, {"FRITZ!Box 2110","133","avm"}, {"FRITZ!Box 2170","119","avm"} };
Genau so lief mir das neulich noch übern weg. Lesezeichen gesetzt und nicht mehr wieder gefunden.
 
Oben Unten