Сравнение строк в switch
- Войдите на сайт для отправки комментариев
Чт, 12/12/2013 - 20:52
Я не нашол ничего лучше как crc32 вычислять для каждой строки и сравнивать с подсчитанными заранее...
Я не нашол ничего лучше как crc32 вычислять для каждой строки и сравнивать с подсчитанными заранее...
вот сами строки с расчетом их crc32 в питоне
>>> import binascii >>> hex(binascii.crc32("on") & 0xffffffff) '0x9b629c8L' >>> binascii.crc32("on") 162933192 >>> binascii.crc32("On") -1674441366 >>> hex(binascii.crc32("On") & 0xffffffff) '0x9c320d6aL' >>> hex(binascii.crc32("ON") & 0xffffffff) '0xa75c2da2L' >>> hex(binascii.crc32("1") & 0xffffffff) '0x83dcefb7L' >>> hex(binascii.crc32("true") & 0xffffffff) '0xfdfc4c8dL' >>> hex(binascii.crc32("off") & 0xffffffff) '0x2bbc5d43L' >>> hex(binascii.crc32("Off") & 0xffffffff) '0x13f11ba3L' >>> hex(binascii.crc32("0") & 0xffffffff) '0xf4dbdf21L' >>> hex(binascii.crc32("false") & 0xffffffff) '0x2bcd6830L' >>> hex(binascii.crc32("OFF") & 0xffffffff) '0xbd1b1fc9L' >>> hex(binascii.crc32("r1") & 0xffffffff) '0xd0e09b1L' >>> hex(binascii.crc32("R1") & 0xffffffff) '0x988a2d13L' >>> hex(binascii.crc32("r2") & 0xffffffff) '0x9407580bL' >>> hex(binascii.crc32("R2") & 0xffffffff) '0x1837ca9L' >>> hex(binascii.crc32("r3") & 0xffffffff) '0xe300689dL' >>> hex(binascii.crc32("R3") & 0xffffffff) '0x76844c3fL' >>> hex(binascii.crc32("r4") & 0xffffffff) '0x7d64fd3eL' >>> hex(binascii.crc32("R4") & 0xffffffff) '0xe8e0d99cL' >>>Вот код скетча...
/* Web Server A simple web server that shows the value of the analog input pins. using an Arduino Wiznet Ethernet shield. Circuit: * Ethernet shield attached to pins 10, 11, 12, 13 * Analog inputs attached to pins A0 through A5 (optional) created 18 Dec 2009 by David A. Mellis modified 9 Apr 2012 by Tom Igoe */ #include <SPI.h> #include <Ethernet.h> #include <SD.h> #include <Wire.h> // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192,168,10,177); #define R1 22 #define R2 23 #define R3 24 #define R4 25 /* This creates an instance of the webserver. By specifying a prefix * of "", all pages will be at the root of the server. */ #define WEBDUINO_SERVER_HEADER "Server: Test/" #define WEBDUINO_AUTH_REALM "Analog data" #define PREFIX "" #include <WebServer.h> WebServer webserver(PREFIX, 80); P(relay_form) = "<form>" "<label for=\"r1\">Relay 1</label><select name=\"r1\"><option>on</option><option>off</option></select><br>" "<label for=\"r2\">Relay 2</label><select name=\"r2\"><option>on</option><option>off</option></select><br>" "<label for=\"r3\">Relay 3</label><select name=\"r3\"><option>on</option><option>off</option></select><br>" "<label for=\"r4\">Relay 4</label><select name=\"r4\"><option>on</option><option>off</option></select><br>" "<input type=\"submit\" value=\"Set\">" "</form>" ; //Init LCD via I2C PCF8264 #include <LiquidCrystal.h> LiquidCrystal lcd(0x27); //CRC static PROGMEM prog_uint32_t crc_table[16] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; unsigned long crc_update(unsigned long crc, byte data) { byte tbl_idx; tbl_idx = crc ^ (data >> (0 * 4)); crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4); tbl_idx = crc ^ (data >> (1 * 4)); crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4); return crc; } unsigned long crc32(char *s) { unsigned long crc = ~0L; while (*s) crc = crc_update(crc, *s++); crc = ~crc; return crc; } void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) { server.httpSuccess(); if (type != WebServer::HEAD) { P(helloMsg) = "<h1>Hello, World!</h1><a href=\"private.html\">Private page</a>"; server.printP(helloMsg); server.println("<pre>"); File dataFile = SD.open("log.txt"); if (dataFile) { while (dataFile.available()) { server.print((char)dataFile.read()); } dataFile.close(); } server.println("</pre>"); } } void privateCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) { /* if the user has requested this page using the following credentials * username = user * password = user * display a page saying "Hello User" * * the credentials have to be concatenated with a colon like * username:password * and encoded using Base64 - this should be done outside of your Arduino * to be easy on your resources * * in other words: "dXNlcjp1c2Vy" is the Base64 representation of "user:user" * * if you need to change the username/password dynamically please search * the web for a Base64 library */ if (server.checkCredentials("dXNlcjp1c2Vy")) { server.httpSuccess(); if (type != WebServer::HEAD) { P(helloMsg) = "<h1>Hello User</h1>"; server.printP(helloMsg); // output the value of each analog input pin for (int analogChannel = 0; analogChannel < 6; analogChannel++) { int sensorReading = analogRead(analogChannel); server.print("analog input "); server.print(analogChannel); server.print(" is "); server.print(sensorReading); server.println("<br />"); } } } /* if the user has requested this page using the following credentials * username = admin * password = admin * display a page saying "Hello Admin" * * in other words: "YWRtaW46YWRtaW4=" is the Base64 representation of "admin:admin" */ else if (server.checkCredentials("YWRtaW46YWRtaW4=")) { server.httpSuccess(); if (type != WebServer::HEAD) { P(helloMsg) = "<h1>Hello Admin</h1>"; server.printP(helloMsg); } } else { /* send a 401 error back causing the web browser to prompt the user for credentials */ server.httpUnauthorized(); } } void togle(uint8_t pin, char * state){ switch(crc32(state)){ case 0x9b629c8: case 0x9c320d6a: case 0xa75c2da2: case 0x83dcefb7: case 0xfdfc4c8d: digitalWrite(pin, LOW); break; case 0x2bbc5d43: case 0x13f11ba3: case 0xbd1b1fc9: case 0xf4dbdf21: case 0x2bcd6830: digitalWrite(pin, HIGH); break; } } uint8_t getpin(char * name){ switch(crc32(name)){ case 0xd0e09b1: case 0x988a2d13: return R1; break; case 0x9407580b: case 0x1837ca9: return R2; break; case 0xe300689d: case 0x76844c3f: return R3; break; case 0x7d64fd3e: case 0xe8e0d99c: return R4; break; } } #define NAMELEN 32 #define VALUELEN 32 void relay(WebServer &server, WebServer::ConnectionType type, char * url_tail, bool tail_complete){ URLPARAM_RESULT rc; char name[NAMELEN]; int name_len; char value[VALUELEN]; int value_len; server.httpSuccess(); switch(type){ case WebServer::HEAD: return; break; case WebServer::GET: while (strlen(url_tail)){ rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN); if (rc != URLPARAM_EOS) togle(getpin(name),value); } default: server.printP(relay_form); } } void setup() { pinMode(R1,OUTPUT); pinMode(R2,OUTPUT); pinMode(R3,OUTPUT); pinMode(R4,OUTPUT); digitalWrite(R1,HIGH); digitalWrite(R2,HIGH); digitalWrite(R3,HIGH); digitalWrite(R4,HIGH); lcd.begin(20,4); lcd.begin(20,4); lcd.backlight(); // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); pinMode(4, OUTPUT); if (!SD.begin(4)) { Serial.println("failed!"); lcd.println("SD not found!"); }else{ Serial.println("done."); sdinfo(); } Serial.println("Initializing Eternet!"); // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // using static ip: Ethernet.begin(mac, ip); } Serial.print("server is at "); Serial.println(Ethernet.localIP()); lcd.println(Ethernet.localIP()); webserver.setDefaultCommand(&defaultCmd); webserver.addCommand("index.html", &defaultCmd); webserver.addCommand("private.html", &privateCmd); webserver.addCommand("relay/", &relay); webserver.begin(); } void sdinfo(){ switch(SD.card.type()) { case SD_CARD_TYPE_SD1: lcd.print("SD1 "); break; case SD_CARD_TYPE_SD2: lcd.print("SD2 "); break; case SD_CARD_TYPE_SDHC: lcd.print("SHC "); break; default: lcd.print("--- "); } uint32_t volumesize; volumesize = SD.volume.blocksPerCluster(); // clusters are collections of blocks volumesize *= SD.volume.clusterCount(); // we'll have a lot of clusters volumesize /= 2; //2k per cluster with 4x512b blocks if(volumesize > 1024){ volumesize /= 1024; lcd.print(volumesize); lcd.println(" Mb"); }else{ lcd.print(volumesize); lcd.println(" Kb"); } } void loop() { char buff[64]; int len = 64; /* process incoming connections one at a time forever */ webserver.processConnection(buff, &len); }Код работает как и должен, но мне кажется что он кривой и не оптимальный.
Ищу красивое и более оптимальное решение для обработки параметров передаваемых в запросе...
Вообще как проще всего сравнивать строки в switch.
Скетч запускаю на меге, а большой он потому что играюсь с модулями разными )))
P.S. LiquidCrystal использован не стандартный...
Используйте strcasecmp и if
Это я знаю... речь идет об конструкциях
switch(string){ case "Test": case "test": case "TEST": test(); case "ok": case "Ok": myFunction(); break; default: otherFunction(); }Если такое на ифах писать ггг....
можно конечно строки в нижний регистр приводить. Надо какой то более простой CRC использовать для расчета идентификатора...
А зачем switch ?? тем более он вроде больше места занимает чем if..
Нормально на if писать,главно оформить отступы кода
Вобщем вопрос больше теоретический чем практический. Вызывать функцию strcmp я считаю затратнее чем расчитать хэш и сравнивать с хэшами - которые число и памяти меньше жрут.
Доброго времени суток !
Вобщем вопрос больше теоретический чем практический. Вызывать функцию strcmp я считаю затратнее чем расчитать хэш и сравнивать с хэшами - которые число и памяти меньше жрут.
Я думаю Вы ошибаетесь. У Вас 8-ми битный процессор самое быстрое, что он может в данной ситуации делать побайтное сравнение. Обработка хешей - это обработка тех же байтов плюс 32-ух битная математика.
я бы делал так:
char str1[] PROGMEM = "void"; char str1[] PROGMEM = "typedef"; char str1[] PROGMEM = "hello"; char *str[] PROGMEM ={str1,str2,str3}; void myFunc(char *a) { uint8_t i1; i1 = 0; while(i1<3) { if (!strcmp(a,(char*)pgm_read_word(&(str[i1])))) break; i1++; } switch(i1){ case 0: doVoidFunc(); break; case 1: doTypedefFunc(); break; case 2: doHelloFunc(); break; case 3: doNeNajdenFunc(); break; } }