2010-08-29 5 views
1

Cela fait un moment que j'ai travaillé avec C++, je suis actuellement en train de rattraper un prochain test de programmation. J'ai la fonction suivante qui a cette signature:Révision de C++: Int à Char

void MyIntToChar(int *arrayOfInt,char* output) 

Int est un tableau de nombres entiers et char * sortie est un tampon qui doit être suffisamment longue pour tenir la représentation de chaîne des nombres entiers que la fonction reçoit.

Voici un exemple de l'utilisation de cette fonction:

int numbers[3] = {11, 26, 81}; 
char* output = "";  // this I'm sure is not valid, any suggestions on how to 
          // to properly initialize this string? 
MyIntToChar(numbers,output); 
cout << output << endl; // this should print "11 26 81" or "11, 26, 81". 
          // i.e. formatting should not be a problem. 

J'ai examiné mon vieux C++ notes de l'université, mais je continue à avoir des problèmes avec ceux-ci. Je me déteste maintenant pour aller dans le monde de Java et ne pas travailler dans ce domaine.

Merci.

+5

Quel est l'antipath de std :: string et std :: vector?(Bien que si vous pensez que ce genre de chose viendra dans le test, assez juste) – Yacoby

+0

Est-ce que 'void MyIntToChar (int * arrayOfInt, char * output)' partie de l'assignation parce qu'elle me ressemble, 'void MyIntToChar (std :: vector in, std :: string out) 'me ressemble plus au RPC. Vous devriez également clarifier votre question. –

+0

Je suis certain que le test saute std :: string et vector. Je veux obtenir mes bases couvertes et puis (si j'ai le temps) passer en revue les conteneurs et la classe de corde dans le STL –

Répondre

0

Vous devriez jeter un oeil à la std::stringstream, ou, plus C-ish (comme char* de type au lieu de string s pourrait suggérer) sprintf.

+0

Je vais essayer et vous le faire savoir. Merci –

+0

D'accord, sprintf fonctionne, mais il imprime seulement le dernier nombre dans le tableau. Une idée de ce qui pourrait être faux? –

+0

Ensuite, construisez-le en petits morceaux. – Dario

1

bien un entier converti en chaîne nécessite un maximum de 12 octets, y compris signe (en supposant 32bit), de sorte que vous pouvez allouer quelque chose comme ça

char * output= new char[12*sizeof(numbers)/sizeof(int)]; 
+0

Je ne savais pas que vous pouviez initialiser ce pointeur de cette façon. Bien que cela ait du sens, étant donné l'équivalence entre les pointeurs et les tableaux. –

1

Tout d'abord, il est impossible d'utiliser votre méthode comme votre exemple dit: char* output a seulement une taille de 1 octet (ne pas oublier le '\0'). Donc vous ne pouvez pas mettre une chaîne entière dedans. Vous obtiendrez des fautes de segmentation. Donc, vous allez utiliser le tas. Ceci est déjà implémenté dans std::string et std::stringstream. Alors utilisez-les pour ce problème.

Jetons un coup d'oeil:

#include <string> 
#include <sstream> 
#include <iostream> 

std::string intArrayToString(int *integers, int numberOfInts) 
{ 
    std::stringstream ss; 
    for (int i = 0; i < numberOfInts; i++) 
    { 
     ss << integers[i] << ", "; 
    } 
    std::string temp = ss.str(); 
    return temp.substr(0, temp.size() - 2); // Cut of the extra ", " 
} 

Et si vous voulez convertir en char*, vous pouvez utiliser yourString.c_str();

+0

Merci pour votre réponse. Je ne suis pas sûr si l'utilisation de Stringstream et chaîne à l'intérieur de la fonction fonctionnera pour moi. –

+0

@Jonathan: Pourquoi pas? Je pense que c'est vraiment la meilleure façon de le faire ... –

+1

Eh bien, je fais de mon mieux pour éviter d'utiliser des chaînes de caractères et d'autres classes dans la STL, comme m'a conseillé le programmeur avec lequel j'ai parlé. Il m'a recommandé de me concentrer sur les bases du langage C/C++, puis de passer à des sujets avancés tels que le langage STL. –

0

avez-vous essayé sprintf(), il fera votre work.For char * initialisation, vous devez soit l'initialiser en appelant malloc ou vous pouvez prendre est comme un tableau char et passer l'adresse à la fonction plutôt que la valeur.

+0

Je vais essayer sprintf et posterai mes conclusions. Merci! –

+0

D'accord, sprintf fonctionne, mais il n'imprime que le dernier numéro du tableau. Une idée de ce qui pourrait être faux? –

2
void MyIntToChar(int *arrayOfInt, char* output); 

C'est faux de plusieurs façons. Tout d'abord, c'est un abus de langage. Vous ne pouvez pas, en général, convertir un nombre entier en un caractère, car seulement dix de tous les intergers (0 ... 9) entreraient dans un. Donc, je suppose que vous voulez convertir des entiers en _strings à la place.

Ensuite, si vous passez des tableaux à des fonctions, ils se désintègrent en pointeurs vers leur premier élément, et toutes les informations sur la taille du tableau sont perdues. Ainsi, lorsque vous passez des tableaux à fonctionner, vous devez également transmettre des informations de taille.
Soit utiliser la voie C de faire cela et passer dans le nombre d'éléments que std::size_t (à obtenir comme sizeof(myarray)/sizeof(myarray[0])):

void MyIntToStr(int *arrayOfInt, std::size_t arraySize, char* output); 

Ou faire les choses comme C++ et passer en deux itérateurs, une pointant vers le premier élément (soi-disant commencer itérateur) et l'autre pointant vers une derrière la dernière (fin itérateur):

void MyIntToStr(int *begin, int *end, char* output); 

Vous pouvez améliorer que de ne pas insister sur les itérateurs étant int*, mais tout ce qui, quand déréférencé, donne un int:

template< typename FwdIt > 
void MyIntToStr(FwdIt begin, FwdIt end, char* output); 

(. Les modèles devraient vous obliger à mettre en œuvre l'algorithme dans un en-tête)

Ensuite, il y a les problèmes avec la sortie. Tout d'abord, attendez-vous vraiment tous les numéros à écrire dans une chaîne? Si oui, comment devraient-ils être séparés? Rien? Espace blanc? Virgule?
Ou pensez-vous qu'un tableau de chaînes sera renvoyé?


En supposant que vous voulez vraiment une chaîne, si je passe le tableau {1, 2, 3, 4, 5} dans votre fonction, il a besoin d'espace pour cinq entiers à un seul chiffre, plus l'espace nécessaire pour quatre séparateurs. Votre signature de fonction suggère que vous vouliez que je l'attribue d'avance, mais franchement, si je dois calculer moi-même, je ferais aussi bien de faire les conversions moi-même. En outre, je n'ai aucun moyen de vous dire combien de mémoire char* points, de sorte que vous ne pouvez pas vérifier si j'avais raison. Comme l'ont découvert des générations de développeurs, il est si difficile d'obtenir à chaque fois que plusieurs langages informatiques ont été inventés pour faciliter les choses aux programmeurs. L'un de ceux-ci est C++, qui vient aujourd'hui avec une classe de chaîne de redimensionnement dynamique.
Il serait beaucoup plus facile (pour vous et pour moi), si je pouvais vous passer un stirng et vous écrivez dans ce:

template< typename FwdIt > 
void MyIntToChar(FwdIt begin, FwdIt end, std::string& output); 

Notez que je passe ce la chaîne par référence non const. Cela vous permet de modifier ma chaîne et de voir les modifications que vous avez faites.
Cependant, une fois que nous faisons cela, vous pourriez tout aussi bien revenir une nouvelle chaîne au lieu de me requireing passer un à vous:

template< typename FwdIt > 
std::string MyIntToChar(FwdIt begin, FwdIt end); 

Cependant, si vous voulez vraiment un tableau de chaînes renvoyées, vous ne devriez pas prendre une chaîne à écrire, mais un moyen où les écrire. La façon naïve de le faire serait de passer un tableau dynamiquement re-sizable de chaîne dynamiquement re-taille. En C++, ceci est écrit std::vector<std::string>:

template< typename FwdIt > 
void MyIntToStr(FwdIt begin, FwdIt end, std::vector<std::string>& output); 

Encore une fois, il pourrait être préférable que vous retour un tel tableau (bien que certains seraient en désaccord depuis la copie d'un tableau de chaîne peut être considéré comme cher).Cependant, le meilleur moyen de le faire ne m'obligerait pas à accepter le résultat sous la forme d'un 'std :: vector'. Et si j'avais besoin des chaînes dans une liste (liée) à la place? Ou écrit dans un flux?
La meilleure façon de le faire serait pour votre fonction d'accepter un itérateur de sortie auquel vous écrivez votre résultat:

template< typename FwdIt, typename OutIt > 
void MyIntToStr(FwdIt begin, FwdIt end, OutIt output); 

Bien sûr, maintenant c'est si général qu'il est difficile de voir ce qu'il fait, donc c'est bon on lui a donné un bon nom. Cependant, en regardant cela, je pense immédiatement que cela devrait s'appuyer sur une autre fonction qui est probablement nécessaire encore plus que celui-ci: Une fonction qui prend un entier et le convertit en une chaîne. En supposant que nous avons une telle fonction:

std::string MyIntToStr(int i); 

il est très facile à mettre en œuvre les versions du tableau:

template< typename FwdIt, typename OutIt > 
void MyIntToStr(FwdIt begin, FwdIt end, OutIt output) 
{ 
    while(begin != end) 
    *output++ = MyIntToStr(*begin++); 
} 

Maintenant, tout ce qui vous reste à faire est de mettre en œuvre cette fonction std::string MyIntToStr(int i);. Comme quelqu'un l'a déjà écrit, cela se fait facilement en utilisant des chaînes de caractères et vous ne devriez pas avoir de problème pour trouver de bons exemples. Cependant, il est encore plus facile de trouver de mauvais exemples, donc je préfère vous donner un ici:

std::string MyIntToStr(int i); 
{ 
    std::ostringstream oss; 
    oss << i: 
    if(!oss) throw "bah!"; // put your error reporting mechanism here 
    return oss.str(); 
} 

Bien sûr, les modèles donnés, facile à généraliser à accepter tout ce qui est diffusable:

template< typename T > 
std::string MyIntToStr(const T& obj); 
{ 
    std::ostringstream oss; 
    oss << obj: 
    if(!oss) throw "bah!"; // put your error reporting mechanism here 
    return oss.str(); 
} 

Notez que, compte tenu de ce modèle de fonction générale, le MyIntToStr() travaillant sur les tableaux fonctionne maintenant automatiquement sur les tableaux de tout type sur lesquels travaille le modèle de fonction qui travaille sur un objet.


Ainsi, à la fin de ce (plutôt épique, je excuses) voyage, voici ce que nous sommes arrivés à: un modèle de fonction généralisée pour convertir quoi que ce soit (ce qui peut être écrit à un flux) dans une chaîne, et un modèle de fonction généralisé pour convertir le contenu de n'importe quel tableau d'objets (qui peuvent être écrits dans un flux) en un flux.

Notez que, si vous aviez au moins une douzaine de conférences 90mins sur C++ et vos instructeurs ne parvenez pas à vous assez apprendre à au moinscomprendrece que j'ai écrit ici, vous avezpasété bien enseigné selon les normes modernes d'enseignement C++.

+0

Je crois que vous avez oublié l'opérateur ++ dans 'MyIntToStr'. L'itérateur 'output' n'est pas avancé. –

+0

@Maciej: En effet, merci! Je l'ai corrigé. – sbi

1

est ici une possibilité si vous êtes prêt à revenir sur un changement de prototype de la fonction

template<int n> 
void MyIntToChar(int (&iarr)[n], string &output){ 
    stringstream ss; 
    for(size_t id = 0; id < n; ++id){ 
     ss << iarr[id]; 
     if(id != n - 1) ss << " "; 
    } 
    output = ss.str(); 
} 

int main(){ 
    int numbers[3] = {11, 26, 81}; 
    string out = ""; 
    MyIntToChar(numbers, out); 
} 
0

On dirait que vous souhaitez utiliser C lang. Voici un exemple. Il y a un extra "," à la fin de la sortie, mais cela devrait vous donner une idée du concept. En outre, j'ai changé le type de retour afin que je sache combien d'octets de sortie ont été utilisés. L'alternative serait d'initialiser la sortie serait null.

int MyIntToChar(int *arrayOfInt, char* output) { 
    int bytes_used = 0; // use to bump the address past what has been used 
    for (int i = 0 ; i < sizeof(arrayOfInt); ++i) 
     bytes_used += sprintf(output + bytes_used, "%u, ", arrayOfInt[i]); 

    return bytes_used; 
} 

int main() {  
    int numbers[5] = {5, 2, 11, 26, 81}; // to properly initialize this string? 
    char output[sizeof(int)*sizeof(numbers)/sizeof(int) + sizeof(numbers)*2]; // int size plus ", " in string 

    int bytes_used = MyIntToChar(numbers, output); 
    printf("%*s", bytes_used, output);// this should print "11 26 81" or "11, 26, 81". 
    }