IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Jak zjistit délku pole předaného do funkce?

V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Antonín Dolejš:31.3.2021 2:16

Ahoj, mám funkci

const char* cgiHandler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]);

char *pcValue[] je pole stringů, ze kterého potřebuju vyndat 3 hodnotu a zjistit její délku, abych ji mohl odeslat funkcí

HAL_UART_Transmit(&huart3, value, length, 50);

Vím, že v C je string vlastně pole znaků, tj. pole stringů je pole polí znaků. Znám i princip pointerů, ale nemám to zatím moc zažité, vždy o nich musím hodně přemýšlet a tady jsem se to toho už totálně zamotal :D Když předávám do funkce pole, tak se ve skutečnosti předá pouze pointer na něj, ten já hvězničkou v definici funkce dereferencuju a dostávám zpátky pole. Teď ale už jen jednorozměrné a navíc nevím, jak dlouhé, protože nemůžu používat na takové pole sizeof() protože mi to jinak vrátí velikost toho pointeru a ne toho pole. To původní pole bylo ale 2D, jeden rozměr mi předali parametrem iNumParams, předpokládám, že pole musí být "obdélník", tj. že všechny parametry budou doplněné nulami tak, aby měli stejnou délku jako nejdelší parametr. Takže kdybych znal celkovou délku, tak bych mohl snadno délku každého parametru spočítat, ale jsem ji schopen nějak zjistit? Nebo jak se má tohle správně implementovat? Vím, že když se předává pole do funkce, tak že se vždy jako další parametr předává délka toho pole (jako je to např. u té funkce HAL_UART_Tran­smit(). Ale tady mi dávají jen počet parametrů a dva pointery, co s tím mám dělat?

Tady je, co o funkci píšou v dokumentaci, pokud by to pomohlo:

Function pointer for a CGI script handler.

This function is called each time the HTTPD server is asked for a file whose name was previously registered as a CGI function using a call to http_set_cgi_­handlers. The iIndex parameter provides the index of the CGI within the cgis array passed to http_set_cgi_­handlers. Parameters pcParam and pcValue provide access to the parameters provided along with the URI. iNumParams provides a count of the entries in the pcParam and pcValue arrays. Each entry in the pcParam array contains the name of a parameter with the corresponding entry in the pcValue array containing the value for that parameter. Note that pcParam may contain multiple elements with the same name if, for example, a multi-selection list control is used in the form generating the data.

The function should return a pointer to a character string which is the path and filename of the response that is to be sent to the connected browser, for example "/thanks.htm" or "/response/error­.ssi".

The maximum number of parameters that will be passed to this function via iNumParams is defined by LWIP_HTTPD_MA­X_CGI_PARAMETER­S. Any parameters in the incoming HTTP request above this number will be discarded.

Requests intended for use by this CGI mechanism must be sent using the GET method (which encodes all parameters within the URI rather than in a block later in the request). Attempts to use the POST method will result in the request being ignored.

Zkusil jsem: Přecejen jsem zkusil funkci sizeof(), ale jak jsem předpokládal vrátila pouze délku pointeru – 4.

Chci docílit: Odeslat třetí (pro test) parametr z HTTP požadavku na UART.

 
Odpovědět
31.3.2021 2:16
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Antonín Dolejš
DarkCoder:31.3.2021 5:26

Vím, že v C je string vlastně pole znaků

Vypadla Ti jedna podstatná věc, díky které to vyřešíš. A to že řetězec v C je definován jako pole znaků ukončené nulovým znakem (null).

Všechny tebou ostatní vyjádřené myšlenky jsou správné. Nulový znak Ti pomůže určit délku řetězce uloženého na daném řádku. Toho můžeš využít a předat funkci ukazatel na samotné pole, pokud víš jak je velké (počet řádků). To je jediná doplňková informace, kterou musíš funkci předat, protože z ukazatele na pole předaného funkci jako argument nelze určit délku pole. Je to obdobné jako u funkce main(), jejíž tvar se používá pro příjem argumentů zadaných na příkazovém řádku.

int main(int argc, char *argv[])

Funkce main() v tomto tvaru má dva parametry. Prvním vyjadřuje počet argumentů zadaných na příkazovém řádku a druhý představuje tyto argumenty uložené v tabulce řetězců.

Jiný způsob, kde není třeba předávat informaci o velikosti pole, je ukončení seznamu argumentů jednoznačným způsobem. Obvykle se to řeší prázdným záznamem.

Podívej na následující program, ze kterého je vše patrné:
Je vytvořena tabulka řetězců představující knihovnu, ve které jsou uloženy názvy knih. Program vypíše všechny názvy knih a jejich délku. Pro výpis názvů a jejich délek je vytvořena funkce infoBook(), která přebírá ukazatel na tabulku řetězců bez jakékoli přídavné informace.

// Vypis nazvu knih a jejich delky ve znacich

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

void infoBook(char *lib[]);

int main(void) {
        char *books[] = {
                "Complete C Reference",
                "Teach Yourself C",
                "C Programming Language",
                "Mastering C Pointers",
                "Extreme C",
                "C Cookbook",
                ""
        };

        infoBook(books);

        return 0;
}

void infoBook(char *lib[]) {
        for (int i = 0; *lib[i]; i++) {
                printf("%s - %d\n", lib[i], strlen(lib[i]));
        }
}

To nejzajímavější na celém programu je způsob zastavení cyklu při procházení knihovny když se dojde na poslední záznam.
Přečtení prvního bytu na daném řádku a ukončení cyklu v případě, že je roven nule (neplatný záznam).
Obsah na daném řádku je tvořen výpisem ukazatele na řádek. A z definice, že řetězce v C jsou ukončeny nulovým znakem, lze určit jak obsah, tak délku řetězce na daném řádku.

Je třeba mít na paměti, že tento způsob lze použít pouze s řetězci. Pro jiné typy dat je nezbytné předat funkci doplňkovou informaci o velikosti pole.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
31.3.2021 5:26
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Antonín Dolejš:31.3.2021 16:12

Díky moc, vše co jsem potřeboval byla funkce strlen() :D Já si říkal, že to nemůže být určitě nic složitého a že o tom přemýšlím zbytečně moc komplikovaně...

HAL_UART_Transmit (&huart3, pcValue[2], strlen(pcValue[2]), 50);

A teď když budu potřebovat najít hodnotu pro konkrétní klíč, tak předpokládám, že bude stačit cyklus a funkce strcmp(), která už si s koncemi poradí sama stejně jako strlen().

Díky i za zajímavý fígl s prázným záznamem, tady to použít nemůžu, to bych musel předělat lwIP, ale v proměnné iNumParams počet záznamů mám, takže to není problém. Někdy se to ale určitě bude hodit :)

Editováno 31.3.2021 16:13
 
Nahoru Odpovědět
31.3.2021 16:12
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Antonín Dolejš
DarkCoder:31.3.2021 16:57

Přesně tak. Znát počet záznamů je důležité a je třeba předně otestovat hodnotu klíče na to, zda je v platném rozsahu počtu záznamů. A to zejména tehdy, přistupujeme-li náhodně k záznamům. Nejen funkce strlen() a strcmp(), ale všechny funkce pro práci s řetězci ze standardní knihovny jazyka C pracují s tím, že nulový znak je ukončujícím znakem řetězce. Tedy i bez funkce strlen() by si se obešel, jednoduše by sis ji naimplementoval sám. :-)

Nahoru Odpovědět
31.3.2021 16:57
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 4 zpráv z 4.