0
votes

Y a-t-il un meilleur moyen d'écrire cela pour C ++?

L'objectif est de créer des substrings à partir d'une chaîne entrée en extrayant des mots séparés par des espaces.

Les sous-chaînes doivent être elles-mêmes elles-mêmes. P>

sonne facile, mais ce qui le rend difficile, mais ce qui le rend difficile Vous ne pouvez utiliser que Strcpy, STRCMP, SHLEN, STRCAT, STRNCPY, STRNCMP, STRNCY, STRNCMP, STRNLEN et STRNCAT. STRAND> P>

Exemple: P>

entrée: P>

"John 40 Hitman" code> p>

pilote: p> xxx pré>

sortie: p>

#include <iostream>
#include <cstring>
#include <stdio.h>

int main(){

const char *string = "Name Age Job";
char name[10];
char age[10];
char job[10];
int length = strlen(string);
int temp = 0;
bool flag = false;

for(int i = 0; i < length + 1; i++){
  if(isspace(string[i]) && !flag){
    strncpy(name, string, i);
    name[i] = '\0';
    temp = i;
    flag = !flag;
    cout << name << endl;
    continue;
  }
  if(isspace(string[i])){
    strncpy(age, string + temp + 1, length - i - 1);
    age[temp - i] = '\0';
    temp = i;
    cout << age << endl;
    continue;
  }
  if(string[i] == '\0'){
    strncpy(job, string + temp + 1, length);
    job[temp - i] = '\0';
    cout << job << endl;
  }
}


20 commentaires

codereview.stackexchange.com


Si seulement l'utilisation de fonctions C-Style STR est vraiment une exigence, votre classe est une classe de programmation C et non un C ++. Désolé, mais c'est la réalité. C ++ ify it en modifiant Char [] à STD :: String.


@Raffallo vient de poster un lien pourrait ne pas être aussi utile (même s'il s'agit de la bonne destination). OP: le site lié est destiné à optimiser le code de travail, de sorte que ce serait un meilleur ajustement pour le site sœur


@ ACRAIG5075 C'est une bonne pratique cependant, pour comprendre comment fonctionne des chaînes. Les programmeurs C ++ doivent le savoir même s'ils n'utilisent jamais STD :: String.


Essayez d'utiliser la méthode Strtok. Il réduira totalement la taille du code. Reportez-vous à Cplusplus.com/reference/cstring/strtok


En ce qui concerne l'examen du code - Oui, c'est le meilleur site pour obtenir des commentaires généraux sur le code de travail complet. Ce n'est pas hors du sujet ici, tant que le code est suffisamment localisé.


Je vote pour fermer cette question comme étant hors sujet, car la demande de révision de code de sa codes.


@Sameerkhan Je ferais certainement que mon professeur limitait ce problème à seulement les fonctions C-String susmentionnées et Strtok n'en faisait pas partie.


Même si cette intro est une intro une intro C ++, je pense que vous feriez mieux de convertir ce que vous avez à pure C et de modifier la balise en C .


@Souravghosh, aucune raison de si proche existe. Les questions demandant des améliorations pourraient être trop larges, mais il s'agit d'un exemple minimal et complet et le problème est clair.


La limitation implique-t-elle que vous ne pouvez pas utiliser STD :: String?


@ user124147777 Vous mentionnez certaines fonctions que vous pouvez utiliser uniquement - mais dans le code utilise d'autres choses - comme Isspace et Cout . Ce n'est pas clair ce que nous sommes autorisés.


Ok je vais répondre à cela juste à cause des votes rapprochés. Il est plus approprié pour codereview.stackexchange.com Mais ce n'est pas hors de sujet ici!


@Lundin en fait je suis en désaccord. C Cordes ne convient pas à C ++. Si vous aviez dit std :: vecteur s et fonctions reflétant la bibliothèque standard C, pouvant être pertinente pédagogiquement.


@Caleth, alors quand vous finissez par interagir avec une API C, vous allez juste rester assis là-bas dans le monde entier? Je suppose que cela fonctionnera bien tant que vous évitez les systèmes exotiques rares tels que Windows et Linux.


@Lundin non, vous appelez str.data () au dernier moment possible . Vous n'avez pas besoin d'utiliser les fonctions de chaîne C qui (doivent-elles) mélanger des allocations avec ce qu'ils sont là pour.


@Caleth C API s'attendra souvent à ce que vous fournissez un tampon de lecture / écriture sous la forme d'une matrice de caractères, de sorte que cela ne fonctionnera pas. Vous devez réellement comprendre comment les matrices de caractères fonctionnent, sans aucun égard.


@Lundin chacun de std :: string , std :: vecteur et std :: unique_ptr peut fournir un Pointeur sur un tableau de Char . C n'a aucun moyen de distinguer ceux des matrices brutes.


@Caleth ce que je veux dire, c'est void c_api (char * byf, taille_t bytes_to_return); . Vous ne pouvez pas passer c_str () à cela, car il est constitué qualifié et immuable.


@Lundin non plus. Il y a une surcharge non Const.


3 Réponses :


1
votes

La bonne façon de le faire avec des fonctions C ne serait que d'utiliser strtok , bien que l'on côtoie une chaîne en place.

En ce qui concerne votre code, il y a beaucoup de ramification inutile et chèques. Vous devriez éviter continuer , il s'agit d'un signe de près de 100% d'une boucle nécessitant des améliorations. Chaque fois que vous vous trouvez besoin de cela, il y a généralement une meilleure façon.

Vous devez également éviter Strncpy car comme vous l'avez remarqué, c'est une douleur à garder une trace de quand il nulle se termine et quand ce n'est pas le cas. C'est une fonction dangereuse et beaucoup plus lente que memcpy , qui pourrait être utilisé à la place.

Voici une version simplifiée basée sur l'utilisation de 2 pointes, l'une tout le temps défini sur le point l'espace suivant et l'un tout le temps réglé sur pointer au début du prochain mot valide. xxx

Ce code simplifie les choses en ne vérifiant pas si une chaîne serait adaptée et il ne veut pas 'T Allouer la mémoire. Le code de la qualité de la production réelle n'utiliserait pas char [5] [10] mais plutôt un tableau de pointeur char * [5] où chaque pointeur est défini sur le point de manière dynamique. mémoire allouée.


2 commentaires

Merci beaucoup! Peut-être que je vais trouver comment faire la matrice du pointeur de mienne


@ user12414777 - Un pointeur est simplement une variable normale qui contient l'adresse de quelque chose d'autre comme valeur - au lieu d'une valeur immédiate comme int A = 5; . Un pointeur tiendrait l'adresse où 5 est stocké en mémoire. Par exemple int * b; est un pointeur-to int et b = & a; attribue l'adresse où < code> 5 est stocké en mémoire comme valeur détenue par B (par exemple, B Pointe maintenant sur A ) - où < Code> 5 réside dans la mémoire.



2
votes

Tout ce que vous avez à faire est de remplacer l'espace '' '' ' code> avec ' \ 0 ' code> (l'extrémité de la chaîne) créant ainsi 3 sous-chaînes de l'original. Le programme suivant fait cela et vide simplement la chaîne à COUT code> mais vous pouvez contenir les pointeurs dans un tableau (par exemple. Char * Substring [3] Code>).

int main(){
    char string[] = "Name Age Job";
    char* temp = string;
    for(char* it = string; *it; ++it ) {
        if (*it == ' ') {
            *it = '\0';
            std::cout << temp << std::endl;
            temp= it + 1;
        }
    }
    std::cout << temp << std::endl;
}


4 commentaires

La chaîne d'entrée est immuable dans la question cependant.


Ensuite, vous finiriez par itération sur le même tableau deux fois, ce qui est lent.


La performance concerne la seule raison de déployer ce code manuellement. Et puis vous devez être très bon pour connaître le système cible. Même ma version est trop naïve d'être du code de qualité de la bibliothèque, même si je m'attends à ce qu'elle fonctionne bien sur des systèmes bas de gamme.


@LUNDIN Vous semblez manquer la prise principale ici: il est déjà assez facile d'optimiser si vous avez besoin d'une copie / deuxième itération et si vous avez besoin d'un code optimisé en premier lieu.



-1
votes

Je suis d'accord avec @ ACRAIG5075 lorsque votre code est plus C de C ++. Si vous envisagez d'écrire cela en C ++ à l'aide de la chaîne STL, une façon de procéder est la suivante.

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


std::vector<std::string> split_string( const std::string &srcString, const char &delimiterKeywrd )
{
    /**
     *  Splits a string according to a keyword delimiter and returns a vector with the 
     *  segments of the split string.
     *  
     *  Args:
     *      @param  srcString:          The required string to split.
     *      @param  delimiterKeywrd:    The delimiter keyword that the string will be splitted to
     *      @return segmentsVectr:      A vector holding the segments of the srcString that was splitted. 
     *
    */

    std::stringstream inputStr;
    inputStr.str( srcString );
    std::string segment;

    std::vector<std::string> segmentsVectr;

    while( std::getline( inputStr, segment, delimiterKeywrd ) )
    {
        segmentsVectr.push_back( segment );
    }

    return segmentsVectr;
}


int main() {
    std::string inputStr{"John 40 Hitman"};

    std::vector<std::string> result;
    char delimiterKeywrd = ' '; 

    result = split_string( inputStr, delimiterKeywrd );

    //  Iterate through the vector and print items on a different line.
    for ( const std::string &item : result )
    {
        std::cout << item << std::endl;
    }

    return 0;
}


0 commentaires