Programme AWK

Fermé
pepe - 22 nov. 2009 à 23:08
mamiemando Messages postés 33135 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 juin 2024 - 23 nov. 2009 à 03:18
Bonjour,
Je souhatairais faire des imbrications de if dans un programme "awk" sous la forme:
C= 0.196;
if (A = 11 && (B < 19950800)) C=0.22;
if (A = 11 && (B > 19950800)) C=0.202;
if (A= 11 && (B> 20000400)) C=0.196;
if (A=13 && (B < 19950800)) C=0.186;
if (A=13 && (B> 19950800)) C=0.206;
if (A=13 && (B> 20000400)) C=0.196;
if (A=14 && (B < 19950800)) C=0.248666;
if (A=14 && (B > 19950800)) C=0.206;
if (A=14 && (B > 20000400)) C=0.196;
Avec A, B, et C de svariables.
Mais cela ne fonctionne pas alors je ne sais si c'est dû au fait que je ne respecte pas les espaces, ou un problème de programmation.
Dois-je ajouter des else avant les "if", mettre == plutôt que de mettre =, etc.
Entout cas , merci de votre aide.

1 réponse

mamiemando Messages postés 33135 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 juin 2024 7 756
23 nov. 2009 à 03:18
Quel fichier as-tu au départ et que veux-tu obtenur au départ ?
Je ne sais pas trop en quoi tu codes -on dirait du C- (et ce que tu codes, et ou les valeurs des constantes comparées à A et B) mais à mon avis, toutes ces constantes ne devraient pas être écrites en dur dans le programme.

Si c'est du C:

L'opérateur = ne sert pas à comparer deux valeurs, il affecte la valeur de droite dans la variable à gauche. L'opérateur = retourne la valeur affectée. Si celle-ci est non nulle, ça revient à la valeur booléenne "false", sinon à la valeur true.

Si tu veux vérifier si A est égal à 11 (etc...), c'est donc l'opérateur == que tu es sensé utiliser. De plus pour éviter de tester la valeur de A à chaque if, il serait plus raisonnable d'imbriquer les if (je ne sais pas trop si c'est de ça dont tu parlais). De plus des else if accéleront le programme. Il faut juste les mettre dans le bon ordre pour que le comportement reste le même, à savoir traiter les plages :
- B < 19950800
- 19950800 <= B <= 20000400
- B > 20000400

Tu noteras au passage que dans ton code actuel, C est modifié deux fois (peu importe la valeur de A) si 20000400, ce qui laisse penser que le code est mal architecturé.

if(A == 11){
  if     (B < 19950800) C = 0.22;
  else if(B > 20000400) C = 0.196; 
  else                  C = 0.202; // (B > 19950800)
}else if(A == 12){
  ...
}
...


Attention aux cas où l'on ne rentre dans aucun if, car C ne sera pas initialisée si elle ne rentre dans aucun if (à moins bien sûr qu'elle ne soit initialisée auparavant). Mais même là c'est pas génial, on compare à une variable numérique à un entier, donc un switch sera a priori plus efficace :

switch(A){
  case 11:
    switch(B){
      if     (B < 19950800) C = 0.22;
      else if(B > 20000400) C = 0.196;
      else                  C = 0.202;

    }
    break;
  case 12:
    switch(B){
      ...
    }
    break;
  ...
  default:
}


À ce stade ça commence à ressembler à quelque chose, mais toutes ces constantes en dur dans le code, ça reste franchement moche. Le code est manifestement redondant et on pourrait plutôt imaginer d'avoir un tableau de 3 cases sur 3 cases dans lequel on traite chacun des 9 cas traités.

Typiquement :
- la ligne 0 pour le cas A=11
- la ligne 1 pour le cas A=13
- la ligne 2 pour le cas A=14
- la colonne 0 pour le cas B < 19950800
- la colonne 1 pour le cas 19950800 <= B <= 20000400
- la colonne 2 pour le cas B > 20000400

Il suffit donc d'écrire un code du genre

unsigned i,j;
double matrice[3][3];

matrice = {
  {0.22,     0.202, 0.196},
  {0.186,    0.206, 0.196},
  {0.248666, 0.206, 0.196}
};

// Mapper A avec la bonne ligne dans la matrice (ligne i)
switch(A){
  case 11: i = 0; break;
  case 13: i = 1; break;
  case 14: i = 2; break;
  default: // lancer une erreur ?
}

// Mapper B avec la bonne colonne dans la matrice (colonne j)
if     (B < 19950800) j = 0;
else if(B > 20000400) j = 1;
else                  j = 2;

// Récupérer la constante C
C = matrice[i][j];


... et là on a un code plus optimisé, plus propre, plus facile à maintenir etc... Bon et tout ça c'est clair, ça ne se remet pas en forme avec juste un awk...

Bonne chance
0