La solution que te propose Eusebe est quand même plus propre ;)
Et pour ma part je pense que c'est ce que tu veux, non???
Version imprimable
La solution que te propose Eusebe est quand même plus propre ;)
Et pour ma part je pense que c'est ce que tu veux, non???
Désolé je n'ai pas vu vos anciens messages,
voilà j'ai améliorer mon code, et il marche comme je veux je vous l'envoi essayer le!!!!
Merci en tout cas pour votre aide, c'est sur que c'est meiux d'utiliser std, mais dans mon cas j'étais contraint de passer par cette methode car je voulais recupérer les nombres dans une ligne et les stocker dans une matrice symétrique en tout cas voilà mon code.
Mettez en commentaire tout ce qui n'est pas reconaissable en c++.
Il demeure un leger petit hic les nombres en format string sont suivi de trucs bizarre!!!
Mais c'est pas grave la conversion de strtod corrige le tire puisqu'il s'arrete de convertir quand il rencontre un caractère qu'il ne connait pas
mais j'aimerai comme même comprende pourquoi il continue à sortir ces trcus bizarre!
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 #include "essai.h" #include <iostream> #include <fstream> #include <iomanip> using namespace std; using namespace std; void main() { // Ouverture du fichier ifstream fichierEntree("c:\\test1.txt", ios::in); // Test d'ouverture du fichier if (!fichierEntree) { cerr << "Problème d'ouverture de fichier" << endl; exit(1); } char* ligne; int i = 0; char * err = NULL; //double z; ligne = new char[10]; fichierEntree.getline(ligne, 4); int conv1 = strtoul(ligne,0,10); ArrayLengthSpecifier dimension(conv1); cout << conv1 << endl; SymmetricMatrix covariance(dimension); int longueur; do { i = i + 1; longueur = 9 * i + 1; ligne = new char [longueur];//format "0.00E+00" //donc 8 caractères; 9i=8i+ (i-1) espaces + élt nul terminal fichierEntree.getline(ligne,longueur); cout << ligne << endl; for (int j=1;j<=i;j++) { char temp[7]; for (int k=0;k<=7;k++) { if (j==1) temp[k] = ligne[k]; else temp[k] = ligne[9* (j - 1) + k ];//attention dimension de 0 à n-1 } const char* caractere=temp; cout << caractere << endl; covariance(i,j) = 2 * strtod(caractere, &err); cout << covariance(i,j) << endl; cout << covariance(j,i) << endl; } delete[] ligne; } while (!fichierEntree.eof()); fichierEntree.close(); }
Non, tu pourrais très bien te contenter de la bibliothèque standard et des string...Citation:
Envoyé par iamor
Dans ton code :
- main doit renvoyer un int (je l'ai déjà dis je crois)
- tu fais un accès à temp[7] alors que ça n'existe pas...
- fais plutôt un tableau (temp) de 9 caractères pour stocker tes 8 caractères (tu oublies le caractère de fin de chaîne)
- ajoutes après ta boucle un "temp[8] = 0;" (le caractère de fin de chaîne)
- à quoi sert de recopier "temp" dans "caractere" ??
Mais je persiste et signe : l'utilisation de std::string et des flux aurait été possible, plus simple et plus propre !
Ton main doit renvoyer un int.
Je pense que l'utilisation de la std et des strings conviendrait.
Et à mon avis, le code que t'as fourni Eusebe est quand même plus propre.
Merci pour votre aide ça marche parfaitement maintenant.
Vous avez probablement raison, mon code ne ressemble à rien, mais l'important c'est que je puisse le faire marcher car j'en ai besoin d'urgence pour l'intégrer dans un autre module. Je le reverrerai plus tard en me laissant le temps de voir un peu les classes std::...
Merci pour votre aide,
ça m'as vraiment aidé
De rien :mrgreen:
Ca fait toujours plaisir quand on peut aider ;)
P.S.: oublie pas de mettre un joli petit :resolu: ;)
Hum... Avec
Tu auras toujours une dernière ligne abérante car il faut tester le résultat de la lecture.Code:
1
2
3
4 do { lecture; traitement; while (!eof)
Le code de la FAQ en plus d'être simple est juste. Pars de là !!
Bonjour,
J'avais évoqué auparavant dans cette discussion ma difficulté pour créer une fonction qui puisse lire à partir d'un fichier ".txt" une matrice trinagulaire supérieure et la stocker dans une variable matrice que j'ai définie préalablement.
N'étant pas expert en c++, j'ai codé en faisant abstraction de la gestion dynamique de la mémoire ce qui me joue des tours maintenant.
Je vous rapelle mon code qui marche dans certains cas et qui est le suivant :
Ce code marche bien sur des matrices de types suivant :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 #include "essai.h" #include <iostream> #include <fstream> #include <iomanip> using namespace std; using namespace std; int main() { // Ouverture du fichier ifstream fichierEntree("c:\\test1.txt", ios::in); // Test d'ouverture du fichier if (!fichierEntree) { cerr << "Problème d'ouverture de fichier" << endl; exit(1); } char* ligne; int i = 0; char * err = NULL; //double z; ligne = new char[10]; fichierEntree.getline(ligne, 4); int conv1 = strtoul(ligne,0,10); ArrayLengthSpecifier dimension(conv1); cout << conv1 << endl; SymmetricMatrix covariance(dimension); int longueur; do { i = i + 1; longueur = 9 * i + 1; ligne = new char [longueur];//format "0.00E+00" //donc 8 caractères; 9i=8i+ (i-1) espaces + élt nul terminal fichierEntree.getline(ligne,longueur); cout << ligne << endl; for (int j=1;j<=i;j++) { char temp[9]; for (int k=0;k<=7;k++) { temp[8]=0; if (j==1) temp[k] = ligne[k]; else temp[k] = ligne[9* (j - 1) + k ];//attention dimension de 0 à n-1 } const char* caractere=temp; cout << caractere << endl; covariance(i,j) = 2 * strtod(caractere, &err); cout << covariance(i,j) << endl; cout << covariance(j,i) << endl; } delete[] ligne; } while (!fichierEntree.eof()); fichierEntree.close(); }
Par contre dès qu'il s'agit d'une matrice qui contient un nombre négatif (par exemple) :Code:
1
2
3
4
5 3 1.23E-02 1.24E-02 1.26E-02 1.27E-02 1.23E-04 1.23E-03
Code:
1
2
3
4
5 3 1.23E-02 -1.24E-02 1.26E-02 1.27E-02 1.23E-04 1.23E-03
Ma définition qui fixe la dimension de temp à 9, devient fausse puisque celle-ci avec le signe moins deviens égale à 10.
Aurriez vous une idée qui puisse contourner le problème??.
J'ai pensé à imbriquer une instruction if à l'intérieure de ma boucle qui test si le premier caractère est "-" et à ce moment fait une réallocation de temp pour porter sa dimension à 10. Mais je ne sais pas comment coder ça en c++. Auriez vous une idée à me proposer, je suis vraiment bloquer la dessus ??
Merci de votre aide
Il me semble qu'on te l'a dit à plusieurs reprises. Code en C++. utilise std::string et std::getline. Oublie new[] dans ce contexte, cela ne t'apporte rien d'intéressant surtout que tu sembles débuter.
Enfin, les flux sont la méthode idoine pour faire les convertions chaines <-> nombres en C++. Pourquoi se compliquer la vie ?
Maintenant, vu que tu sembles utiliser une bibliothèque toute faite, tu devrais déjà disposer de fonctions de sérialization et désérialization de tes matrices -- si la bibliothèque est bien faite.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 std::ifstream file("c:/test1.txt"); if (!file) throw std::runtime_error("cannot open test1.txt"); // lecture de la dimension int size; file >> size; file.ignore(std::numeric_limits<streamsize>::max(), '\n' ); // purge de la fin de ligne // je suppose qu'il n'y a pas de lignes vides par la suite. SymetricMatrix matrix(size); std::string line; for (int l=0 ; std::getline(file, line) ; ++l) { // désolé, il est tard, je condense std::istringstream iss(line); for (int c = 0 ; iss >> matrix[l][c] ; ++c) { // désolé, il est tard, je condense /*nop;*/ } }
Merci pour ta réponse.
J'ai réussi de mon côté à developper quelque chose qui ressemble à ton code :
Pour l'instant ça marche bien, merci en tout cas des vos conseils, par contre je voudrais bien comprend à quoi sert le std:: que fait-il au niveau de l'allocation de mémoire et en quoi cela diffère-til par rapport au CCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 //fichier main principal #include "essai.h" #include <iostream> #include <sstream> #include <fstream> #include <iomanip> #include <string> using namespace std; int main() { ifstream FichierMatrice("D:\\Documents and Settings\\AMOR\\Desktop\\VaRaction\\covariance.txt",ios::in); if (!FichierMatrice) { cerr << "Ouverture du fichier impossible" << endl; exit(1); } int val1; double* valf; FichierMatrice >> val1; ArrayLengthSpecifier dimension(val1); SymmetricMatrix covariance(dimension); // retourne la dimension de lma matrice //cout << val1 << endl; int dime = (val1*(val1+1))/2; valf = new double [dime]; for (int i=1;i<=val1;i++) { for (int j=1;j<=i;j++) { FichierMatrice >> valf[j]; covariance(i,j)= valf[j]; //retourne les éléments de la matrice covariance(i,j) //cout << covariance(i,j) <<endl; } } //test sur les éléments de la matrice covariance cout << covariance (2,1) <<endl; return 0; }
std est un espace de noms (namespace) et n'a donc pas grand chose à voir avec l'allocation de la mémoire. Pour plus de détails sur les namespace, voir la FAQ http://c.developpez.com/faq/cpp/?page=namespace et http://c.developpez.com/faq/cpp/?pag...sing_namespaceCitation:
Envoyé par iamor
Tu n'as pas besoin de réaliser des allocations dynamiques de façon explicite dans ton cas.
D'un tu as des fuites de mémoire dans l'état actuel. De deux le code correct avec gestion explicite est vite compliqué. De trois, concentre toi d'abord sur l'algorithmie. Tu fais encore beaucoup de manipulations inutiles. Ce qui me fait dire que tu as le temps avant de rentrer dans les détails de la gestion de la mémoire en C++.
std::vector (tableaux dynamiques redimensionnables) et std::string (chaînes de caractères dynamiques redimensionnables) sont tes amis.
Plein de choses dans la FAQ et dans les vrais cours de C++ (pas les cours de C traduits en C++ qui sont à fuir).
Bonsoir
Je répond un peu tardivement mais voilà j'ai bien changé mon code pour qu'il soit plus clean, mais voilà je voudrais avoir une petite aide sur la construction d'une fonction.
Mon code est le suivant:
Pour l'améliorer je suite construire en plus des fonction simind et chol une fonction simcor.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 //fichier main principal #include "essai.h" #include <iostream> #include <sstream> #include <fstream> #include <iomanip> #include <string> using namespace std; int main() { //initialise la graine du générateur de variable normale init_genrand(time(NULL)); ifstream fichierEntree("D:\\Documents and Settings\\AMOR\\Desktop\\VaRaction\\covariance.txt", ios::in); int dim; fichierEntree >> dim; ArrayLengthSpecifier dimension(dim); SymmetricMatrix covariance(dimension); /* lecture de la matrice */ for( int i=1 ; i<=dim ; ++i ) { for( int j=1 ; j<=i ; ++j ) { double val; fichierEntree >> val; covariance(i,j) = val; } } fichierEntree.close(); //décompose la matrice de covariance suivant cholesky Matrix C; C = chol(covariance); int nbre_simul; ColumnVector E; ColumnVector epsilon_correl; //saisie du nombre de simulation cout << "Veuillez saisir le nombre de simulations souhaitees : "; cin >> nbre_simul; // définie la matrice de sortie Matrix simul_epsilon (nbre_simul,dim); for(int i=1 ; i<=nbre_simul ; ++i ) { E = simind(dim); epsilon_correl = C * E; for(int j=1 ; j<=dim ; ++j ) { simul_epsilon(i,j) = epsilon_correl(j); } } std::cout << simul_epsilon(4,4) << std::endl; /* affichage pour tester la matrice de cholesky */ for( int i=1 ; i<=dim ; ++i ) { for( int j=1 ; j<=dim ; ++j ) { if (j==1) std::cout << C(i,j); else { std::cout << " " << C(i,j); } } std::cout << std::endl; } /* affichage pour tester la matrice simul_epsilon */ for( int i=1 ; i<=nbre_simul ; ++i ) { for( int j=1 ; j<=dim ; ++j ) { if (j==1) std::cout << simul_epsilon(i,j); else { std::cout << " " << simul_epsilon(i,j); } } std::cout << std::endl; } //écriture de la matrice de Cholesky transformée dans un fichier .txt ofstream fichierSortie("C:\\Matrice de cholesky transformée.txt",ios::out); if (!fichierSortie) { cerr << "Création du fichier impossible" << endl; exit(1); } for (int i=1;i<=dim;i++) { for (int j=1;j<=i;j++) { if (j==1) fichierSortie << C(i,j); else { fichierSortie << " " << C(i,j); } } fichierSortie << endl; } return 0; }
Voilà le fichier contenant ces fonctions:
Le fichier principal devientCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100 // Il s'agit du fichier DLL principal. #include "stdafx.h" #include "CorrelSimul.h" ReturnMatrix chol(const SymmetricMatrix& correlation) { //renvoie la dimension de la matrice de corrélation ArrayLengthSpecifier dimension(correlation.Nrows()); int dimension1 = correlation.Nrows(); //initialise le test de défini positivité à faux bool test=false; //diagonalise la matrice de corrélation DiagonalMatrix D(dimension); Matrix V(dimension1,dimension1); LowerTriangularMatrix L(dimension); Matrix resultat; //renvoie les valeurs propres EigenValues(correlation,D,V); // if (D(1)<=0) test=true; if (test=false) { L = Cholesky(correlation); resultat=L; } else { for (int i = 1; i <= dimension1; i++) { D(i)=sqrt(max(D(i),0)); /* on transforme D en D+ puis en (D+)^1/2 pour prendre la racine carrée */ } resultat = V*D*V.t(); } D.Release(); V.Release(); L.Release(); return resultat; } ReturnMatrix simind(const int& nbre_noms) { //créer une matrice colonne epsilon ColumnVector epsilon; //redimensionne la matrice espsilon avec la dimension correpondante //au nombre de titre epsilon.ReSize(nbre_noms); //générateur de loie normale for (int i=1; i<=nbre_noms; ++i) { epsilon(i)= normal_random(); } epsilon.Release(); return epsilon; } ReturnMatrix simcor(const int& nbre_simul, const int& dim, const SymmetricMatrix& covariance) { //décompose la matrice de covariance suivant cholesky Matrix C; C = chol(covariance); //définie le vecteur de variables aléatoires normales ColumnVector E; //définie le vecteur issue de la multiplication de E et C ColumnVector epsilon_correl; // définie la matrice de sortie Matrix simul_epsilon (nbre_simul,dim); for(int i=1 ; i<=nbre_simul ; ++i ) { E = simind(dim); epsilon_correl = C * E; for(int j=1 ; j<=dim ; ++j ) { simul_epsilon(i,j) = epsilon_correl(j); } } C.Release(); E.Release(); epsilon_correl.Release(); simul_epsilon.Release(); return simul_epsilon; }
Le problème c'est que j'ai un message d'erreur qui est le suivant et dont je ne comprend pas l'origine !Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 //fichier main principal #include "essai.h" #include <iostream> #include <sstream> #include <fstream> #include <iomanip> #include <string> using namespace std; int main() { //initialise la graine du générateur de variable normale init_genrand(time(NULL)); ifstream fichierEntree("D:\\Documents and Settings\\AMOR\\Desktop\\VaRaction\\covariance.txt", ios::in); int dim; fichierEntree >> dim; ArrayLengthSpecifier dimension(dim); SymmetricMatrix covariance(dimension); /* lecture de la matrice */ for( int i=1 ; i<=dim ; ++i ) { for( int j=1 ; j<=i ; ++j ) { double val; fichierEntree >> val; covariance(i,j) = val; } } fichierEntree.close(); //saisie du nombre de simulation int x; cout << "Veuillez saisir le nombre de simulations souhaitees : "; cin >> x; //définie la matrice de sortie //Matrix sortie(x,dim); //sortie = simcor(x, dim, covariance); //std::cout << sortie(4,4) << std::endl; //écriture de la matrice de Cholesky transformée dans un fichier .txt ofstream fichierSortie("C:\\Matrice de cholesky transformée.txt",ios::out); if (!fichierSortie) { cerr << "Création du fichier impossible" << endl; exit(1); } Matrix COLout; COLout = chol(covariance); for (int i=1;i<=dim;i++) { for (int j=1;j<=i;j++) { if (j==1) fichierSortie << COLout(i,j); else { fichierSortie << " " << COLout(i,j); } } fichierSortie << endl; } return 0; }
L'origine du problème est mis en commentaires dans le fichier principalCode:
1
2 essai.cpp(45) : error C2660: 'simcor'*: la fonction ne prend pas 3 arguments
Qu'en pensez-vous ?
Tu n'aurais pas oublié la déclaration de ta fonction ? Ou alors ce serait une déclaration fausse ?
PS: Fais des efforts sur ton indentation STP. Le code n'est pas lisible. Prend n'importe quel éditeur, tu lui demandes de réindenter avec des espaces uniquement (sans utiliser le caractère de tabulation), avant de copier-coller ici. Ton extrait est déjà trop long comme ça.
Bonjour,
Que veux-tu dire par la déclaration de ma fonction??, pourtant je l'ai bien défini dans le code ou sont aussi définies les fonctions simond et chol.
P.S: Dans ton ancien messages, tu veux dire que je laisse trop de tabulation verticales entres les lignes de code c'est ça??
Je dirais plutôt que tu ne laisses pas assez de tabulations horizontales, et en fouillis en plus (l'alignement n'est pas préservé).
Et comme il n'existe à ce jour aucun moyen de régler les tabulations sur une page Web, on se retrouve en plus avec des tabs de 8, ce qui n'est pas une valeur raisonnable pour du code.
Donc, le monsieur te demande:
- De réindenter correctement ton code,
- De régler (si ce n'est pas déjà fait) des tabs de taille raisonnable (3 ou 4 caractères) dans ton éditeur de texte,
- De le passer à la fonction "tabs to spaces" pour fixer ces tabs.
Sauf celui de Visual :aie: .Citation:
Prend n'importe quel éditeur
Déjà, les fonctions tabs to spaces et spaces to tabs sont cachées (il faut jouer avec les toolbars pour les débloquer) mais en plus la fonction spaces to tabs convertit TOUS les espaces en tabs, et non pas seulement ceux du début.
Bon j'ai trouvé la raison à mon erreur ma fonction était mal déclaré dans le fichier .h (un simple oubli)
Merci en tout cas de vos réponses