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í.
Mezi 13:00 až cca 16:00 proběhne odstávka sítě z důvodu aktualizace. Web bude po celou dobu nedostupný.

Diskuze: Uložení více textů do pole

Aktivity
Avatar
Caster
Člen
Avatar
Caster:30.3.2022 0:53

Pro Arduino vytvářím program poznámkový blok na lednici, které bude na e-paper displeji zobrazovat počet dnů do expirace a jméno uložené potraviny. Procesor bude v režimu spánku a pomocí hodin RTC se každý den v 6:00 probudí od expirace odečte 1 den, aktualizuje výpis na displeji a vrátí se do režimu spánku. Základ programu pro Seeeduino XIAO včetně ovládání displeje mi již funguje. Po překročení expirace se budou další tři dny zobrazovat záporné hodnoty 0 -1 -2 -3 a další den bude položka smazána a nebude se již vypisovat na displej. Zbylé potraviny se "virtuálně" posunou o řádek dolů, aby se začaly vypisovat od horního okraje displeje.

V C++ si chci vyzkoušet práci s textem, program pak převedu do Arduina.

ukázka textu na displeji

Zkusil jsem: Po nákupu zatím zadám potraviny do programu ručně, zkompiluji ho a nahraji do MCU pomocí Arduino IDE. Později data (názvy koupených potravin a datum expirace do MCU nahraji pomocí bluetooth z aplikace Android, kterou již vytvářím v Android Studiu, nadiktováním např. (šunka 5 2 tj. expirace 2.5.) - základ programu mi již funguje.

#include <iostream>

uint8_t dny[6];
char* array[5];

int main()
{
        array[1] = "Sunka Bohemia";
        array[2] = "Cesn syrova pomazanka";
        array[3] = "Hermelin";
        array[4] = "Smetana";
        array[5] = "Pazitka";
        array[6] = "Hovezi bujon tekuty";
        printf("%s", array);
}

Chci docílit: Nevím přesně, jak názvy potravin uložit do textového pole ideálně v jednotlivých řádcích viz pokus programu níže, abych pak názvy potravin mohl na displej vypisovat v cyklu.

 
Odpovědět
30.3.2022 0:53
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:30.3.2022 8:08

Pro nahrani potravin, neslo by pouzit carovy kod a ctecku?
google = cpp array examples
Jestli to spravne chapu, ale c++ neznam, tak mas spatne tu hvezdicku.
https://www.geeksforgeeks.org/…ways-create/

char* array[5]; // tvoje
const char *colour[4] // jejich

A take maji vsechny definice v mainu.
A take neprekracuji limit pole, kdyz mam 5, tak je to 0 az 4

Editováno 30.3.2022 8:10
 
Nahoru Odpovědět
30.3.2022 8:08
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:30.3.2022 11:52

Práce s texty má mnoho podob, pokud chceš pracovat s řetězcovými literály, pak pole ukazatelů je dobrá volba.

Deklaraci pole ukazatelů máš v pořádku (na pozici * nezáleží), správný je i způsob jak měnit danou položku. Chybně už máš to že nerespektuješ počet prvků pole a přistupuješ k prvku, jehož paměť už není tvá! Velikost 5 = rozsah 0-4.

Celkově bude celá aplikace složitější, ale abys mohl na něco navázat, zde je krátká a jednoduchá ukázka s polem ukazatelů na řetězce.

#include <stdio.h>

int main(void) {
    char* foods[] = {
       "Sunka Bohemia",
       "Cesn syrova pomazanka",
       "Hermelin",
       "Smetana",
       "Pazitka",
       "Hovezi bujon tekuty"
    };

    size_t len = sizeof(foods) / sizeof(foods[0]);

    printf("Pocet retezcu v poli - %llu\n\n", len);


    // Vypis pole retezcu různymi způsoby
    for (int i = 0; i < len; i++) printf("%s\n", foods[i]);
    // for (int i = 0; i < len; i++) fprintf(stdout, "%s\n", foods[i]);
    // for (int i = 0; i < len; i++) puts(foods[i]);

    // u fputs nedochazi k odradkovani
    // for (int i = 0; i < len; i++) fputs(foods[i], stdout);

    // fputs lze pouzit takto s putchar()
    /*
    for (int i = 0; i < len; i++) {
        fputs(foods[i], stdout);
        putchar('\n');
    }
    */

    foods[4] = "Porek";

    putchar('\n');

    // Vypis modifikovaného pole pomocí ukazatelové aritmetiky
    for (char** p = foods; p < foods + len; p++) puts(*p);

    putchar('\n');

    // Vypis adres retezcu a retezce na dané adrese
    for (int i = 0; i < len; i++) {
        printf("%u - %s\n", (unsigned)foods[i], foods[i]);
    }

    return 0;
}

Pole je inicializováno ukazateli na řetězce. Zjistí se, kolik prvků (řetězců) obsahuje, pro ověření se hodnota vypíše. Vypíše se obsah pole. Zamění se název jedné položky a opět se vypíše pole. Nakonec je zobrazena informace pro zajímavost a to adresy jednotlivých řetězců, kde je vidět, že řetězce nejdou za sebou ale jsou různě rozmístěny v paměti. Výpis polí je proveden dvěma různými způsoby - klasicky a pomocí ukazatelové aritmetiky. Jsou rovněž pro ukázku použity různé funkce a způsoby pro výpis řetězců.

Nahoru Odpovědět
30.3.2022 11:52
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:30.3.2022 12:02

Super, díky za skvělou ukázku ;-) Šlo by nějak nadefinovat to textové pole s pevnou či max. délkou jednoho prvku 21 znaků (více se na řádek displeje) nevejde, abych nemusel počet znaků kontrolovat při zadání do programu ?

 
Nahoru Odpovědět
30.3.2022 12:02
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:30.3.2022 12:36

Ano, šlo. Tam už se pak "nepracuje" s ukazateli ale deklarace je 2D pole, kde druhý index udává maximální délku řádku. První počet řádků pochopitelně.. Práce s 2D polem se pak liší od práce s polem ukazatelů. Přiřazení, které bylo použito v předešlé ukázce zde možné není, a naopak v předešlé ukázce nelze použít to co bude v této ukázce.

Zde je opět krátká ukázka práce s řetězci tentokráte ve 2D pole:

#define _CRT_SECURE_NO_WARNINGS

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

#define ROW_LIMIT 21

int main(void) {
    char foods[][ROW_LIMIT + 1] = {
       "Sunka Bohemia",
       "Cesn syrova pomazanka",
       "Hermelin",
       "Smetana",
       "Pazitka",
       "Hovezi bujon tekuty"
    };

    size_t len = sizeof(foods) / sizeof(foods[0]);

    for (int i = 0; i < len; i++) puts(foods[i]);
    putchar('\n');

    // Chceme zmenit polozku "Pazitka" na "Porek" - OK
    if(strlen("Porek") <= ROW_LIMIT) strcpy(foods[4], "Porek");

    // Chceme upravit text pro Smetanu - k tomu nedojde
    if (strlen("Smetana - super tucna dobrota z Alberta") <= ROW_LIMIT)
        strcpy(foods[3], "Smetana - super tucna dobrota z Alberta");

    for (int i = 0; i < len; i++) puts(foods[i]);
    putchar('\n');

    // Ale da se to upravit takto
    if (strlen("Smetana - super tucna dobrota z Alberta") <= ROW_LIMIT)
        strcpy(foods[3], "Smetana - super tucna dobrota z Alberta");
    else memcpy(foods[3], "Smetana - super tucna dobrota z Alberta", ROW_LIMIT);

    for (int i = 0; i < len; i++) puts(foods[i]);

    return 0;
}
Nahoru Odpovědět
30.3.2022 12:36
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:30.3.2022 12:57

Samozřejmě můžeš vkládat text přímo:

// Ale da se to upravit takto
memcpy(foods[3], "Smetana - super tucna dobrota z Alberta", ROW_LIMIT);

To ale může způsobit, že se může na displeji zobrazovat stejný text pro dvě různé položky. Což může vést k nepříjemnostem. Můžeš použít lexikografické porovnání pomocí funkce strcmp(), které to může eliminovat. V ukázce to zahrnuto není, ale před vkládáním nové položky je třeba nějaký ten test provést.

Nahoru Odpovědět
30.3.2022 12:57
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Caster:30.3.2022 13:46

Díky, vyzkouším ;-)

 
Nahoru Odpovědět
30.3.2022 13:46
Avatar
Caster
Člen
Avatar
Caster:30.3.2022 16:25

Program jsem musel trochu upravit a přidat "const" před definicí pole jídel. Jinak mi to hlásilo chybu "Při převodu z řetězcového literálu se ztratí kvalifikátor const".

#include <iostream>

int8_t dny[6] = {
        -1,
        3,
        12,
        14,
        16,
        47
};


int main()
{
        const char* array[] = {
        "Sunka Bohemia",
        "Cesn syrova pomazanka",
        "Hermelin", "Smetana",
        "Pazitka",
        "Hovezi bujon tekuty"};

        int len = sizeof(array) / sizeof(array[0]);

        printf("Pocet retezcu v poli - %d\n\n", len);

        // Vypis pole
        for (int i = 0; i < len; i++) printf("%3d %s\n", dny[i], array[i]);
}
 
Nahoru Odpovědět
30.3.2022 16:25
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:30.3.2022 17:31

Ano, C++ je v tomto ohledu při práci s řetězcovými literály řekněme striktnější než C. 😊

Kód je v pořádku, snad jen několik drobností:

  • pracuješ v C++, používej pro výpis cour << když vkládáš iostream. Nebo vlož cstdio.h a používej standartní IO funkce jazyka C.
  • v inicializovaném poli měj každou položku na samostatném řádku. Teď to ale není důležité, finální aplikace bude mít úplně jinou podobu.
  • a nakonec udržuj data ucelená. Dny prošlosti budou součástí jídla. Bude se Ti tak s tím lépe pracovat.

Ve finální aplikací pak budeš mít objekt displej, kde jeho vlastnosti bude počet řádků, šířka řádku, a 2D pole typu char.

Nahoru Odpovědět
30.3.2022 17:31
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Caster:30.3.2022 22:08

Program už dělá to, co má ;-). Jen nevím jaký příkaz použít aby se zastavil a nemusel jsem ho nechat běžet v prázdné smyčce, když již není co vypisovat.

#include <iostream>
#include <windows.h>

const char* array[] = {
        "Sunka Bohemia",
        "Cesn syrova pomazanka",
        "Hermelin", "Smetana",
        "Pazitka",
        "Hovezi bujon tekuty"
};

int8_t dny[6] = {
        -1,
        3,
        12,
        14,
        16,
        47
};

int p = 0;      // Udává první položku pole pro výpis
int k;          // Pevná poslední položka výpisu
int d;          // Bude udávat počet položek po expiraci



int main()
{
        int len = sizeof(array) / sizeof(array[0]);
        k = len;

        printf("Pocet retezcu v poli - %d\n\n", len);

        while (len > 0) {
                // Vypis pole
                for (int i = p; i < k; i++) printf("%3d %s\n", dny[i], array[i]);
                printf("\n");

                Sleep(3000);    // Pauza 2 sekundy

                d = 0;
                // Expirace - 1
                for (int i = p; i < k; i++) {
                        --dny[i];
                        if (dny[i] < -3) {
                                //dny[i] = 0    // Nemusíme nulovat
                                //array[i] = "";// Nemusíme nulovat
                                d++;            // Daná potravina expirovala, příště ji již nebudeme expirovat
                        }
                }
                if (d > 0) {
                        len = len - d;          // Nějaké potraviny vyřadíme z výpisu (exp < -3)
                        p = p + d;              // Na displej začneme vypisovat potraviny po již expirovaných
                }
        }
        // Tady již expirovaly všechny potraviny a není co vypisovat
}
 
Nahoru Odpovědět
30.3.2022 22:08
Avatar
Caster
Člen
Avatar
Caster:31.3.2022 9:31

Vyřešeno, exit(0) ;-)

 
Nahoru Odpovědět
31.3.2022 9:31
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:31.3.2022 12:48

Celé to můžeš napsat jednodušeji..

int main(){
    int p = 0;
    int len = sizeof(array) / sizeof(array[0]);

    while (p < len) {
        for (int i = p; i < len; i++) printf("%3d %s\n", dny[i], array[i]);
        putchar('\n');
        Sleep(1000);
        for (int i = p; i < len; i++) {
            if (--dny[i] < -3) p++;
        }
    }
}
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
31.3.2022 12:48
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:31.3.2022 12:52

JJ díky, odpadla proměná "d", vyzkouším ;-).

 
Nahoru Odpovědět
31.3.2022 12:52
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 13 zpráv z 13.