Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Recensione HONOR Magic V6: spessore record e super batteria. È lui il fold da battere?
Recensione HONOR Magic V6: spessore record e super batteria. È lui il fold da battere?
HONOR Magic V6 è arrivato in Italia a 2.299,90 euro con una promessa precisa: unire 4 mm di spessore da aperto (8,75 mm chiuso nel modello White, 9 mm negli altri colori) a una batteria da 6.660 mAh, la più capiente mai vista su un pieghevole. Lo abbiamo usato per oltre una settimana in versione Red 16/512 GB per capire se lo Snapdragon 8 Elite Gen 5 tiene testa alla concorrenza anche fuori dai benchmark ufficiali
Redmi Pad 2 9.7: ampio display, economico e peso contenuto, ma qualche limite nelle prestazioni
Redmi Pad 2 9.7: ampio display, economico e peso contenuto, ma qualche limite nelle prestazioni
Redmi Pad 2 9.7 punta su un display ampio e fluido, una batteria capace di accompagnare l'uso quotidiano senza ansie da ricarica e un prezzo accessibile, a partire da 179,90 euro per la versione con 64 GB di storage. Lo Snapdragon 6s 4G Gen 2 e i 4 GB di RAM della configurazione più diffusa frenano però chi cerca reattività e multitasking spinto: ecco il bilancio dopo due settimane di prova diretta
Peugeot Polygon Concept: ecco il futuro delle utilitarie
Peugeot Polygon Concept: ecco il futuro delle utilitarie
Polygon è la concept car di Peugeot che mostra il futuro delle soluzioni del segmento B: tra design compatti e innovativi affiancati da dimensioni compatte uno scherzo dalla manovrabilità incredibile per le manovre a bassa velocità
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


Recensione HONOR Magic V6: spessore record e super batteria. È lui il fold da battere? Recensione HONOR Magic V6: spessore record e sup...
Redmi Pad 2 9.7: ampio display, economico e peso contenuto, ma qualche limite nelle prestazioni Redmi Pad 2 9.7: ampio display, economico e peso...
Peugeot Polygon Concept: ecco il futuro delle utilitarie Peugeot Polygon Concept: ecco il futuro delle ut...
Reno16 Pro: il compatto di OPPO punta su fotocamera da 200MP e il nuovo Bubble! La recensione Reno16 Pro: il compatto di OPPO punta su fotocam...
 Hisense 55U7SE: tuttofare e accessibile, il MiniLED per film, sport e gioco Hisense 55U7SE: tuttofare e accessibile, il Min...
Meta AI non userà più le f...
Stop ai giochi fisici su PlayStation: pe...
NVIDIA ha creato CUDA, ma una startup vu...
Il tallone d'Achille dei QD-LED è...
Apple pronta a produrre alcuni chip con ...
Anthropic proroga ancora Fable 5 gratis ...
SBS annuncia la nuova gamma Laptop con t...
Gli italiani sono interessati alla sicur...
Galaxy Watch 9, chip più veloce f...
Steam ha appena chiuso un semestre molto...
I nuovi iPhone 18 Pro potrebbero essere ...
Huawei realizzerà chip di nuova g...
La JAXA ha eseguito un test del prototip...
Netflix, ritorna la prova gratuita per i...
Il satellite LINK per salvare il telesco...
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: 07:53.


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