Utilisons un langage de script pour une vie C ++ confortable 2 Générer automatiquement une source C ++

Dans un article précédent, j'ai écrit Let's code avec une bonne visibilité en utilisant le type std :: map.

** Pour un environnement embarqué supérieur à un certain niveau **

Si vous avez plus d'une certaine quantité d'environnement embarqué (par exemple, une carte telle que Raspberry Pi ou Zynq), vous pouvez utiliser g ++ et il ne devrait y avoir aucun problème avec STL. Et vous pouvez écrire des programmes à l'aide de conteneurs STL. Je pense que STL devrait être activement utilisé pour créer une version qui fonctionne correctement lors du développement sur un PC (je suis inquiet de l'implémentation de C ++ de certains compilateurs commerciaux, et de STL qui utilise ce compilateur Je pense que la situation est différente de l'ancien temps où je m'inquiétais de l'implémentation de. À ce moment-là, j'ai entendu dire qu'on m'avait demandé de réécrire le code écrit en STL en code non STL.) .. Les spécifications externes de STL sont claires et il est facile pour plusieurs membres de partager une compréhension commune. Autant j'ai aimé utiliser STL, autant j'évite l'effort de clarifier suffisamment les spécifications et de tester les algorithmes des autres parties.

Si l'implémentation finale est un PC, il pourrait être laissé en STL, et il y aurait une option pour le laisser en STL dans certains environnements embarqués. Dans cet article, pour ceux qui ne peuvent toujours pas utiliser STL pour leur implémentation finale, je suggère d'utiliser STL lors du développement de code qui fonctionne correctement sur la version PC en montrant que la source C ++ peut être générée automatiquement. C'est quelque chose à faire.

** Un script qui facilite la migration vers un environnement où le type std :: map ne peut pas être utilisé **

Le script Python suivant lit les données de mappage de std :: map <std :: string, int> dans le fichier withMap.cpp et génère une séquence d'instructions if () else if () sans utiliser STL. est.

intoElseif.py


# -*- coding: utf-8 -*-
def parseMap(name):
    u"""
    std::map<std::string, int>Lisez atmomicNumbers.
Lisez la clé et la valeur de la carte et attribuez-les au dictionnaire Python.
    """
    d = {}
    for line in open(name, "rt"):
        oline = line.strip().replace(",", " ")
        if len(oline) > 1 and oline[-1] == ",":
            oline = oline[:-1]
        f = oline.split()
        if len(f) == 4 and f[0] == "{":
            d[int(f[2])] = f[1]
    return d

if __name__ == "__main__":
    u"""
C basé sur le dictionnaire lu/C++Génère une instruction if else if.
    """
    d = parseMap(name="withMap.cpp")
    keys = d.keys()
    keys.sort()
    k = keys[0]
    print """if(strcmp(instr, %s) == 0){
    r = %s;
}""" % (d[k], k),
    for i in range(1, len(keys)):
        k = keys[i]
        print """else if(strcmp(instr, %s) == 0){
    r = %s;
}""" % (d[k], k),

Fichier C ++ contenant les données de type std :: map des données d'entrée

withMap.cpp


#include <iostream>
#include <string>
#include <map>

/**Conteneur de type de carte qui correspond au numéro atomique du symbole d'élément
*L'initialisation est effectuée en même temps que la déclaration.
*(Seulement jusqu'à Ne dans le deuxième cycle est décrit.)
*/
std::map<std::string, int> atmomicNumbers = {
	{ "H", 1 },
	{ "He", 2 },
	{ "Li", 3 },
	{ "Be", 4 },
	{ "B", 5 },
	{ "C", 6 },
	{ "N", 7 },
	{ "O", 8 },
	{ "F", 9 },
	{ "Ne", 10 }
};

int main(int argc, char* argv[]){
	std::string symbol = "Be";
	
	std::cout << symbol << " " << atmomicNumbers[symbol] << std::endl;
}

Résultat d'exécution

generated.cpp


if(strcmp(instr, "H") == 0){
    r = 1;
} else if(strcmp(instr, "He") == 0){
    r = 2;
} else if(strcmp(instr, "Li") == 0){
    r = 3;
} else if(strcmp(instr, "Be") == 0){
    r = 4;
} else if(strcmp(instr, "B") == 0){
    r = 5;
} else if(strcmp(instr, "C") == 0){
    r = 6;
} else if(strcmp(instr, "N") == 0){
    r = 7;
} else if(strcmp(instr, "O") == 0){
    r = 8;
} else if(strcmp(instr, "F") == 0){
    r = 9;
} else if(strcmp(instr, "Ne") == 0){
   r = 10;
}

De cette manière, il est facile de générer automatiquement une partie du programme à partir de la partie de données régulière. Par conséquent, nous insistons pour assurer la santé du programme en utilisant un format de données clair. Si vous écrivez un programme en utilisant std :: map, l'effet de l'augmentation des données sera { "Ne", 10 } Tout ce que vous avez à faire est d'ajouter les lignes qui suivent, éliminant ainsi le besoin de changer le code ailleurs.

Je pense que c'est d'abord pour sécuriser un mécanisme qui peut garantir son bon fonctionnement, puis pour sécuriser les performances (vitesse de traitement, taille du programme) lors de la mise en œuvre.

** Supplément: **

Dans l'exemple ci-dessus, sans utiliser std :: map

python


char* [] atomicSymbols = {
    "H", "He",
    "Li", "Be", "B", "c", "N", "O", "F", "Ne"
}

Il est également possible de traiter en utilisant le tableau. Cependant, nous utilisons ici le type std :: map <std :: string, int> pour suggérer d'utiliser une bibliothèque standard pour la logique qui associe les clés aux valeurs.

** Remarque: **

La génération de parties d'un programme à l'aide d'un langage de script a longtemps été utilisée par certains. Lors de l'écriture de nombreux contenus similaires avec uniquement les données remplacées, une partie du programme était automatiquement générée en fonction des données. Les données sont mises à jour fréquemment, il peut donc ne pas être possible de les écrire à la main une fois. Une telle approche peut être utilisée pour n'importe quelle langue. Par exemple, Ratfor, un langage d'extension FORTRAN, a utilisé un préprocesseur pour masquer les lacunes de la spécification du langage FORTRAN. Je pense qu'améliorer la visibilité du traitement en cours consiste à assurer la santé du programme à un stade précoce.

Post-scriptum: "Méthode de programmation" Chapitre 9 Notation "9.5 Programme pour décrire le programme" inclut le nom Il est conçu pour générer un message d'erreur basé sur un fichier d'en-tête contenant des commentaires. Dans ce livre, le script de perl se convertit automatiquement. De cette manière, le langage de script peut être utilisé pour accélérer le développement dans le langage C / C ++.

python


enum {
    Eperm,  /* Permission denied */
    Eio,    /* I/O error */
    Efile,  /* File does not exist */
    Emem,   /* Memory limit reached */
    Espace, /* Out of file space */
    Egreg   /* It's all Greg's fault */
};

Il existe un exemple de génération de la déclaration suivante à partir de.

python


char *errs[] = {
   "Permission denied", /* Eperm */
   "I/O error", /* Eio */
   "File does not exist", /* Efile */
   "Memory limit reached", /* Emem */
   "Out of file space", /* Espace */
   "It's all Greg's fault", /* Egreg */ 
 };

Recommended Posts

Utilisons un langage de script pour une vie C ++ confortable 2 Générer automatiquement une source C ++
Utilisez un langage de script pour une vie confortable en C ++
Utilisons un langage de script pour une implémentation C ++ confortable après vérification avec python
Utilisons le langage de script pour une vie confortable en C ++ 4 - Utilisons la propre bibliothèque de C ++ à partir du langage de script -
Utilisez un langage de script pour une vie confortable en C ++ 3-Laissez le graphique à matplotlib-
Utilisons un langage de script pour une vie confortable en C ++ 6-Que diriez-vous de développer un programme en tant que bibliothèque pour Python?
Utilisez un langage de script pour une vie C ++ confortable-OpenCV-Port Python vers C ++ -
Utilisez un langage de script pour une vie C ++ confortable 5 - Utilisez l'environnement intégré de Spyder pour vérifier les données numériques -
Générer automatiquement un dictionnaire polaire utilisé pour l'analyse des émotions
Remarques sur l'intégration du langage de script dans les scripts bash
Remarque 2 pour intégrer le langage de script dans un script bash
Scripting Language C —— Comment un fichier texte sans shebang est exécuté