PDA

View Full Version : C++ inizializzazione stringa dentro uno switch, problemi!


Abdujaparov
24-09-2006, 21:52
Ho scritto questo pezzo di codice che devo completare a poco a poco però ci sono dei problemi che io non riesco a comprendere.

switch(sel){
case 1:
string uno="";
string due="";
break;
case 2:
break;
case 3:
break;
case 4:
break;

default:
return 0;

}
}

Se provo a compilare con questo pezzo di codice mi vengono dati degli errori nella dichiarazione delle due stringhe (include <string> c'è) e non riesco a capire il perchè, so che è una cosa scema ma non capisco cosa ci possa essere di sbagliato.
Questi sono gli errori che mi vengono dati in fase di compilazione:
rimo.cpp
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(46) : error C2360: initialization of 'due' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(38) : see declaration of 'due'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(46) : error C2360: initialization of 'uno' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(37) : see declaration of 'uno'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(48) : error C2360: initialization of 'due' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(38) : see declaration of 'due'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(48) : error C2360: initialization of 'uno' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(37) : see declaration of 'uno'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(50) : error C2360: initialization of 'due' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(38) : see declaration of 'due'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(50) : error C2360: initialization of 'uno' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(37) : see declaration of 'uno'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(52) : error C2360: initialization of 'due' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(38) : see declaration of 'due'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(52) : error C2360: initialization of 'uno' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(37) : see declaration of 'uno'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(54) : error C2360: initialization of 'due' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(38) : see declaration of 'due'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(54) : error C2360: initialization of 'uno' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(37) : see declaration of 'uno'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(56) : error C2360: initialization of 'due' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(38) : see declaration of 'due'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(56) : error C2360: initialization of 'uno' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(37) : see declaration of 'uno'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(58) : error C2360: initialization of 'due' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(38) : see declaration of 'due'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(58) : error C2360: initialization of 'uno' is skipped by 'case' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(37) : see declaration of 'uno'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(60) : error C2361: initialization of 'due' is skipped by 'default' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(38) : see declaration of 'due'
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(60) : error C2361: initialization of 'uno' is skipped by 'default' label
c:\documents and settings\angelo\documenti\visual studio 2005\projects\primo\primo\primo.cpp(37) : see declaration of 'uno'
Build log was saved at "file://c:\Documents and Settings\angelo\Documenti\Visual Studio 2005\Projects\Primo\Primo\Debug\BuildLog.htm"
Primo - 16 error(s), 0 warning(s)

Che cosa vogliono dire? Cosa diamine posso fare per risolvere?
Posso passare una string ad un metodo che vuole char*?
Se non posso farlo come converto una string in un char*?
Grazie, ciao ciao.
Grazie, ciao ciao.

71104
24-09-2006, 22:30
eh caro Angelo :P il problema è che non puoi dichiarare variabili all'interno di uno switch, a prescindere da che le inizializzi o no; vanno dichiarate per forza fuori oppure in un blocco di codice interno al case racchiuso da parentesi graffe:

switch (asd) {
case lol:
{
int rofl = 0;
.
.
.
}
break;
}

Abdujaparov
24-09-2006, 22:59
Grazie mille e per quanto riguarda string e char *?
Grazie, ciao ciao

cionci
25-09-2006, 10:28
Per convertire una string in char * usi il metodo c_str() che però ritorna un const char *, attenzione...quindi non la puoi passare a funzioni che manipolano il buffer della stringa...o che comunque che non hanno const char * nel prototipo...

Abdujaparov
25-09-2006, 22:15
Grazie mille, poi ho risolto in questo modo:

string nome;
quando una funzione accetta char* io passo: &nome[0].

Ora ho un altro problema, devo prendere da linea di comando due stringhe formate da più parole solo che se appena digito la prima stringa e do invio, in automatico come stringhe mi vengono prese le due parole che ho digitato e non mi viene neanche chiesto di inserire la seconda stringa.
Allego il codice ed un esempio per farmi capire.
Codice:
cout<<"Inserisci prima stringa";
cin>>nome;
cout<<"\n"<<"Seconda stringa";
cin>>pollo;

Mi viene posta la prima domanda ed inserisco: "ciao mimmo".
La seconda richiesta non mi viene posta e pollo assume valore "mimmo", mentre nome assume valore "ciao".
Io invece voglio che nome contenga tutto "ciao mimmo" e che poi mi venga fatta la seconda richiesta.
Cosa devo modificare?
Grazie,ciao ciao.

cionci
25-09-2006, 22:28
string nome;
quando una funzione accetta char* io passo: &nome[0].

E' assolutamente errato...così vai a lavorare sulla struttura di memorizzazione utilizzata da string e NON si deve fare... Chi ti dice che la stringa sia memorizzata tutta sequenzialmente ? Questa è una delle cose più brutte che si possa fare in C++ :)
Se ti serve un char * allora fai così:

char *tmp = new char[s.length()+1];
strcpy(tmp, s.c_str());
funzione(tmp);
delete[] tmp;

In ogni caso sei sei te a scrivere "funzione" non vedo perchè non metterti a passare const char * invece di char *...

Ora ho un altro problema, devo prendere da linea di comando due stringhe formate da più parole solo che se appena digito la prima stringa e do invio, in automatico come stringhe mi vengono prese le due parole che ho digitato e non mi viene neanche chiesto di inserire la seconda stringa.
Allego il codice ed un esempio per farmi capire.
Codice:
cout<<"Inserisci prima stringa";
cin>>nome;
cout<<"\n"<<"Seconda stringa";
cin>>pollo;

Mi viene posta la prima domanda ed inserisco: "ciao mimmo".
La seconda richiesta non mi viene posta e pollo assume valore "mimmo", mentre nome assume valore "ciao".
Io invece voglio che nome contenga tutto "ciao mimmo" e che poi mi venga fatta la seconda richiesta.
Cosa devo modificare?
Grazie,ciao ciao.

string s;
getline(cin, s);

PGI-Bis
25-09-2006, 23:35
eh caro Angelo :P il problema è che non puoi dichiarare variabili all'interno di uno switch, a prescindere da che le inizializzi o no; vanno dichiarate per forza fuori oppure in un blocco di codice interno al case racchiuso da parentesi graffe:
[omissis]


Sei sicuro? La accendiamo? O proviamo l'aiuto del pubblico? :D.

71104
26-09-2006, 00:43
Sei sicuro? La accendiamo? O proviamo l'aiuto del pubblico? :D. *piccola verifica*: apro Visual C++ 2005, nuovo progetto, Project -> Properties -> Configuration Properties -> C/C++ -> Language -> ... *cerco un'opzione relativa agli switch* -> *non c'è* :Prrr:

si, la accendiamo :p

cionci
26-09-2006, 09:42
si, la accendiamo :p
Sono d'accordo...a meno che non vengano dichiarate in un sottoblocco con scope minore del ramo del case...

trallallero
26-09-2006, 10:18
Sono d'accordo...a meno che non vengano dichiarate in un sottoblocco con scope minore del ramo del case...
non mi sembra ci sia da essere d'accordo o no ... é proprio la regola del C/C++ che lo impedisce ;)

sysmandave
26-09-2006, 10:25
posso importunare ognuno di voi? Avrei bisogno di una dritta per poter entrare in maniera autodidattica nella programmazione...

PGI-Bis
26-09-2006, 10:32
Il blocco dell'enunciato (io uso questo termine per "statement") switch può contenere altri enunciati e la dichiarazione in C++ è un enunciato (declaration-statement). Ergo la norma è che lo switch possa contenere anche la dichiarazione di variabili, con o senza inizializzazione. Si può fare:

Caso 1
switch(a) {
int x = a;
case 0:
//blabla
case 1:
//blibli
}

Caso 2
switch(b) {
case 0:
//blibli
case 1:
int x = 10;
break;
}

Caso 3
switch(c) {
case 0:
int x;
break;
case 1:
int y;
break;
}

Però non si può fare:

Caso 4
switch(c) {
case 0:
int x = 0;
case 1:
break;
}

Eppure "int x = 0;" è "well formed". Epperchè mai non si può fare? Perchè lo switch non può contenere la dichiarazione di una variabile?

No. Non si può fare per via di un'eccezione alla regola dei salti dentro a un enunciato composto:

void pippo(int x) {
if(x == 2) goto jump;
int y = x + 1;
jump: //blabla;
}

L'eccezione dice che un programma che esegua un salto all'interno di un blocco (aka enunciato composto in C++) è mal formato se il salto avvenga da un punto in cui una variabile automatica è fuori ambito a un punto in cui è in ambito. A meno che (eccezione all'eccezione) la variabile non sia un POD e sia dichiarata senza inizializzazione (caso 3).

71104
26-09-2006, 15:22
boh, fa' come ti pare, ma intanto col gcc va :Prrr:
è solo il Visual Studio che fa problemi (e probabilmente ha ragione)

trallallero
26-09-2006, 15:34
Caso 2
switch(b) {
case 0:
//blibli
case 1:
int x = 10;
break;
}
questo non si puó fare :read:

PGI-Bis
26-09-2006, 15:53
questo non si puó fare :read:

Non basta dire che non si può, neppure se si mette l'icona :read: . D'altronde non è che io lo sappia per intervento divino :D. Basta invece leggere lo standard ISO/IEC 14882.

6.4.2 (Switch)
6.7 (Declaration Statement), paragrafo 3
3.9 Tipi POD

e vedrai che si può. Se il compilatore che usi non te lo consente allora o è un compilatore per il C++ de noantri oppure c'è qualche altra eccezione all'eccezione della norma (eventuale) che mi sono perso.

trallallero
26-09-2006, 16:05
Non basta dire che non si può, neppure se si mette l'icona :read: . D'altronde non è che io lo sappia per intervento divino :D. Basta invece leggere lo standard ISO/IEC 14882.

6.4.2 (Switch)
6.7 (Declaration Statement), paragrafo 3
3.9 Tipi POD

e vedrai che si può. Se il compilatore che usi non te lo consente allora o è un compilatore per il C++ de noantri oppure c'è qualche altra eccezione all'eccezione della norma (eventuale) che mi sono perso.
questo é la prova:

#include <stdio.h>

int main()
{
int x = 1;

switch(x)
{
case 1:
int y; // riga 10
int z = 2;
break;
}
return 0;
}

questa é la compilazione:
gcc prova.c -o p
questo é l'out:

prova.c: In function `main':
prova.c:10: syntax error before "int"

PGI-Bis
26-09-2006, 16:14
questo é la prova: [omissis]

Sei sicuro? La accendiamo? O proviamo l'aiuto del pubblico? :D.

trallallero
26-09-2006, 16:21
Sei sicuro? La accendiamo? O proviamo l'aiuto del pubblico? :D.
faccio una telefonata a casa :D

PGI-Bis
26-09-2006, 16:24
:D:D:D

Anche in C l'enunciato switch accetta degli enunciati. A differenza di C++, però, la dichiarazione in C non è un enunciato. Quindi uno switch C non può contenere la dichiarazione di una variabile.

Quello che hai incollato è codice C e lì si, non si può fare.

trallallero
26-09-2006, 16:28
:D:D:D

Anche in C l'enunciato switch accetta degli enunciati. A differenza di C++, però, la dichiarazione in C non è un enunciato. Quindi uno switch C non può contenere la dichiarazione di una variabile.

Quello che hai incollato è codice C e lì si, non si può fare.
vero :D

mv prova.c prova.cc
gcc prova.cc -o p
:yeah:

71104
26-09-2006, 16:35
Non basta dire che non si può, neppure se si mette l'icona :read: . D'altronde non è che io lo sappia per intervento divino :D. Basta invece leggere lo standard ISO/IEC 14882.

6.4.2 (Switch)
6.7 (Declaration Statement), paragrafo 3
3.9 Tipi POD
ma sto standard dove si legge?

71104
26-09-2006, 16:38
trovato, come non detto :p

PGI-Bis
26-09-2006, 16:45
Si scarica dal sito di ANSI per 30 dollarozzi ballanti e sonanti.

In rete si trovano i "draft" che sono delle versioni tipo "lavori in corso" dello standard:

link FTP (ftp://ftp.research.att.com/dist/c++std/WP/CD2/)

A naso direi che il draft è uguale allo standard però non ho mai fatto un confronto pagina per pagina (leggere lo standard è una palla intergalattica :D).

71104
26-09-2006, 18:51
30 cheeee?? mavalà, terzo link trovato su Google:

http://www.ishiboo.com/~nirva/c++/C++STANDARD-ISOIEC14882-1998.pdf

:asd:


EDIT: quarto scusa :asd:
http://www.google.com/search?hl=en&q=iso%2Fiec+14882&btnG=Google+Search

PGI-Bis
26-09-2006, 19:26
Pensa che stupidi quelli dell'ANSI: si fanno pagare 30 dollari per una cosa che si può ottenere gratis.

Ma ti pare che www.ishiboo.com/˜nirva sia una fonte che un programmatore può prendere in considerazione quando si tratti di ottenere lo standard che definisce un linguaggio? E se capita un guaio al cliente cosa diciamo, che su topolino.org c'era scritto di fare così?

Abdujaparov
26-09-2006, 19:33
Ho modificato il pezzo di codice per prendere 2 stringhe ma ho un altro problema.
Il mio codice adesso è così:

cout<<"inserisci nome: ";
cin.getline(nome,300);
cout<<" "<<"inserisci numero: ";
cin.getline(numero,300);
d.AggiungiContatto(nome, numero);

dove nome e numero sono dure array di char di 300 caratteri, solo che ora non mi chiede la prima stringa, ma mi chiede direttamente la seconda cioè l'output è:

inserisci nome: inserisci numero:

tutto di botto e posso solo inserire il numero mentre il nome rimane vuoto.
Come posso risolvere?
Grazie, ciao ciao.

71104
26-09-2006, 22:59
Pensa che stupidi quelli dell'ANSI: si fanno pagare 30 dollari per una cosa che si può ottenere gratis. potere della pirateria :cool:

Ma ti pare che www.ishiboo.com/˜nirva sia una fonte che un programmatore può prendere in considerazione quando si tratti di ottenere lo standard che definisce un linguaggio? E se capita un guaio al cliente cosa diciamo, che su topolino.org c'era scritto di fare così? diamo la colpa a "Màicrosoft Visual C+ 20005 Ecspress"; o, molto più probabilmente, a Dev-C++ :asd:

intanto io mi becco lo standard gratis e tu no, moralista :Prrr:
ci vedi qualcosa di sbagliato in quel file? :Prrr:

PGI-Bis
27-09-2006, 00:38
potere della pirateria :cool:

:D vecchio bucaniere! :D

Quel documento è "datato" nel senso che è l'originale del 1998. Lo standard ha subito una revisione nel 2003. Niente di rivoluzionario ma qualche spuntatina qua e là c'è stata. Se prendi a mero titolo d'esempio il capitolo 5.2.2 (Function Call), le due versioni della parte etichettata "4" sono:

ISO/IEC14882:1998, p. 67
When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding argument. When a function is called, the parameters that have object type shall have completely-defined object type.

ISO/IEC14882:2003, p. 69
When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding
argument. If the function is a nonstatic member function, the “this” parameter of the function (9.3.2)
shall be initialized with a pointer to the object of the call, converted as if by an explicit type conversion
(5.4). [Note: There is no access checking on this conversion; the access checking is done as part of the
(possibly implicit) class member access operator. See 11.2. ] When a function is called, the parameters
that have object type shall have completely-defined object type.

Roba di questo genere.

trallallero
27-09-2006, 08:07
Ho modificato il pezzo di codice per prendere 2 stringhe ma ho un altro problema.
Il mio codice adesso è così:

cout<<"inserisci nome: ";
cin.getline(nome,300);
cout<<" "<<"inserisci numero: ";
cin.getline(numero,300);
d.AggiungiContatto(nome, numero);

dove nome e numero sono dure array di char di 300 caratteri, solo che ora non mi chiede la prima stringa, ma mi chiede direttamente la seconda cioè l'output è:

inserisci nome: inserisci numero:

tutto di botto e posso solo inserire il numero mentre il nome rimane vuoto.
Come posso risolvere?
Grazie, ciao ciao.
potresti avere un "invio" nel buffer stdin, quindi quando arriva alla getline la salta perché usa quell'invio come se fosse premuto dall'utente. L'unica cosa che mi viene in mente, ma il caffé deve ancora fare effetto :coffee:

71104
27-09-2006, 12:52
Quel documento è "datato" nel senso che è l'originale del 1998. Lo standard ha subito una revisione nel 2003. Niente di rivoluzionario ma qualche spuntatina qua e là c'è stata. Se prendi a mero titolo d'esempio il capitolo 5.2.2 (Function Call), le due versioni della parte etichettata "4" sono: [...] when even Google is not enough, unleash the power of eMule!! :asd: