Robert85 Napisano Kwiecień 16, 2021 Udostępnij Napisano Kwiecień 16, 2021 Czołem, jako osoba mniej ścisła, męczę się od wczoraj z próbą ustawienia dwóch zmiennych pobranych z pliku txt zlokalizowanym na zdalnym serwie, korzystając z biblioteki HTTPClient.h. Plik tekstowy ma zawartość "640, 1530" (ale może być też dowolny separator lub nawet w osobnej linii, mam dostęp do tego pliku i mogę go zrobić jak chcę, wazne aby działało). http.begin("http://192.168.1.2/zmienne.txt"); int httpCode2 = http.GET(); if (httpCode2 > 0) { //Check for the returning code String payload2 = http.getString(); } else { Serial.println("<br>Blad pobrania danych z serwa</br>"); } http.end(); Za cholerę nie potrafię przerobić tych dwóch wartości na 2 osobne zmienne liczbowe czyli np.: zmienna1 = 640; zmienna2 = 1530; Kombinowałem i przerobieniem tego na tablicę ale wówczas zmienna[0] = 640 a zmienna[1] = 0. Próbowałem używać funkcji konwertujacych string na int, ale rezultaty podobne. Większość przykładów na necie to operowanie pobieranym plikiem z np. karty SD i użycie funkcji fscanf, ale przypadku pobrania zawartości pliku przez http.GET() to już nie działa. Myślałem też o przerobieniu tego na XML, ale to bez sensu skoro to tylko 2 liczbowe wartości. Będę wdzięczny za naprowadzenie. Pozdro Cytuj Link do komentarza Share on other sites More sharing options...
H1M4W4R1 Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 [C++] https://en.cppreference.com/w/cpp/regex [C] https://stackoverflow.com/questions/1085083/regular-expressions-in-c-examples Więcej raczej nie muszę tłumaczyć, ewentualnie skanujesz stringa jako tablicę znaków dopisując znaki do tablicy A i po wystąpieniu separatora przetwarzasz tablicę A na zmienną i ją czyścisz. Cytuj Link do komentarza Share on other sites More sharing options...
Robert85 Kwiecień 16, 2021 Autor tematu Udostępnij Kwiecień 16, 2021 (edytowany) Znalazłem taką funkcję i staram się to zrobić za jej pomocą. #include <stdio.h> #include <stdlib.h> int main(void){ char *input = "640 1530"; int len = 0; sscanf(input, "%*[^0-9]%n", &len);//count not-digits(The Number isn't negative) char *p = input + len; char *start = p; int v, n = 0; while(1 == sscanf(p, "%d%n", &v, &len)){ ++n;//count elements p += len; } int array[n];//or allocate by malloc(and free) char *endp = NULL; int i; for(i = 0; i < n; ++i){ array[i] = strtol(start, &endp, 10); start = endp + 1; } //check print for(i = 0; i < n; ++i) printf("%d ", array[i]); puts(""); return 0; } Edytowano Kwiecień 16, 2021 przez Robert85 Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 (edytowany) Podam Ci sposób który ja stosuję. Niech napis wejściowy będzie po prostu ciągiem znaków (czyli jakimś kawałkiem pamięci, w którym po kolei siedzą sobie znaczki) i dysponujemy adresem pierwszego elementu (wskaźnikiem). Czyli przykładowo: char *napis="640, 1530"; ale równie dobrze może to być: char *napis = " 640 : 1530 : "; Spróbuję znaleźć pierwszą liczbę w napisie. W tym celu przeszukuję napis aż do napotkania końca napisu lub początku liczby: bool blad; char *wskaznik; int zmienna; wskaźnik = napis; blad = false; while (1) { if (!*wskaznik) { // czy to koniec napisu? blad = true; // niedobrze! break; } if (isdigit(*wskaznik)) { // czy to cyfra? break; } if (*wskaznik == '-' && isdigit(wskaznik[1]) { // a może początek liczby ujemnej? break; } wskaznik++; // nie, to jeszcze nie liczba, sprawdzimy następny znak } // i w tym miejscu mamy albo początek, liczby, albo koniec napisu if (blad) { // tu sobie wymyśl co robić jeśli napis nie zawiera liczby } // funkcja pobiera z pierwszego parametru liczbę. Drugim parametrem jest // adres zmiennej, do której wstawia adres następnego znaku za liczbą. // Trezeci to po prostu podstawa - jako że używamy systemu dziesiętnego // podajemy funkcji 10 zmienna = strtol(napis, &napis, 10); // i tu mamy w zmiennej wartość pierwszej liczby Wygląda na skomplikowane? Jak się przypatrzysz, to wcale nie. Jak wyciągnąć dwie liczby powinieneś na tej podstawie sam napisać, jakby Ci się nie chciało to masz tu przykład: #define ILOSC_LICZB 2 bool blad; char *wskaznik; int zmienna[ILOSC_LICZB]; wskaźnik = napis; blad = false; int i; for (i=0; i< ILOSC_LICZB; i++) { // pobieramy każdą liczbę while (1) { if (!*wskaznik) { // czy to koniec napisu? blad = true; // niedobrze! break; } if (isdigit(*wskaznik)) { // czy to cyfra? break; } if (*wskaznik == '-' && isdigit(wskaznik[1]) { // a może początek liczby ujemnej? break; } wskaznik++; // nie, to jeszcze nie liczba, sprawdzimy następny znak } // i w tym miejscu mamy albo początek, liczby, albo koniec napisu if (blad) { break; // nie było którejś kolejnej liczby, przerywamy pracę } zmienna[i] = strtol(napis, &napis, 10); } // i tu mamy albo tablicę zmienna wypełnioną naszymi liczbami, albo zasygnalizowany błąd I co ważne: funkcje isdigit i strtol są częścią standardu C a nie Arduino, w związku z tym należy zapowiedzieć kompilatorowi że będziemy je stosować, W tym celu trzeba w pliku źródłowym wstawić na początku dwie dyrektywy: // tu siedzą isdigit, isalpha, isalnum, islower i inne // ciekawe funkcje operujące na pojedynczych znakach ASCII #include <ctype.h> // a tu siedzą standardowe funkcje języka C, m.in. strtol #include <stdlib.h> 2 godziny temu, H1M4W4R1 napisał: [C++] https://en.cppreference.com/w/cpp/regex Naprawdę, nie znasz prostszych sposobów? No to ja Twojej gry nie kupię bo mi się procek w telefonie usmaży 😉 Edytowano Kwiecień 16, 2021 przez ethanak 2 Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
_LM_ Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 (edytowany) Są funkcje strtok i strtok_r zamiana na int atoi() Edytowano Kwiecień 16, 2021 przez _LM_ Cytuj Link do komentarza Share on other sites More sharing options...
H1M4W4R1 Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 2 minuty temu, ethanak napisał: Naprawdę, nie znasz prostszych sposobów? No to ja Twojej gry nie kupię bo mi się procek w telefonie usmaży Uwaga lekki offtopic - tylko do @ethanak 😉 To jest najprostszy sposób, bo najmniej problemów. A pod regexami był alternatywny 😛 I rozumiem, że masz jednordzeniowy procesor o taktowaniu 16MHz w telefonie? (sarkazm)... W moich aplikacjach praktycznie takich rzeczy nie widać, bo są liczone w tle (o ile nie są hardcodowane...) Najpierw gry są tworzone pod CTR, gdzie tylko ma "działać" (równie dobrze nie musi) w edytorze. Celem jest nagranie reklamy, a nie tworzenie w pełni wydajnej i funkcjonalnej gry. To drugie się nie opłaca. Tutaj przykład rozwiązania problemu z języka C# - porównaj sobie ile linijek zajmuje to u Ciebie, a ile u mnie 😉 - w mojej branży czas jest cenniejszy niż jakakolwiek wydajność (powód powyżej) return await (await RegEx.GetMatchesAsync("<regex_string>")).SelectAsync(q => int.Parse(q)); A tyle wpisuję w edytorze (ret aw (aw rex.GMAs("<regex_string>") 🠒 .SAs(q => int.Pa(q); Większość programistów marnuje zasoby procesora... Wiem po tym jak dostaję projekty po innych osobach - najczęściej wszystko stoi na jednym wątku przez co gra chodzi jak muł... Po coś jednak telefon ma te osiem rdzeni, a system zadowoli się jednym... A jak już coś ma być wydane: Najpierw ma działać, optymalizacją zajmie się stażysta. Cytuj Link do komentarza Share on other sites More sharing options...
Robert85 Kwiecień 16, 2021 Autor tematu Udostępnij Kwiecień 16, 2021 Dziękuję za pomoc. I tak rozbiłem się o mur typu zmiennych. Biblioteka HTTPClient ma funkcję pobierającą dane z URLa do zmiennej typu string String payload2 = http.getString(); Funkcja, którą wrzuciłem działa bdb, ale jeśli zmienna jest char * a nie String. Kombinowałem z konwersją string na const char itd, ale poległem. Muszę chyba się przewietrzyć bo mi zwoje w mózgu przegrzało. Kiedyś (z 15 lat temu) robiłem jakieś proste wizytówki w php i tam nie miałem nigdy problemu z typami zmiennych a tutaj rozbijam się na banałach, aż mi wstyd. Program na ten moment wygląda tak (brakuje tylko przekonwertowania zmiennej payload2 na czas1 (mimo wielu podejść - nie poradziłem sobie). Na tem moment nagłówku mam to: #include <NTPClient.h> #include <WiFi.h> #include <WiFiUdp.h> #include <HTTPClient.h> #include <string.h> #include <stdlib.h> #include <ctype.h> HTTPClient http; http.begin("http://192.168.1.2/zmienne.txt"); //adres url ze zmiennymi // zawartość pliku txt to "640 1530" int httpCode2 = http.GET(); //Make the request if (httpCode2 > 0) { //Check for the returning code String payload2 = http.getString(); // tutaj mam zawartość pliku txt postaci "640 1530" // miejsce na przekonertowanie String payload2 na char *czas1 // int len = 0; sscanf(czas1, "%*[^0-9]%n", &len); char *p = czas1 + len; char *start1 = p; int v, n = 0; while(1 == sscanf(p, "%d%n", &v, &len)){ ++n; p += len; } int array[n]; char *endp = NULL; int i; for(i = 0; i < n; ++i){ array[i] = strtol(start1, &endp, 10); start = endp + 1; } int zmienna1 = array[0]; int zmienna2 = array[1]; Cytuj Link do komentarza Share on other sites More sharing options...
Elvis Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 Tak sobie patrzę na to asynchroniczne parsowanie prostego stringa i dochodzę do wniosku że jednak apple niesłusznie był oskarżany o celowe spowalnianie swoich urządzeń. A tymczasem facebook chyba czyta w moich myślach - po pokazał mi obrazek, którym muszę się podzielić. Idealnie pasuje do tej dyskusji: 1 Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 3 minuty temu, Robert85 napisał: Kombinowałem z konwersją string na const char itd, ale poległem. String s = cośtam; const char *napis = s.c_str(); Cytuj Link do komentarza Share on other sites More sharing options...
_LM_ Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 zamiana String na char (char*)&str lub s.c_str() Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 26 minut temu, H1M4W4R1 napisał: W moich aplikacjach praktycznie takich rzeczy nie widać, bo są liczone w tle No wiesz, propozycja użycia regexpa tam gdzie praktycznie wystarczy strpbrk świadczy o tym, że być może paru innych rzeczy nie widać 🙂 (nie obrażaj się, jakbyś nie wiedział to jest to żart) Cytuj Link do komentarza Share on other sites More sharing options...
_LM_ Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 O @ethanak mnie uprzedził, za wolny net mam 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
Robert85 Kwiecień 16, 2021 Autor tematu Udostępnij Kwiecień 16, 2021 Dodałem zgodnie z sugestią: String payload2 = http.getString(); (char*)&payload2; int len = 0; sscanf(payload2, "%*[^0-9]%n", &len); ale i tak wypluwa błąd: cannot convert 'String' to 'const char*' for argument '1' to 'int sscanf(const char*, const char*, ...)' Cytuj Link do komentarza Share on other sites More sharing options...
_LM_ Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 (edytowany) Scanf(char*) & payload.... Spróbuj też bez ampersand. Sorki pisząc z komórki nie mogę tego precyzyjnie przedstawić Edytowano Kwiecień 16, 2021 przez _LM_ Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Kwiecień 16, 2021 Udostępnij Kwiecień 16, 2021 2 minuty temu, Robert85 napisał: Dodałem zgodnie z sugestią String payload2 = http.getString(); (char*)&payload2; sscanf(payload2, "%*[^0-9]%n", &len); A co to niby miało znaczyć? Bo znaczy to w tej chwili tyle: Pobierasz do zmiennej payload2 typu String wynik http.getString(); Bierzesz teraz payload2, przekształcasz na char *, a wynik tego przekształcenia wyrzucasz. Wywołujesz funkcję sscanf, której pierwszym argumentem jest payload2 (typu String, bo się przecież magicznie nie zmienił) Dziwisz się, że kompilator nie chce String tam gdzie chce const char *. Na pewno taka była sugestia? A czemu nie np.: sscanf(payload2.c_str(), "%*[^0-9]%n", &len); (czyli zgodnie z sugestią)? Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!