Oppure

Loading
06/11/15 10:52
AldoBaldo
Ciao a tutti.

Stavo cercando di aggiungere le funzioni template all'insieme delle mie (limitate) conoscenze, ma mi trovo di fronte a una cosa che non riesco a capire da solo. Ho già provato ad aggiungere un paio di bicchieri di buon rosso per rafforzare la capacità d'introspezione ma niente da fare -- il mistero non si dipana. :rotfl: Prima di cadere nella spirale senza fine dell'alcolismo provo a chiedere il vostro prezioso aiuto. La questione è questa...

Perché diavolo la funzione template CompattaArray() in questo codice funziona per i valori double e int e non per le stringhe const char * ?

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

template <class tipo> // prototipo della funzione template
unsigned int CompattaArray( tipo *a, unsigned int totEl,
                            bool fNullita(tipo*),
                            const tipo *nullo = NULL );

// prototipi delle funzioni di verifica
// delle condizioni di nullita' (esempi)
bool CondizioneNullitaPtr( const char *e );
bool CondizioneNullitaDouble( double *e );
bool CondizioneNullitaInt( int *e );

int main() {
    const unsigned int totEl = 6;
    unsigned int nElValidi = 0;

    // tutti i puntatori NULL vengono "cassati"
    // gli elementi "residui" vengono annullati
    const char *aPtr[totEl] = {"a","b",NULL,"c","d","e"};
    const char *nPtr = NULL;
    nElValidi = CompattaArray( aPtr, totEl, CondizioneNullitaPtr, &nPtr );
    for( unsigned int i=0; i<totEl; ++i )
        printf( "0x%08X\n", (unsigned int)aPtr[i] );
    printf( "%u elementi validi\n\n", nElValidi );

    // tutti i valori inferiori a 0.5 vengono "cassati";
    // gli elementi "residui" NON vengono annullati
    double aDouble1[totEl] = {1.0,0.5,0.0,0.49,2.76,0.54};
    nElValidi = CompattaArray( aDouble1, totEl, CondizioneNullitaDouble );
    for( unsigned int i=0; i<totEl; ++i )
        printf( "%f  ", aDouble1[i] );
    printf( "\n%u elementi validi\n\n", nElValidi );

    // tutti i valori inferiori a 0.5 vengono "cassati";
    // gli elementi "residui" vengono annullati
    double aDouble2[totEl] = {1.0,0.5,0.0,0.49,2.76,0.54};
    double nDouble = 0.0; // valore di annullamento double
    nElValidi = CompattaArray( aDouble2, totEl, CondizioneNullitaDouble, &nDouble );
    for( unsigned int i=0; i<totEl; ++i )
        printf( "%f  ", aDouble2[i] );
    printf( "\n%u elementi validi\n\n", nElValidi );

    // tutti i valori non compresi tra 5 e 10 vengono "cassati";
    // gli elementi "residui" vengono annullati
    int aInt[totEl] = {1,6,8,-2,10,11};
    int nInt = 0; // valore di annullamento int
    nElValidi = CompattaArray( aInt, totEl, CondizioneNullitaInt, &nInt );
    for( unsigned int i=0; i<totEl; ++i )
        printf( "%d  ", aInt[i] );
    printf( "\n%u elementi validi\n\n", nElValidi );

    return 0;
}

template <class tipo>
unsigned int CompattaArray( tipo *a, unsigned int totEl,
                            bool fNullita(tipo*),
                            const tipo *nullo ) {
    unsigned int i, j;

    for( i=j=0; i<totEl; ++i )
        if( !fNullita(&(a[i])) )
            a[j++] = a[i];

    if( nullo )
        for( i=j; i<totEl; ++i )
            a[i] = *nullo;

    return j; // la quantita' degli elementi non nulli
              // "raggruppati" in testa all'array
}

bool CondizioneNullitaPtr( const char *e ) {
    // CompattaArray() elimina tutti i puntatori NULL
    return e == NULL;
}

bool CondizioneNullitaDouble( double *e ) {
    // CompattaArray() elimina tutti i valori inferiori a 0.5
    return *e < 0.5;
}

bool CondizioneNullitaInt( int *e ) {
    // CompattaArray() elimina tutti i valori non compresi tra 5 e 10
    return *e < 5 || *e > 10;
}


Il compilatore mastica tutto, quindi sputa fuori questa odiosa raffica di sentenze, secondo me con la chiara intenzione di denigrare i miei sforzi con una palese dose di sadismo:

||=== Build: Release in Prova fTemplate (compiler: GNU GCC Compiler) ===|
\main.cpp||In function 'int main()':|
\main.cpp|23|error: no matching function for call to 'CompattaArray(const char* [6], const unsigned int&, bool (&;)(const char*), const char**)'|
\main.cpp|23|note: candidate is:|
\main.cpp|5|note: template<class tipo> unsigned int CompattaArray(tipo*, unsigned int, bool (*)(tipo*), const tipo*)|
\main.cpp|5|note: template argument deduction/substitution failed:|
\main.cpp|23|note: deduced conflicting types for parameter 'tipo' ('const char*' and 'const char')|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

(Ho eliminato tutti i riferimenti al percorso del file main.cpp, per sintetizzare, tanto sono irrilevanti in questo contesto.)

Credo che la chiave possa essere in quel conflicting types for parameter 'tipo', ma non capisco da cosa possa nascere il conflitto. Il compilatore non dovrebbe sostituire "tipo" con "const char*" e accettare aPtr (l'array di stringhe const char* in main) come un puntatore ad un array di const char*, ovvero come tipo* ? Non dovrebbe valere la stessa cosa anche per nPtr? No, pare proprio di no, ma non capisco perché. Sto già versando il terzo bicchiere di rosso.
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.
06/11/15 11:15
Roby94
Se provi con un semplice puntatore a char il compilatore fa ancora storie?
aaa
06/11/15 12:35
AldoBaldo
Non credo che troverebbe differenze tra un puntatore che punta a un array di char e un puntatore che punta ad un array di int o di double. Le apparenze mi portano a ipotizzare che la soluzione sia nascosta da qualche parte nel modo in cui viene interpretato il puntatore che punta a un array di puntatori a (const) char...

Edit: Ho effettivamente provato, il codice che segue funziona benissimo.

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

template <class tipo> // prototipo della funzione template
unsigned int CompattaArray( tipo *a, unsigned int totEl,
                            bool fNullita(tipo*),
                            const tipo *nullo = NULL );

// prototipi delle funzioni di verifica
// delle condizioni di nullita' (esempi)
bool CondizioneNullitaChar( char *e );

int main() {
    const unsigned int totEl = 6;
    unsigned int nElValidi = 0;

    // tutti i valori non compresi tra 'c' e 'f' vengono "cassati";
    // gli elementi "residui" vengono annullati
    char aChar[totEl] = "acudi";
    char nChar = 'Non credo che troverebbe differenze tra un puntatore che punta a un array di char e un puntatore che punta ad un array di int o di double. Le apparenze mi portano a ipotizzare che la soluzione sia nascosta da qualche parte nel modo in cui viene interpretato il puntatore che punta a un array di puntatori a (const) char...


Edit: Ho effettivamente provato, il codice che segue funziona benissimo.

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

template <class tipo> // prototipo della funzione template
unsigned int CompattaArray( tipo *a, unsigned int totEl,
                            bool fNullita(tipo*),
                            const tipo *nullo = NULL );

// prototipi delle funzioni di verifica
// delle condizioni di nullita' (esempi)
bool CondizioneNullitaChar( char *e );

int main() {
    const unsigned int totEl = 6;
    unsigned int nElValidi = 0;

    // tutti i valori non compresi tra 'c' e 'f' vengono "cassati";
    // gli elementi "residui" vengono annullati
    char aChar[totEl] = "acudi";
    char nChar = '{parsed_message}'; // valore di annullamento char
    nElValidi = CompattaArray( aChar, totEl, CondizioneNullitaChar, &nChar );
    printf( "%s", aChar );
    printf( "\n%u elementi validi\n\n", nElValidi );
	
    return 0;
}

template <class tipo>
unsigned int CompattaArray( tipo *a, unsigned int totEl,
                            bool fNullita(tipo*),
                            const tipo *nullo ) {
    unsigned int i, j;

    for( i=j=0; i<totEl; ++i )
        if( !fNullita(&(a[i])) )
            a[j++] = a[i];

    if( nullo )
        for( i=j; i<totEl; ++i )
            a[i] = *nullo;

    return j; // la quantita' degli elementi non nulli
              // "raggruppati" in testa all'array
}

bool CondizioneNullitaChar( char *e ) {
    // CompattaArray() elimina tutti i valori non compresi tra 'c' e 'f'
    return *e < 'c' || *e > 'f';
}
'; // valore di annullamento char nElValidi = CompattaArray( aChar, totEl, CondizioneNullitaChar, &nChar ); printf( "%s", aChar ); printf( "\n%u elementi validi\n\n", nElValidi ); return 0; } template <class tipo> unsigned int CompattaArray( tipo *a, unsigned int totEl, bool fNullita(tipo*), const tipo *nullo ) { unsigned int i, j; for( i=j=0; i<totEl; ++i ) if( !fNullita(&(a[i])) ) a[j++] = a[i]; if( nullo ) for( i=j; i<totEl; ++i ) a[i] = *nullo; return j; // la quantita' degli elementi non nulli // "raggruppati" in testa all'array } bool CondizioneNullitaChar( char *e ) { // CompattaArray() elimina tutti i valori non compresi tra 'c' e 'f' return *e < 'c' || *e > 'f'; }
Ultima modifica effettuata da AldoBaldo 06/11/15 12:52
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.
06/11/15 12:56
TheDarkJuster
Usi l'operatore di stringa " per un array di caratteri : che usano l'operatore '. Per fare "a", "b" to serve const char **lista non char *lista.
Inoltre specificare il numero di elementi mentre inizializzi un array è una pratica abbastanza discutibile.
aaa
06/11/15 13:12
AldoBaldo
Sì, sono dettagli che conosco, solo che non sempre li tengo in considerazione. Avrei effettivamente potuto scrivere così:

    // tutti i valori non compresi tra 'c' e 'z' vengono "cassati";
// gli elementi "residui" vengono annullati
char aChar[totEl] = {'a','c','u','d','i','Sì, sono dettagli che conosco, solo che non sempre li tengo in considerazione. Avrei effettivamente potuto scrivere così:


    // tutti i valori non compresi tra 'c' e 'z' vengono "cassati";
// gli elementi "residui" vengono annullati
char aChar[totEl] = {'a','c','u','d','i','{parsed_message}'};
char nChar = '{parsed_message}'; // valore di annullamento char

nElValidi = CompattaArray( aChar, totEl, CondizioneNullitaChar, &nChar );

for( unsigned int i=0; i<totEl; ++i )
    if( aChar[i] != '{parsed_message}' )
        printf( "%c ", aChar[i] );
    else printf( "\'\0\' " );

printf( "\n%u elementi validi\n\n", nElValidi );


Nei termini dell'errore che ho illustrato originariamente non cambia nulla, non credo proprio che l'errore sia lì.

L'aggiunta esplicita della quantità degli elementi dell'array è una scelta che ho fatto perché, siccome sto "sperimentando", volevo essere sicuro di non incorrere in errori nella quantificazione degli elementi nelle varie prove.'}; char nChar = 'Sì, sono dettagli che conosco, solo che non sempre li tengo in considerazione. Avrei effettivamente potuto scrivere così:

    // tutti i valori non compresi tra 'c' e 'z' vengono "cassati";
// gli elementi "residui" vengono annullati
char aChar[totEl] = {'a','c','u','d','i','{parsed_message}'};
char nChar = '{parsed_message}'; // valore di annullamento char

nElValidi = CompattaArray( aChar, totEl, CondizioneNullitaChar, &nChar );

for( unsigned int i=0; i<totEl; ++i )
    if( aChar[i] != '{parsed_message}' )
        printf( "%c ", aChar[i] );
    else printf( "\'\0\' " );

printf( "\n%u elementi validi\n\n", nElValidi );


Nei termini dell'errore che ho illustrato originariamente non cambia nulla, non credo proprio che l'errore sia lì.

L'aggiunta esplicita della quantità degli elementi dell'array è una scelta che ho fatto perché, siccome sto "sperimentando", volevo essere sicuro di non incorrere in errori nella quantificazione degli elementi nelle varie prove.'; // valore di annullamento char nElValidi = CompattaArray( aChar, totEl, CondizioneNullitaChar, &nChar ); for( unsigned int i=0; i<totEl; ++i ) if( aChar[i] != 'Sì, sono dettagli che conosco, solo che non sempre li tengo in considerazione. Avrei effettivamente potuto scrivere così:

    // tutti i valori non compresi tra 'c' e 'z' vengono "cassati";
// gli elementi "residui" vengono annullati
char aChar[totEl] = {'a','c','u','d','i','{parsed_message}'};
char nChar = '{parsed_message}'; // valore di annullamento char

nElValidi = CompattaArray( aChar, totEl, CondizioneNullitaChar, &nChar );

for( unsigned int i=0; i<totEl; ++i )
    if( aChar[i] != '{parsed_message}' )
        printf( "%c ", aChar[i] );
    else printf( "\'\0\' " );

printf( "\n%u elementi validi\n\n", nElValidi );


Nei termini dell'errore che ho illustrato originariamente non cambia nulla, non credo proprio che l'errore sia lì.

L'aggiunta esplicita della quantità degli elementi dell'array è una scelta che ho fatto perché, siccome sto "sperimentando", volevo essere sicuro di non incorrere in errori nella quantificazione degli elementi nelle varie prove.' ) printf( "%c ", aChar[i] ); else printf( "\'\0\' " ); printf( "\n%u elementi validi\n\n", nElValidi );


Nei termini dell'errore che ho illustrato originariamente non cambia nulla, non credo proprio che l'errore sia lì.

L'aggiunta esplicita della quantità degli elementi dell'array è una scelta che ho fatto perché, siccome sto "sperimentando", volevo essere sicuro di non incorrere in errori nella quantificazione degli elementi nelle varie prove.
Ultima modifica effettuata da AldoBaldo 06/11/15 13:13
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.
06/11/15 14:44
TheDarkJuster
Ma tu hai una funzione che accetta un puntatore, non un puntatore a puntatore.
aaa
06/11/15 21:51
lumo

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

template <class tipo> // prototipo della funzione template
unsigned int CompattaArray(tipo *a, unsigned int totEl,
	bool fNullita(tipo*),
	const tipo *nullo = NULL);

// prototipi delle funzioni di verifica
// delle condizioni di nullita' (esempi)
bool CondizioneNullitaPtr(char **e);
bool CondizioneNullitaDouble(double *e);
bool CondizioneNullitaInt(int *e);

int main() {
	const unsigned int totEl = 6;
	unsigned int nElValidi = 0;

	// tutti i puntatori NULL vengono "cassati"
	// gli elementi "residui" vengono annullati
	char *aPtr[totEl] = { "a","b",NULL,"c","d","e" };
	char *nPtr = NULL;
	nElValidi = CompattaArray(aPtr, totEl, CondizioneNullitaPtr, &nPtr);
	for (unsigned int i = 0; i<totEl; ++i)
		printf("0x%08X\n", (unsigned int)aPtr[i]);
	printf("%u elementi validi\n\n", nElValidi);

	// tutti i valori inferiori a 0.5 vengono "cassati";
	// gli elementi "residui" NON vengono annullati
	double aDouble1[totEl] = { 1.0,0.5,0.0,0.49,2.76,0.54 };
	nElValidi = CompattaArray(aDouble1, totEl, CondizioneNullitaDouble);
	for (unsigned int i = 0; i<totEl; ++i)
		printf("%f  ", aDouble1[i]);
	printf("\n%u elementi validi\n\n", nElValidi);

	// tutti i valori inferiori a 0.5 vengono "cassati";
	// gli elementi "residui" vengono annullati
	double aDouble2[totEl] = { 1.0,0.5,0.0,0.49,2.76,0.54 };
	double nDouble = 0.0; // valore di annullamento double
	nElValidi = CompattaArray(aDouble2, totEl, CondizioneNullitaDouble, &nDouble);
	for (unsigned int i = 0; i<totEl; ++i)
		printf("%f  ", aDouble2[i]);
	printf("\n%u elementi validi\n\n", nElValidi);

	// tutti i valori non compresi tra 5 e 10 vengono "cassati";
	// gli elementi "residui" vengono annullati
	int aInt[totEl] = { 1,6,8,-2,10,11 };
	int nInt = 0; // valore di annullamento int
	nElValidi = CompattaArray(aInt, totEl, CondizioneNullitaInt, &nInt);
	for (unsigned int i = 0; i<totEl; ++i)
		printf("%d  ", aInt[i]);
	printf("\n%u elementi validi\n\n", nElValidi);
	getchar();
	return 0;
}

template <class tipo>
unsigned int CompattaArray(tipo *a, unsigned int totEl,
	bool fNullita(tipo*),
	const tipo *nullo) {
	unsigned int i, j;

	for (i = j = 0; i<totEl; ++i)
		if (!fNullita(&a[i]))
			a[j++] = a[i];

	if (nullo)
		for (i = j; i<totEl; ++i)
			a[i] = *nullo;

	return j; // la quantita' degli elementi non nulli
			  // "raggruppati" in testa all'array
}

bool CondizioneNullitaPtr(char **e) {
	// CompattaArray() elimina tutti i puntatori NULL
	return *e == NULL;
}

bool CondizioneNullitaDouble(double *e) {
	// CompattaArray() elimina tutti i valori inferiori a 0.5
	return *e < 0.5;
}

bool CondizioneNullitaInt(int *e) {
	// CompattaArray() elimina tutti i valori non compresi tra 5 e 10
	return *e < 5 || *e > 10;
}



P.S.: di solito le funzioni come quelle vengono passate a loro volta come parametro di template :D
aaa
06/11/15 22:20
TheDarkJuster
Lumo hai definito la funzione condizione nullità ptr perché la funzione funzionava con un solo puntatore e non un puntatore a puntatore?
O ci sono modifiche che mi sfuggono?
aaa