Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Insta360 Luna Ultra: la potenza del sensore da 1 pollice incontra la portabilità estrema
Insta360 Luna Ultra: la potenza del sensore da 1 pollice incontra la portabilità estrema
Insta360 Luna Ultra integra un sensore da 1 pollice 8K, ottiche Leica e triplo chip IA. Tra schermo OLED rimovibile, workflow I-Log a 10 bit e stabilizzazione a tre assi, analizziamo le doti tecniche di una gimbal camera pensata per i professionisti
Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa
Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa
Marvel's Wolverine porta Logan in un'avventura inedita, violenta e fortemente narrativa, costruita attorno alla sua natura di combattente e al difficile rapporto con il proprio passato. Insomniac Games punta su combattimenti spettacolari, progressione e personalizzazione, inserendo l'azione in un mondo segnato dalla persecuzione dei mutanti. Un viaggio intenso, che alterna mattanza, esplorazione e momenti sorprendentemente emotivi.
DJI Romo 2: tante novità lo rendono un robot completo
DJI Romo 2: tante novità lo rendono un robot completo
Romo 2 è la seconda generazione di robot lavapavimenti di DJI, un modello che si caratterizza per la precisione nel sistema di navigazione e per il funzionamento particolarmente silenzioso. Con le modifiche introdotte in questa seconda versione, e un posizionamento di prezzo più allineato alla concorrenza, rappresenta una valida alternativa sul mercato delle soluzioni di pulizia domestica
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 03-08-2009, 15:01   #1
Y3PP4
Member
 
Iscritto dal: Jul 2009
Messaggi: 210
[C] Problema nel ritorno di una stringa

Giorno a tutti, stò scrivendo un piccolo parser e tra i vari passi da seguire c'è quello di rimuovere i commenti e gli spazi bianchi (in modo da poter effettuare token senza problemi dei blank spaces).

Semplificando la funzione incriminata ho ricostruito il programma con la singola funzione e un main che la richiama.
L'algoritmo è molto semplice: tramite una switch inserita in una for che cicla i caratteri della riga elimina tabulazioni, blank spaces, e commenti.

Per verificare il funzionamento dell'algoritmo in sè ho modificato il programma facendogli direttamente mostrare i caratteri della stringa che non siano i suddetti da eliminare e tutto viene mostrato correttamente.
escaping2.c (codice funzionante ma non è ciò che mi serve - esegue solo l'algoritmo)
Codice PHP:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void EscapeStringchar *source )
{
    
unsigned int i
    
unsigned int isCommentLine 0/*on 1 the line will be discarded - is a comment line*/
    //char *bufString;
    
for( 0strlen(source); i++ )
    {
        switch( 
source[i] )
        {
            case 
'\t':
            case 
' ' :
                break;
            case 
'#' :
                
isCommentLine 1;
                break;
            default  :
                
printf("%c"source[i]);
                break;
        }
        if(
isCommentLine/* != 0"*/
        
{
            return;
        }
    }
    return;
/*EscapeString*/

int main()
{
    
char *string "this is a string #and this is a comment that will not show.";
    
EscapeString(string);
    return 
0;

Ma se invece voglio raccogliere in una stringa i caratteri non riesco proprio.
Ottengo sempre un segmentation fault e gdb si blocca sulla chiamata alla funzione, quindi è quella che non lavora a dovere.
Ora mostro lo stesso algoritmo che dovrebbe ritornare la stringa:
blank.c (segmentation fault)
Codice PHP:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CRLF
static char *EscapeStringchar *source )
{
    
unsigned int i
    
unsigned int isCommentLine 0/*on 1 the line will be discarded - is a comment line*/
    
char *bufString;
    for( 
0strlen(source); i++ )
    {
        switch( 
source[i] )
        {
            case 
'\t':
            case 
' ' :
                break;
            case 
'#' :
                
isCommentLine 1;
                break;
            default  :
                
bufString += source[i];
                break;
        }
        if(
isCommentLine/* != 0"*/
        
{
            return 
bufString;
        }
    }
    return 
bufString;
/*EscapeString*/

int main()
{
    
char *String "this is a string #and this is a comment that will not show.";
    
char *escapedString EscapeString(String);
    
printf("%s" CRLFescapedString);
    return 
0;

Premetto che una volta risolto questo problema la funzione userà questo prototipo:
static char *EscapeString( char *dest, char *source );
in modo da accettare come input anche la stringa in cui conservare la stringa elaborata ed evitare di scrivere questo poco elegante: char *escapedString = EscapeString(string); ma il problema è lo stesso.

Ringrazio chiunque saprà dirmi cosa sbaglio... è da sabato che ci sto lavorando sopra e ho spulciato tutto google ma non ne sono venuto a capo.
Ps. Ho provato con strcat e strcpy lavorando sui puntatori, ma stesso risultato.
Y3PP4 è offline   Rispondi citando il messaggio o parte di esso
Old 03-08-2009, 15:14   #2
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Quel
Codice:
                bufString += source[i];
purtroppo non esiste in C. Devi usare l'allocazione dinamica della stringa (ergo: malloc() e realloc()) e concatenare con strcat(), o aggiungere un carattere alla volta.
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 03-08-2009, 15:24   #3
Y3PP4
Member
 
Iscritto dal: Jul 2009
Messaggi: 210
Quote:
Originariamente inviato da DanieleC88 Guarda i messaggi
Quel
Codice:
                bufString += source[i];
purtroppo non esiste in C. Devi usare l'allocazione dinamica della stringa (ergo: malloc() e realloc()) e concatenare con strcat(), o aggiungere un carattere alla volta.
Lol imperdonabile errore.
Riguardo all'utilizzo di malloc() avevo già provato a effettuare un bel
Codice PHP:
char *bufString malloc(sizeof(source)); 
calcolando una lunghezza massima pari alla stringa di input (dato che si và a sottrarre non ad addizionare altri caratteri)
e poi usare strcat(bufString, source[i]) nel blocco default.
Ma ovviamente strcat si aspetta una puntatore costante di tipo char (const char *src).
Eseguo quindi il cast come segue:
Codice PHP:
strcat(bufString, (char *)source[i]); 
Ma il compilatore mi segnala un errore di tipo: warning: cast to pointer from integer of different size.
E indovina un po' ?
Segmentation fault. Sò qual'è il problema ma non son riuscito a risolverlo e tra i tanti test avevo testato quel +=.

Mille grazie per l'attenzione!
Ciao e buona giornata.
Y3PP4 è offline   Rispondi citando il messaggio o parte di esso
Old 03-08-2009, 15:54   #4
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Aspetta aspetta, qui stai facendo un po' di confusione e ti capisco, i puntatori fanno girare la testa a molti.

Allora, per calcolare la lunghezza in caratteri di una stringa non usare sizeof(p), dove p è il puntatore alla stringa. La grandezza esatta la trovi con:
Codice:
size_t uSize = (strlen(source) + 1) * sizeof(char);
Ovvero, un'area di memoria grande tanto quanto la grandezza di un singolo char (dato dal sizeof()), moltiplicata per la lunghezza della stringa originaria (data da strlen()) più uno (per il terminatore di stringa). Se usi semplicemente sizeof(source) otterrai sempre l'equivalente di sizeof(char *), perché quello è il tipo di source. Una cosa simile funzionerebbe soltanto su un'array di char.

Poi, strcat() si occupa di concatenare due stringhe, ma tu la chiami su una stringa e su un carattere (rispettivamente, char* e char), il che non è la stessa cosa. Per copiare solo un carattere nella stringa, ti consiglierei lavorare su di un indice e salvare il carattere che vuoi man mano che ti serve, abbozzo un po':
Codice:
char *sNewString = /* allocazione */;
unsigned uIndex = 0;

while (/* scansiona la stringa originale */)
{
    if (/* il carattere c è quello giusto */)
    {
        sNewString[uIndex++] = c;
    }
}
Insomma, puoi accodare così ogni nuovo carattere nella stringa.

ciao
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!

Ultima modifica di DanieleC88 : 03-08-2009 alle 15:57.
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 03-08-2009, 17:35   #5
Y3PP4
Member
 
Iscritto dal: Jul 2009
Messaggi: 210
Quote:
Originariamente inviato da DanieleC88 Guarda i messaggi
Aspetta aspetta, qui stai facendo un po' di confusione e ti capisco, i puntatori fanno girare la testa a molti.

Allora, per calcolare la lunghezza in caratteri di una stringa non usare sizeof(p), dove p è il puntatore alla stringa. La grandezza esatta la trovi con:
Codice:
size_t uSize = (strlen(source) + 1) * sizeof(char);
Ovvero, un'area di memoria grande tanto quanto la grandezza di un singolo char (dato dal sizeof()), moltiplicata per la lunghezza della stringa originaria (data da strlen()) più uno (per il terminatore di stringa).
Hai perfettamente ragione, ho commesso un'errore, ma adesso che me lo hai chiarito spero di non commetterlo in seguito.
Quote:
Originariamente inviato da DanieleC88 Guarda i messaggi
Se usi semplicemente sizeof(source) otterrai sempre l'equivalente di sizeof(char *), perché quello è il tipo di source. Una cosa simile funzionerebbe soltanto su un'array di char.
E qui si ho fatto un'errore coi puntatori, nel senso che io pensavo che essendo un char *name; un puntatore a una locazione di memoria che contiene una sequenza di char (come del resto gli array), una cosa simile avrebbe funzionato anche sul puntatore (che, forse erroneamente, pensavo si riferisse a un'array di char).
Quote:
Originariamente inviato da DanieleC88 Guarda i messaggi
Poi, strcat() si occupa di concatenare due stringhe, ma tu la chiami su una stringa e su un carattere (rispettivamente, char* e char), il che non è la stessa cosa. Per copiare solo un carattere nella stringa, ti consiglierei lavorare su di un indice e salvare il carattere che vuoi man mano che ti serve, abbozzo un po':
Codice:
char *sNewString = /* allocazione */;
unsigned uIndex = 0;

while (/* scansiona la stringa originale */)
{
    if (/* il carattere c è quello giusto */)
    {
        sNewString[uIndex++] = c;
    }
}
Insomma, puoi accodare così ogni nuovo carattere nella stringa.

ciao
Qui non mi è molto chiaro. Strcat() effettua una concatenazione. Prende due stringe in input ok, ma se una stringa fosse di un solo char dovrebbe funzionare lo stesso no? Quindi effettuando un cast all'ultimo secondo su un tipo char mi aspettavo funzionasse, ma evidentemente benchè l'abbia castata a char * non la riconosce come stringa ma come singolo carattere. Ed ora capisco anche a cosa si riferiva quell'errore che diceva casting to pointer from integer of different size.

Beh adesso provo il metodo che mi hai consigliato per lavorare su un singolo char alla volta.

Mille grazie e buona serata!
Y3PP4 è offline   Rispondi citando il messaggio o parte di esso
Old 03-08-2009, 17:53   #6
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Il tuo dubbio ulla strcat() viene dal fatto che in C non esiste un "tipo stringa", ma una stringa è semplicemente definita da un'area di memoria contenente dei caratteri e terminata da un carattere speciale (uno '\0'). Quindi un carattere singolo NON è una stringa: una stringa C contenente un solo carattere è in realtà una sequenza di due caratteri (il carattere più il terminatore).

Le funzioni standard del C che lavorano sulle stringhe presuppongono che ciò che ricevono in input sia un puntatore ad una stringa terminata da '\0'. Se non viene mai incontrato il terminatore, puoi sforare e leggere memoria inesistente o a cui non dovresti avere accesso. Il semplice cast da carattere a puntatore di caratteri significa che otterrai un puntatore con indirizzo pari al valore del carattere (quindi tra 0 e 255 inclusi), e non la memoria che ti aspetteresti.
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 03-08-2009, 18:24   #7
Y3PP4
Member
 
Iscritto dal: Jul 2009
Messaggi: 210
Bene, più o meno mi è chiaro. Nel senso che ho capito quello che hai detto, ma dato che l'unica differenza (come hai specificato, entrambe terminano con \0) è la sequenza di caratteri, non capisco perchè le funzioni che accettano le stringhe non l'accettano. Infondo sarebbe come dichiarare:
char *ciao = "a";
char ciao = "a";
char ciao[4] = "a";
tutte e tre sono viste come a\0 no?
Capisco il fatto del puntatore e che punta a una memoria di un singolo char, ma proprio a livello di memoria non capisco cosa cambia. char *ciao = "a" viene riconosciuta dalle funzione che accettano la stringa e char ciao = "a" no. Se non si basasse sul riconoscimento dei tipi, potrebbe accettarle senza problemi mi pare. Capisco che è cosi e boh (soprattutto poichè appunto si basa sul riconoscimento dei tipi) ed è un linguaggio molto vecchio (e quindi non una cosa fatta male) ma mi rimane sto chiodo fisso solo per pura curiosità. Il resto l'ho perfettamente capito .
Y3PP4 è offline   Rispondi citando il messaggio o parte di esso
Old 03-08-2009, 18:30   #8
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Quote:
Originariamente inviato da Y3PP4 Guarda i messaggi
Infondo sarebbe come dichiarare:
char *ciao = "a";
char ciao = "a";
char ciao[4] = "a";
tutte e tre sono viste come a\0 no?
Il primo e il terzo sì, il secondo no. Perché "a" diventa effettivamente "a\0", quindi una stringa definita in memoria e composta da due caratteri. Ora, per quel che ti ho spiegato prima, il compilatore assegna a ciò che sta a sinistra dell'assegnazione il puntatore alla stringa, ma nel secondo caso il tipo della variabile è char, ovverosia un valore intero di 1 byte (e non di 4 byte come sono i puntatori nelle architetture x86 a 32 bit), perciò si rifiuta di farlo senza segnalarti (giustamente) un errore. Non volevo scendere così "in basso" per spiegarti l'errore.

ciao
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 03-08-2009, 18:41   #9
Y3PP4
Member
 
Iscritto dal: Jul 2009
Messaggi: 210
Oh, finalmente mi è chiaro.
Mi spiace averti portato via così tanto tempo, ma a me non piacciono i dogmi e vorrei capire le varie cose, sia per curiosità sia perchè entrando nell'ottica che sta alla base di un ragionamento non solo riesco ad applicarlo meglio, ma riesco a ricordarlo con facilità e non si dimentica nel tempo.
Un po' come la matematica: se un esecizio ti viene spiegato con tanto di perchè delle operazioni lo ricordi meglio e più facilmente di quello in cui ti danno la formula e basta.



Mille grazie e buona serata.
Y3PP4 è offline   Rispondi citando il messaggio o parte di esso
Old 03-08-2009, 18:45   #10
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Figurati, fai strabenissimo a "scavare" per capire bene le cose. Non mi hai rubato tempo, altrimenti non ti avrei risposto...
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Insta360 Luna Ultra: la potenza del sensore da 1 pollice incontra la portabilità estrema Insta360 Luna Ultra: la potenza del sensore da 1...
Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa Marvel's Wolverine, la recensione: Logan torna p...
DJI Romo 2: tante novità lo rendono un robot completo DJI Romo 2: tante novità lo rendono un ro...
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED Sony Bravia 9 II: il True RGB alla prova, dove l...
Geely EX5, un mese al volante: il SUV elettrico cinese che ci ha sorpreso (quasi) senza riserve Geely EX5, un mese al volante: il SUV elettrico ...
Apple inserisce l'iMac 21,5 pollici del ...
GeForce RTX 6000: design a chiplet e arr...
Questi oggetti non dovrebbero esistere, ...
Un ESP32, un modulo ECG e un bottone cuc...
Grazie a un lancio preciso, il Nancy Gra...
Centrali elettriche libere di inquinare:...
Un razzo spaziale Vega C dell'italiana A...
Mozilla: i modelli IA aperti sono solo 4...
Intel e SK hynix al tavolo per un'allean...
Osservare la Luna con la NASA, anche in ...
Wallbox per auto elettriche su Amazon: d...
Il mistero della stagione degli uragani ...
La Corte di Cassazione affida i ricorsi ...
Tutti i nuovi prodotti Apple prenotabili...
DDR5, un kit da 598 a 1.215 euro in un m...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 12:11.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v