Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Idea bislacca per stringhe dinamiche in C
Forum - C/C++ - Idea bislacca per stringhe dinamiche in C

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 18:13
Domenica, 10/05/2020
Ieri m'è balenata un'idea bislacca per poter disporre in qualche modo di stringhe dinamiche in C da usare anche come stringhe comuni. L'idea e' questa...

Appurato che una stringa allocata in memoria dinamica è individuata da un puntatore char*, e che quel puntatore arriva da malloc(), calloc() o realloc() sotto forma di void*, e che una stringa dinamica dovrebbe disporre sostanzialmente di un valore per la lunghezza corrente e uno per la capacità massima, aggiungendo un terzo valore per usarlo come "firma" del mio tipo di stringa particolare, mi son detto...

...perché non mettere i dati in questione PRIMA del puntatore ai char* veri e propri, con dei fattori di scostamento negativi per reperirli? in questo modo potrei evitare di creare un tipo dati sotto forma di struttura con i campi necessari, sostituendoli sostanzialmente con un unico array di char.

Con un disegnino, potrei rappresentare la situazione come si vede nell'allegato.

Avendo typedef char* dStr; sarebbe possibile usare direttamente le dStr come comuni stringhe con le funzioni standard del C, e fare cose tipo...

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include "d_str.h"
  3.  
  4. int main() {
  5.     dStr ds;
  6.  
  7.     ds = dStr_CreateCopyCString( "Prima" );
  8.  
  9.     if( ds ) {
  10.         int ok;
  11.  
  12.         printf( "\"%s\" (%u caratteri)\n", ds, dStr_GetLength(ds) );
  13.  
  14.         ok = dStr_AppendCString( &ds, " dopo" );
  15.  
  16.         if( ok )
  17.             printf( "\"%s\" (%u caratteri)\n", ds, dStr_GetLength(ds) );
  18.  
  19.         ds = dStr_Destroy( ds );
  20.     }
  21.  
  22.     ds = dStr_Create( 256 );
  23.  
  24.     if( ds ) {
  25.         printf( "\"%s\" (%u caratteri)\n", ds, dStr_GetLength(ds) );
  26.  
  27.         strcpy( ds, "Prima" );
  28.         strcat( ds, " dopo" );
  29.         dStr_UpdateLength( ds );
  30.  
  31.         printf( "\"%s\" (%u caratteri)\n", ds, dStr_GetLength(ds) );
  32.  
  33.         ds = dStr_Destroy( ds );
  34.     }
  35.  
  36.     return 0;
  37. }



AldoBaldo ha allegato un file: schema.png (58333 bytes)
Clicca qui per guardare l'immagine


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 18:14
Domenica, 10/05/2020
Il codice, con i commenti, è lunghetto, quindi per non "intasare" questa pagina lo inserisco come allegato.


AldoBaldo ha allegato un file: d_str.zip (5708 bytes)
Clicca qui per scaricare il file


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 21:27
Domenica, 10/05/2020
Vuoi reinventare le BSTR di OLE COM di Microsoft?

Arrivato tardi ...

https://docs.microsoft.com/en-us/previous-versions/windows/ ...


Ultima modifica effettuata da nessuno il 10/05/2020 alle 21:28


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 22:16
Domenica, 10/05/2020
Non so neppure cosa siano, le BSTR, ad essere proprio sinceri. C'è una parentela? Vado a vedere.
OLE COM è una sigla che ho letto non so quante volte nella documentazione della quale dispongo, ma non sono mai riuscito a capire veramente in cosa consista. Visto che mi ci indirizzi, vedo anche quello, almeno per averne un'idea di massima.

Nel frattempo, ho trovato e sistemato un paio di schifezze (molto probabilmente introducendone altre, per buona misura). Ad esempio, finché non ho attivato la modalità "pedantic" del "warning", il compilatore accettava zitto zitto una cosa che non pensavo fosse "sconveniente", cioè "spostare" aritmeticamente dei void*. Se lo segna come "warning" vorrà dire che non è un errore, ma una possibile fonte di errori della quale non ho mai letto sui testi sui quali ho studiato (tanti anni fa). Comunque ho eliminato i warning spargendo qua e là cast come fossero concime, trasformando i puntatori in semplici valori numerici di tipo size_t.

Inoltre, ho trovato un errore grave che mandava tutto in palla nel momento in cui si cercava di aggiungere/inserire una stringa in se stessa. Non si trattava di un errore nel codice, ma proprio nella logica dell'operazione. Risolto con un semplice flag e un'assegnazione "strategica" in una sola funzione alla quale si appoggiano molte altre, ma mi era proprio sfuggito.

EDIT: Ho letto la pagina che descrive il concetto di massima di BSTR. Be', trovo lusinghiero che in Microsoft abbiano avuto un'idea simile a quella che è venuta in mente a me senza averne mai sentito parlare! Vuol dire che non è un'idea così disastrosa, no? Comunque ci sono delle differenze. Ad esempio, io non uso caratteri a due byte, ma a byte singolo. Inoltre aggiungo nell'intestazione altri due dati: un identificatore (che spero possa ridurre la possibilità di usare malamente quel tipo di stringa) e un dato che memorizza la capienza massima del buffer nel quale è contenuta la stringa. E ancora... nella pagina introduttiva non ho trovato cenno al fatto che quelle stringhe siano dinamiche, nè che possano essere usate "in parallelo" con string.h. Magari leggendo più a fondo salta fuori che han già fatto anche quello, chissà. Vado a vedere cos'è OLE COM.

EDIT 2: Bene, ho letto su stackoverflow una pagina descrittiva su OLE e su COM. Il concetto non mi era estraneo, ma non ho mai preso in considerazione l'idea di usare quel tipo di caratteristica, quindi non sapevo che rientrasse sotto quella denominazione. Certo è che se dovessi provare a metterci le mani avrei non pochi grattacapi, perché mi sa che dev'essere un materiale non proprio "lineare"...


AldoBaldo ha allegato un file: d_str.zip (5765 bytes)
Clicca qui per scaricare il file

Ultima modifica effettuata da AldoBaldo il 10/05/2020 alle 22:39


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 22:30
Domenica, 10/05/2020
Un altro esempio di uso di dStr. Non fa niente di utile, mi è servito per fare un po' di test. Ho scoperto il difetto grave quando ho tentato di inserire nel ciclo for dStr_Append(&s1,s1) -- copiare s1 in coda a se stessa faceva "esplodere" tutto per via di un bel pastrocchio con i puntatori in fase di riallocazione.

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include "d_str.h"
  3.  
  4. const char kStrErr[] = "Errore!\n";
  5.  
  6. void mostra( dStr s ) {
  7.     if( s ) {
  8.         printf( "Validita': %s\n", dStr_IsValid(s)?"si":"no" );
  9.         printf( "Contenuto: \"%s\"\n", s );
  10.         printf( "Lunghezza: %u\n", dStr_GetLength(s) );
  11.         printf( "Capacita': %u\n\n", dStr_GetCapacity(s) );
  12.     } else puts( "dStr NULL\n\n" );
  13. }
  14.  
  15. int main() {
  16.     dStr s1 = NULL;
  17.     dStr s2 = NULL;
  18.  
  19.     // crea una stringa dinamica vuota,
  20.     // con spazio utile per 40 caratteri
  21.     // e un terminatore
  22.     s1 = dStr_Create( 40 );
  23.  
  24.     // crea una seconda stringa dinamica,
  25.     // con dimensioni adatte a contenere
  26.     // esattamente la stringa C passata
  27.     s2 = dStr_CreateCopyCStr( ", e poi un'altra" );
  28.  
  29.     if( s1 && s2 ) { // la creazione e' riuscita?
  30.         int i, ok;
  31.  
  32.         mostra(s1);
  33.  
  34.         // copia una stringa C in s1
  35.         // la capacita' di s1 resta 40
  36.         ok = dStr_CopyCStr( &s1, "Una" );
  37.         if( ok ) mostra(s1); else puts( kStrErr );
  38.  
  39.         // aggiunge per 5 volte una stessa stringa
  40.         // C in coda ad s1; quando la lunghezza della
  41.         // stringa risultante supera i 40 caratteri,
  42.         // la capacita' della stringa dinamica viene
  43.         // incrementata quanto basta
  44.         for( i=0; i<3; ++i ) {
  45.             if( dStr_Append(&s1,s2) ) mostra(s1);
  46.             else { puts( kStrErr ); break; }
  47.         }
  48.  
  49.         // senza modificare il testo contenuto,
  50.         // aumenta la capacita' della stringa dinamica
  51.         ok = dStr_Resize( &s1, 256 );
  52.         if( ok ) mostra(s1); else puts( kStrErr );
  53.  
  54.         // usa direttamente s1 con strcat(), per
  55.         // aggiungere tre puntini; si crea una
  56.         // discrepanza tra la lunghezza del testo
  57.         // contenuto in s1 e la lunghezza registrata
  58.         // nel "campo" apposito
  59.         strcat( s1, "..." );
  60.         mostra( s1 );
  61.         printf( "Il testo in s1 ha in realta' %u caratteri.\n\n", strlen(s1) );
  62.  
  63.         // "riallinea" la lunghezza del testo
  64.         // contenuto in s1 e la lunghezza registrata
  65.         // nel "campo" apposito
  66.         ok = dStr_UpdateLength( s1 );
  67.         if( ok ) mostra(s1); else puts( kStrErr );
  68.  
  69.         // elimina lo spazio disponibile in s1
  70.         // per la parte che eccede la lunghezza del
  71.         // testo contenuto
  72.         ok = dStr_Minimize( &s1 );
  73.         if( ok ) mostra(s1); else puts( kStrErr );
  74.     } else puts( kStrErr ); // creazione fallita
  75.  
  76.     // se esistono, distrugge s1 e s2
  77.     s1 = dStr_Destroy( s1 );
  78.     s2 = dStr_Destroy( s2 );
  79.  
  80.     return 0;
  81. }



ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
Goblin (Member)
Expert


Messaggi: 375
Iscritto: 02/02/2011

Segnala al moderatore
Postato alle 23:21
Domenica, 10/05/2020
Come mi dispiace (rosiko) di non "masticare" il C (sono depresso :P )... è una discussione interessante, ma molto distante dal  mio "sapere", cmq ho letto tutto, e seguo ...
G.


Ibis redibis non morieris in bello
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 7:00
Lunedì, 11/05/2020
Le BSTR sono Unicode perche' non ha senso oggi come oggi (a parte gli esercizietti per la didattica) usare stringhe che non lo siano. Ed erano Unicode tanto tempo fa. Sono praticamente le stringhe che internamente usava VB6.

Il prefisso con la lunghezza e' sufficiente, tutto il resto mi sembra proprio inutile. E' ovvio che l'allocazione e' dinamica come potrebbe essere diversamente?

Divertiti, io continuero' ad usare la SysAllocString e le BSTR anche se OLE COM sta per essere completamente soppiantato da .NET

Comunque se vuoi avere un'idea di cosa gia' esiste e si usa nel campo professionistico e da molto tempo

https://docs.microsoft.com/it-it/previous-versions/windows/ ...

https://docs.microsoft.com/it-it/previous-versions/windows/ ...

https://docs.microsoft.com/it-it/previous-versions/windows/ ...

Ultima modifica effettuata da nessuno il 11/05/2020 alle 7:48


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 9:31
Lunedì, 11/05/2020
Di essere professionale non mi interessa nulla, in questo campo, però sono curioso e senz'altro leggerò quel che mi hai indicato. Non ora, che sto lavorando. Grazie per i suggerimenti. Se riguardano caratteristiche datate, magari trovo le stesse informazioni anche sulla documentazione che ho sul mio disco rigido, il che sarebbe molto più comodo. In caso siano "avvicinabili" per il mio livello, magari finirò pure per usare quel che viene descritto.

Dopo aver letto, saprò (forse) farmi un'idea di quanto utili o inutili possano essere i due "campi" in più che ho messo nelle mie stringhette. Secondo me quello che riguarda la "capacità" proprio inutile non è, ma vedremo. Inoltre ho come la sensazione che le stringhe usate come BSTR non siano compatibili con le funzioni in string.h (è giusto una "sensazione", vedrò leggendo).

Una cosa so per certo: per i miei scopi i 256 caratteri dell'ASCII esteso sono più che sufficienti. Non che voglia snobbare le altre soluzioni, ma ognuno compra le scarpe in relazione alla misura dei propri piedi, non di quelli altrui. ;)


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 9:45
Lunedì, 11/05/2020
Il problema è che le librerie si scrivono per i piedi altrui non per i tuoi


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo