Visual Studio 2017 - C++ Errore di compilazione prodotto fra double e int


#1

Rieccomi qui, questa volta il problema non riguarda gli esercizi ma un esempio svolto all’interno della lezione (con gli esercizi sono un “pelino” indietro rispetto alle lezioni, my bad, ma sto cercando di capire meglio come diamine funzionano i puntatori e andare avanti con le lezioni vedendo come si utilizzano mi è d’aiuto).

Sto seguendo le lezioni relative alle linked list e l’esempio svolto simula un programma gestionale per l’emissione di uno scontrino. Ho l’abitudine di “ricopiare” il codice scritto durante la lezione invece che scaricare il progetto bello, pronto e compilante, proprio per capire dove commetto errori e assimilare meglio i concetti.

Il codice è questo:

#include "stdafx.h"
#include <iostream>

using namespace std;

struct t_riga_scontrino;

struct t_scontrino {
	string data;
	int codice_punto_vendita;
	string codice_cassa;

	t_riga_scontrino *head; // Il puntatore *head rappresenta l'indirizzo del primo nodo lista righe scontrino
};

struct t_riga_scontrino {
	int codice_prodotto;
	double qta;
	double prezzo;

	t_riga_scontrino *next; // Il puntatore *next rapprensenta l'indirizzo della riga successiva o nullptr se è l'ultima riga
};

void ins_testa(t_riga_scontrino* &head, t_riga_scontrino* nuovo) { // si può usare un template per generalizzare la funzione
	nuovo->next = head;
	head = nuovo;
}

void ins_coda(t_riga_scontrino* &head, t_riga_scontrino* nuovo) {
	t_riga_scontrino *cerca_fine_lista = head;

	if (head == nullptr)	// se la lista è vuota si usa l'inserimento in testa per il primo nodo
		ins_testa(head, nuovo);	
	else {
		// ricerco la fine della lista
		// obiettivo: fermarsi quando cerca_fine_lista	e' sull'ultimo nodo
		//			  cioè sul nodo che ha nullptr come next
		while (cerca_fine_lista->next != nullptr)
			cerca_fine_lista = cerca_fine_lista->next;

		cerca_fine_lista->next = nuovo;
		nuovo->next = nullptr;
	}
}

void stampa_righe_scontrino(t_riga_scontrino* head) {
	t_riga_scontrino *scorri = head;

	while (scorri != nullptr) {
		cout << "--------\n";
		cout << "Codice Prodotto: " << scorri->codice_prodotto << endl;
		cout << "Quantita': " << scorri->qta << endl;
		cout << "Prezzo: " << scorri->prezzo << endl;

		scorri = scorri->next;
	}
}


int main()
{
	t_scontrino *scontrino = new t_scontrino { "19/12/2017", 123, "CassaL1", nullptr };
	
	// simulo l'emissione dello scontrino con un ciclo for
	// legando i parametri della struct con il contatore i
	for (int i = 0; i < 10; i++) {
		t_riga_scontrino *nuovo = new t_riga_scontrino{ i, 10 * i, 100.0 * i}; // L'errore è in questa riga
		ins_coda(scontrino->head, nuovo);
	}

	stampa_righe_scontrino(scontrino->head);

    return 0;
}

Quando compilo ho un solo errore che fa riferimento alla conversione da int a double e che non ha senso. Questa conversione avviene all’interno del ciclo for usato per riempire la lista. In questo ciclo lego il codice del prodotto, la quantità e il prezzo (questi ultimi due sono double) al contatore del ciclo (int). L’errore è il seguente:

Errore	C2397	la conversione da 'int' a 'double' richiede una conversione verso un tipo di dati più piccolo	

Ho spulciato su internet e da quello che ho visto questo errore salta fuori, giustamente, quando si vuole convertire un tipo di dati più grande in uno più piccolo (double-int, int-short, etc), non ho trovato nessun riscontro su questo errore in un caso simile al mio.

Qualche idea?


#3

a che riga è l’errore segnalato dal compilatore?

Da quel poco che ricordo (e sono davvero arrugginito) mi sovvengono alcune idee, probabilmente sbagliate:

  • non puoi fare alcune operazioni tra int e double, devi prima convertire entrambe le var in int o double
  • forse double è troppo lungo, prova a usare float invece
  • smetti di leggermi e aspetta che passi un dev

probabilmente l’ultimo è il consiglio migliore :old_doh:

(e io dovrei tornare a studiare =)


#4

Nel codice ho aggiunto un commento alla riga :smile:
È la prima riga delle istruzioni del ciclo for nel main

t_riga_scontrino *nuovo = new t_riga_scontrino{ i, 10 * i, 100.0 * i}; // L'errore è in questa riga

In questi giorni ho provato anche con il cast a double. Niente.
Se dichiaro entrambe le variabili come int invece funziona. Immagino anche se le dichiaro entrambe double, ma usare un double per il contatore di un ciclo in un esercizio mi sembra uno spreco, non perché influenzi più di tanto il consumo di memoria (in questo caso soprattutto) ma proprio a livello concettuale.

Ma l’errore dice l’esatto contrario. È questa la cosa assurda, dice che convertire da int a double richiede una conversione verso un tipo di dati più piccolo. Quando mai un double è più piccolo di un int?!
Mi sa che il compilatore di Visual Studio è ubriaco :old_ubriaconi:

PS: domani mi sa che vi rompo le bolas con un altro post di domande. Puntatori e funzione localtime/localtime_s :old_lol:


#5

Aggiornamento
Nei giorni scorsi cercavo una soluzione sull’internet e sono finito sul forum Microsoft di Visual Studio dove c’era un tizio con un problema simile e lo aveva segnalato come bug. Il report è poi stato chiuso perché il tipo non ha dato nessuna info. Ho chiesto in coda a quel thread spiegando, spero in modo chiaro (non so quanto sia chiaro il mio inglese), il problema e chiedendo numi. Stasera ho controllato e un tipo mi ha risposto dicendomi di aprire un nuovo report perché quello è chiuso da mesi. L’ho aperto e aspetto notizie, vi lascio il link al mio report, non si sa mai, magari può tornare utile:

https://developercommunity.visualstudio.com/content/problem/173839/error-c2397-about-conversion-from-int-to-double.html


#6

Ciao, sono tornato ora e ho provato a copiare il tuo codice su VisualStudio.
Me lo compila ed esegue senza errori, Potrebbe essere un problema del tuo compilatore?

questo è l’output:

--------
Codice Prodotto: 0
Quantita': 0
Prezzo: 0
--------
Codice Prodotto: 1
Quantita': 10
Prezzo: 100
--------
Codice Prodotto: 2
Quantita': 20
Prezzo: 200
--------
Codice Prodotto: 3
Quantita': 30
Prezzo: 300
--------
Codice Prodotto: 4
Quantita': 40
Prezzo: 400
--------
Codice Prodotto: 5
Quantita': 50
Prezzo: 500
--------
Codice Prodotto: 6
Quantita': 60
Prezzo: 600
--------
Codice Prodotto: 7
Quantita': 70
Prezzo: 700
--------
Codice Prodotto: 8
Quantita': 80
Prezzo: 800
--------
Codice Prodotto: 9
Quantita': 90
Prezzo: 900

qui trovi qualche info sul casting delle variabili


#7

Eh, mi sa di sì, a queso punto credo proprio che sia un problema di Visual Studio 2017


#8

Io ho usato il 2013


#9

Mi hanno risposto

A parte “fixing is from etc.” che non ho capito cosa voglia dire (se invece che 10, parametro già dichiarato double, scrivo 10.0 allora funziona? :old_o_o:) , ma che significa che non posso convertire da int a double? :old_hmm:

EDIT: il tipo aveva ragione. Aggiungendo la virgola al 10 il compilatore non ha dato errori. Ma 10 lo avevo già dichiarato double. Non capisco…


#10

Non è che l’errore è quel 100.0?


#11

No, no. Al contrario, dovevo mettere il .0 anche al 10. Da quello che capisco, e potrei sbagliare, scrivendo “10” lui lo considera int ai fini dell’operazione e si “confonde” perché lo avevo dichiarato double. :old_boh: Ha senso?


#12

Tu hai dichiarato i INT, però nella struttura dichiari:

Li cerchi di assegnare i (un integer) ai due double.
Prova con:

t_riga_scontrino *nuovo = new t_riga_scontrino{ i, 10 * (double)i, 100.0 * (double)i}

EDIT: nel modo suggerito sopra forzi la conversione di i da integer a double.
con l’aggiunta del .0 fai effettuare una conversione automatica al compilatore. Il risultato è lo stesso, ma la è più leggibile il primo modo :wink:

Quindi, o
t_riga_scontrino *nuovo = new t_riga_scontrino{ i, 10 * (double)i, 100 * (double)i}
oppure
t_riga_scontrino *nuovo = new t_riga_scontrino{ i, 10.0 * i, 100.0 * i}


#13

Avevo già provato in questo modo e non ha funzionato.
Cambiando

t_riga_scontrino *nuovo = new t_riga_scontrino{ i, 10 * i, 100.0 * i };

in

t_riga_scontrino *nuovo = new t_riga_scontrino{ i, 10.0 * i, 100.0 * i };

invece funge.

Da quel che ho capito, visto che ho dichiarato che la variabile qta è double, quando riempio la struttura con il ciclo for il valore che assegno alla variabile deve avere la forma di un double (10.0). Ma non riesco a trovare nulla che mi chiarisca questa cosa. E soprattutto perché a te con il vs 2013 e al tizio di cui seguo le lezioni con Code::Blocks funziona a prescindere da questo “dettaglio”


#14

Ho editato il post mentre rispondevi.
Si, devi fare attenzione alla conversione dei tipi:
nella struttura di t_riga_scontrino hai un integer e due double, i è un integer, va bene per codice_prodotto, ma non può essere assegnato a qta e prezzo. Devi convertirlo in double. Moltiplicare i per un valore non intero (x.x) esegue una conversione automatica da integer a double e rimette a posto le cose.
Lo stesso fa l’operatore di casting (double). Strano che il tuo compilatore non lo riconosca. Hai controllato nelle varie impostazioni del compilatore?


#15

Ho riprovato con il cast, adesso funziona. Mi sa che prima o sbagliavo qualcosa oppure con tutte le prove che ho fatto avevo incasinato il codice.
Grazie per la spiegazione e la pazienza :old_drinks: