Taille maxi d'un char en C++

Résolu/Fermé
ptit81 Messages postés 29 Date d'inscription mercredi 12 septembre 2007 Statut Membre Dernière intervention 6 décembre 2012 - 16 juil. 2009 à 17:04
mamiemando Messages postés 33475 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 janvier 2025 - 24 juil. 2009 à 10:10
Bonjour,

J'utilise depuis un moment un code pour générer une expression dont la longueur dépend d'un nombre rentré par l'utilisateur.
Jusque maintenant, je ne l'avais pas utilisé avec un nombre très grand mais maintenant, j'aurai besoin de le faire et ça a l'air de poser problème comme s'il ne voulait pas que mon expression soit trop longue.
le code est le suivant:

char c_equation_cc1[1000]="X1_i_dot=W1_i_i*X1_i";
char c_i[10];
for(int i=1;i<=i_s;i++)
{
itoa(i,c_i,10);
strcat(c_equation_cc1,"+E1_i_");
strcat(c_equation_cc1,c_i);
strcat(c_equation_cc1,"*U_");
strcat(c_equation_cc1,c_i);
}
fprintf(f_cc1,"%s%s",c_equation_cc1,";\n}\n\n");

et donc, pour des valeurs de i_s (données par l'utilisateur) pas trop grande, ça marche bien, mais pour des valeurs de l'ordre de 200, ça foire.
Donc, j'ai essayé de remplacer à la première ligne "char c_equation_cc1[1000]" par "char c_equation_cc1[10000]" mais ça ne change rien du tout.
Je me demande donc si les variables char sont limitées en nombre de caractère et si oui, comment puis-je résoudre le problème.

Merci d'avance
A voir également:

8 réponses

mamiemando Messages postés 33475 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 janvier 2025 7 815
16 juil. 2009 à 19:17
Première chose pour t'expliquer pourquoi 1000 ou 10000 ne changent rien :
char c_equation_cc1[1000]="X1_i_dot=W1_i_i*X1_i";

Ici tu alloues un bloc de 1000 char et tu stockes l'adresse de ce bloc dans c_equation_cc1 (type char *). Ensuite tu réaffectes cette adresse avec celle de la chaîne "X1_i_dot=W1_i_i*X1_i". La zone pointée par c_equation_cc1 n'est donc plus un bloc de 1000 char, mais un bloc d'une vingtaine de char d'où le problème.

Si tu programmes en C++ (cf le titre) autant utiliser les fonctionnalités du C++ et n'utiliser les fonctions que C qu'en cas de nécessité. On peut avoir un code qui s'affranchit complètement des notions de dimensionnement de buffer, par exemple en utilisant la classe std::ostringstream :
// Au début de ton fichier
#include <string>
#include <sstream>

// A la déclaration de f_cc1
// Au lieu d'utiliser un char * autant utiliser une std::string
std::string f_cc1;

// Dans ta fonction
std::ostringstream oss;
oss << "X1_i_dot=W1_i_i*X1_i";
for(unsigned i = 1; i <= i_s; ++i){
  oss << "+E1_i_" << i << "*U_" << i;
}
oss << ';' << std::endl << '}' << std::endl << std::endl; 

// Concatène le contenu de c_equation_cc1 à f_cc1
f_cc1 += c_equation_cc1.str();

Petites précisions :

1) Un std::ostringstream peut être vu comme un flux sur un buffer de taille virtuellement infinie (comprendre on ne se pose pas de question en terme d'allocation mémoire). L'opérateur << permet de rajouter des choses à la fin du flux. La constante std::endl désigne le retour à la ligne (\n) en C++.

2) Note qu'ici on ne manipule pas que des std::string et des char* d'où l'utilité des std::ostringstream, sinon on aurait pu se contenter d'utiliser des std::string. Il n'est pas très judicieux de faire itoa la ou un sprintf en C et un std::ostringstream en C++ s'avèrent plus pertinents.

3) Pour plus d'informations sur les classes std::string et std::ostringstream :
https://community.hpe.com/t5/custom/page/page-id/HPPSocialUserSignonPage?redirectreason=permissiondenied&referer=https%3A%2F%2Fcommunity.hpe.com%2Ft5%2FServers-Systems-The-Right%2FSGI-com-Tech-Archive-Resources-now-retired%2Fba-p%2F6992583
http://www.cplusplus.com/reference/sstream/ostringstream/ostringstream/

Bonne chance
1
ptit81 Messages postés 29 Date d'inscription mercredi 12 septembre 2007 Statut Membre Dernière intervention 6 décembre 2012 2
17 juil. 2009 à 10:50
Merci beaucoup.

C'est en effet plus simple que ce que je faisais.
Je pense qu'il y a quand même une coquille dans ce que tu as écris vu que tu crée oss mais tu ne l'utilise pas par la suite.
J'ai donc réécris avec mes notations:

std::string s_equation_cc1;
std::ostringstream oss;
oss << "X1_i_dot=W1_i_i*X1_i";
for(unsigned i = 1; i <= i_s; ++i)
{
oss << "+E1_i_" << i << "*U_" << i;
}
oss << ';' << std::endl << '}' << std::endl << std::endl;
s_equation_cc1 += oss.str();

Par contre, c'est vraiment bête mais après, j'arrive pas à imprimer dans un fichier (f_cc1, créé plus haut dans le code) le string "s_equation_cc1".
je fais:

fprintf(f_cc1,"%s",s_equation_cc1);

et après compilation (qui a l'air de bien se passer); ça m'ouvre une fenêtre windows où il est marqué:

"generation_modele_etat_pt.exe a rencontré un problème et doit fermer. Nous vous prions de nous excuser pour le désagrément encouru." etc.

et j'ai un warning:

" [Warning] cannot pass objects of non-POD type `struct std::string' through `...'; call will abort at runtime "

Pourtant, pour imprimer un string, c'est bien %s qu'il faut utiliser! non!

Merci d'avance...
0
mamiemando Messages postés 33475 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 janvier 2025 7 815
17 juil. 2009 à 11:09
Je pense qu'il y a quand même une coquille dans ce que tu as écris vu que tu crée oss mais tu ne l'utilise pas par la suite.

Ben si j'utilisais oss (avec les opérateur <<, oss.str() pour écrire dans la chaîne etc...).

Par contre, c'est vraiment bête mais après, j'arrive pas à imprimer dans un fichier (f_cc1, créé plus haut dans le code) le string "s_equation_cc1".
je fais: fprintf(f_cc1,"%s",s_equation_cc1);


C'est normal un std::string n'est pas un char *, pour extraire le char * correspondant tu dois utiliser la méthode c_str(). Regarde les liens que je t'ai donné sur les objets std::string et std::ostringstream.

De plus pour manipuler un fichier il serait plus judicieux d'utiliser la classe std::ofstream qui s'utilise ensuite comme un std::ostringstream. Avec un peu de chance tu n'as même pas besoin de faire une étape par un std::ostringstream et tu peux écrire directement dans le fichier.
#include <fstream>
#include <iostream>

int main(){
  const char *filename = "pouet.txt";
  std::ofstream ofs(filename);
  if(!ofs){
    std::cerr << "can't write " << filename << std::endl;
    return 1;
  }
  ofs << "plop" << 1.23 << std::endl;
  ofs.close();
  return 0;
}

Bonne chance
0
ptit81 Messages postés 29 Date d'inscription mercredi 12 septembre 2007 Statut Membre Dernière intervention 6 décembre 2012 2
21 juil. 2009 à 13:06
La première méthode proposée ne marche pas parce qu'avec c_str, il me tronque mon string au bout d'un certain nombre de caractère et je retombe sur le problème précédent.

Pour la deuxième méthode, j'ai pas trouvé comment utiliser le ofstream sur un fichier déjà commencé.
Quand je l'utilise, il a l'air de me remettre systématiquement le fichier à blanc et si je ne veux pas recommencer entièrement mon code, il faudrait que je puisse continuer un fichier existant. (comme on peut le faire dans les options du fprintf).
A part ça, c'est vraiment une bonne idée car ça a l'air, encore une fois, de simplifier beaucoup l'écriture.

Est ce que quelqu'un a une idée?

merci d'avance
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mamiemando Messages postés 33475 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 janvier 2025 7 815
21 juil. 2009 à 14:22
La première méthode proposée ne marche pas parce qu'avec c_str, il me tronque mon string au bout d'un certain nombre de caractère et je retombe sur le problème précédent.

Peux-tu nous donner le code complet ? Normalement il n'y a pas de raison que ta chaîne soit tronquée, je pense que tu as dû faire une erreur quelque part.

Pour la deuxième méthode, j'ai pas trouvé comment utiliser le ofstream sur un fichier déjà commencé.

Il faut passer à la méthode open des flags supplémentaires pour écrire en mode "append".
http://www.cplusplus.com/reference/fstream/ofstream/open/
Je verrais bien un truc du genre :
std::ofstream ofs.open("pouet.txt",std::app);

Quand je l'utilise, il a l'air de me remettre systématiquement le fichier à blanc et si je ne veux pas recommencer entièrement mon code, il faudrait que je puisse continuer un fichier existant. (comme on peut le faire dans les options du fprintf).

Oui c'est normal. Par défaut un ofstream se comporte comme un fopen(fp,"pouet.txt","w");

A part ça, c'est vraiment une bonne idée car ça a l'air, encore une fois, de simplifier beaucoup l'écriture.

Ca ça ne fait aucun doute ^^ Le C++ simplifie grandement les questions existentielles du genre "comment je dimensionne mon buffer" et la gestion de la mémoire en général. De plus les entrées/sorties sont souvent plus pratiques en C++ qu'en C.

Bonne chance
0
ptit81 Messages postés 29 Date d'inscription mercredi 12 septembre 2007 Statut Membre Dernière intervention 6 décembre 2012 2
21 juil. 2009 à 14:37
Voici mon bout de code:

std::ostringstream oss_e_cc1;
oss_e_cc1 << "X1_i_dot=W1_i_i*X1_i";
for(unsigned i = 1; i <= i_s; i++)
{
oss_e_cc1 << "+E1_i_" << i << "*U_" << i;
}
std::string s_equation_cc1;
s_equation_cc1 += oss_e_cc1.str();

fprintf(f_cc1," %s%s",s_equation_cc1.c_str(),";\n}\n\n");

Je regarde ce que ça donne d'utiliser std::app
0
ptit81 Messages postés 29 Date d'inscription mercredi 12 septembre 2007 Statut Membre Dernière intervention 6 décembre 2012 2
24 juil. 2009 à 08:19
Pour finir, j'ai recodé entièrement en C++ et ça marche très bien en utilisant ostringstream et ofstream.
0
mamiemando Messages postés 33475 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 janvier 2025 7 815
24 juil. 2009 à 10:10
Parfait ! Bonne continuation !
0