2010-04-16 5 views
1
while (true) 
{ 
    //read in the file 
    StreamReader convert = new StreamReader("../../convert.txt"); 

    //define variables 
    string line = convert.ReadLine(); 
    double conversion; 
    int numberIn; 
    double conversionFactor; 

    //ask for the conversion information 
    Console.WriteLine("Enter the conversion in the form (Amount, Convert from, Convert to)"); 
    String inputMeasurement = Console.ReadLine(); 
    string[] inputMeasurementArray = inputMeasurement.Split(','); 


    //loop through the lines looking for a match 
    while (line != null) 
    { 
     string[] fileMeasurementArray = line.Split(','); 
     if (fileMeasurementArray[0] == inputMeasurementArray[1]) 
     { 
      if (fileMeasurementArray[1] == inputMeasurementArray[2]) 
      { 
       Console.WriteLine("The conversion factor for {0} to {1} is {2}", inputMeasurementArray[1], inputMeasurementArray[2], fileMeasurementArray[2]); 

       //convert to int 
       numberIn = Convert.ToInt32(inputMeasurementArray[0]); 
       conversionFactor = Convert.ToDouble(fileMeasurementArray[2]); 

       conversion = (numberIn * conversionFactor); 
       Console.WriteLine("{0} {1} is {2} {3} \n", inputMeasurementArray[0], inputMeasurementArray[1], conversion, inputMeasurementArray[2]); 
       break; 
      } 
     } 
     else 
     { 
      Console.WriteLine("Please enter two valid conversion types \n"); 
      break; 
     } 
     line = convert.ReadLine(); 
    } 
} 

Le fichier comprend les éléments suivants:Coincé dans une boucle

ounce,gram,28.0 
pound,ounce,16.0 
pound,kilogram,0.454 
pint,litre,0.568 
inch,centimetre,2.5 
mile,inch,63360.0 

L'utilisateur saisira quelque chose comme 6, once, gramme

L'idée est qu'il trouve la bonne ligne en vérifiant si les premier et second mots du fichier sont les mêmes que les deuxième et troisième mots saisis par l'utilisateur.

Le problème est que si elle vérifie la première ligne et échoue l'instruction if, si elle passe à l'instruction else et s'arrête. J'essaie de trouver un moyen où il s'arrêtera après qu'il trouve la ligne correcte mais pas avant. Si quelqu'un tape une valeur qui ne se trouve pas dans le fichier, une erreur doit apparaître.

Répondre

5

Supprimez l'instruction break dans la clause else. Cela provoque la sortie de la boucle. Vous pouvez vraiment améliorer ce code en lisant les facteurs de conversion dans une structure de données interne, peut-être un dictionnaire claveté par l'unité de conversion "de" avec la valeur soit un dictionnaire des unités de sortie possibles et leur facteur de conversion - ou un paire clé/valeur personnalisée si vous n'avez qu'une seule unité de sortie possible. Cela transformerait votre boucle interne en une recherche en deux étapes (beaucoup plus rapide) et vous éviterait d'avoir à relire le fichier de conversion à chaque fois. Comme le souligne @Ben, le message d'erreur est également au mauvais endroit. Il doit être en dehors de la boucle/recherche, et seulement exécuté si aucune correspondance n'a été trouvée.

Exemple de code - noter qu'il n'y a pas de validation d'entrée dans ce code:

var conversions = new Dictionary<string,Dictionary<string,double>>(); 
var convert = new StreamReader("../../convert.txt"); 
while ((var line = convert.ReadLine()) != null) 
{ 
    string components = line.Split(','); 
    Dictionary<string,double> unitConversions; 
    if (conversions.ContainsKey(components[0])) 
    { 
     unitConversions = conversions[components[0]]; 
    } 
    else 
    { 
     unitConversions = new Dictionary<string,double>(); 
     conversions.Add(components[0], unitConversions); 
    } 
    unitConversions.Add(components[1], Convert.ToDouble(components[2])); 
} 

while (true) 
{ 
    //ask for the conversion information  
    Console.WriteLine("Enter the conversion in the form (Amount, Convert from, Convert to)");  
    var inputMeasurement = Console.ReadLine();  
    var inputMeasurementArray = inputMeasurement.Split(','); 

    bool converted = false; 
    Dictionary<string,double> unitConversion; 
    if (conversions.TryGetValue( inputMeasurementArray[1], out unitConversion)) 
    { 
     double conversionFactor; 
     if (unitConversion.TryGetValue(inputMeasurementArray[2], out conversionFactor)) 
     { 
      converted = true; 
      conversion = Convert.ToDouble(inputMeasurementArray[0]) * conversionFactor; 
      Console.WriteLine("{0} {1} is {2} {3} \n", inputMeasurementArray[0], inputMeasurementArray[1], conversion, inputMeasurementArray[2]);    
     } 
    } 

    if (!converted) 
    { 
     Console.WriteLine("Please enter two valid conversion types\n"); 
    } 
} 
+0

Vous êtes mieux sur la piste que j'étais, mais l'autre serait toujours sur le mauvais niveau (ie une erreur par ligne dans le fichier de définition de conversion, pas une erreur par mauvaise entrée) –

+0

@Ben - Je n'ai pas pris la peine de vérifier si l'interface était correct. Il est clair que le message d'erreur doit sortir de la boucle interne, auquel cas la clause else n'est même pas nécessaire. En outre, je considérerais obtenir les données de conversion une seule fois et les stocker en interne de sorte qu'il n'est pas nécessaire de les relire à chaque fois. Si vous faites cela, alors la boucle interne devient une simple recherche dans un dictionnaire. – tvanfosson

+0

-1, car il traite toujours chaque ligne qui ne correspond pas à une erreur. Il ne résout pas le problème de comment vérifier le fichier entier avant d'échouer. – Tesserex

0

si tvanfosson réponse ne fonctionne pas. vous pouvez remplacer la pause qu'il a mentionnée par continuer. L'exécution passera à la prochaine boucle

+0

Ce serait mauvais - vous sauteriez le ReadLine() 'et juste créé une boucle sans fin .. –

2

Je suppose que vous comprenez ce que fait votre code, donc je n'ai pas besoin de préciser que le break l'arrête. Vous demandez simplement quoi faire pour accomplir ce que vous voulez. Le break à l'intérieur de votre bloc if est correct, et le fera s'arrêter lorsqu'une correspondance est trouvée.

Un continue ne fonctionnera pas non plus, c'est en ce moment dire que c'est une erreur si la première ligne ne correspond pas. Pourquoi avez-vous la boucle while externe? En particulier, pourquoi lisez-vous le fichier à l'intérieur la boucle? Lisez-le une fois, puis bouclez.

Je pense que ce que vous voulez est de mettre quelque chose comme bool found = false; au-dessus de votre boucle de lecture de ligne. Ensuite, à l'intérieur du bloc if réussi, définissez found = true; avant le break. Débarrassez-vous complètement du bloc else, car ce n'est pas une erreur. Cela signifie simplement que vous ne l'avez pas encore trouvé. Ensuite, en dehors de la boucle, mettre

if (!found) Console.WriteLine("Please enter two valid conversion types \n"); 

Utilisez found pour déterminer si de procéder ou non, après en boucle dans le fichier entier.

+0

Merci beaucoup cela a fonctionné, je savais que je devais le prendre en dehors de la boucle en quelque sorte mais je suis nouveau à C# et couldn Ne pensez pas à la meilleure façon de le faire! – sark9012

1

L'autre doit être complètement supprimé.

Introduisez l'indicateur booléen 'succès', initialisez-le à false et réglez-le sur true lorsque vous trouvez une valeur.

Ensuite, en dehors la boucle while,

if (success == false) { 
    Console.WriteLine("Please enter two valid conversion types \n"); 
} 
1

Pour résoudre ce problème, j'extraire des parties de l'algorithme dans des méthodes distinctes de sorte que vous pouvez isoler le contrôle de flux. Je commence par écrire une méthode qui recherche un fichier pour les paramètres de conversion qui correspondent à l'entrée de l'utilisateur:

private string[] FindConversionSetting(string[] input, StreamReader reader) 
{   
    do 
    { 
     string line = reader.ReadLine(); 
     if (line != null) 
     { 
      string[] settings = line.Split(','); 
      bool sourcesMatch = string.Compare(input[1], settings[0], true) == 0; 
      bool targetsMatch = string.Compare(input[2], settings[1], true) == 0; 

      if (sourcesMatch && targetsMatch) 
      {      
       return settings; // Match found 
      } 
     } 
    } while (line != null); 

    return null; // No match 
} 

Ensuite, créez une méthode appelée ConvertAndDisplayInput pour isoler le code que vous voulez exécuter une fois que vous avez trouvé un match - C'est juste comme votre condition de succès ci-dessus, donc je ne vais pas le répéter ici.

Enfin, j'écrire la logique de commande (montré pour une seule conversion ici, vous voudrez peut-être un appelant à boucle sur jusqu'à ce que l'utilisateur frappe un retour chariot ou quelque chose):

// In Program.Main (for example) 

Console.WriteLine("Enter the conversion in the form (Amount, Convert from, Convert to)"); 

string input = Console.ReadLine(); 

using (StreamReader reader = new StreamReader("../../convert.txt") 
{ 
    string[] conversionSetting = this.FindConversionSetting(input, reader); 

    if (conversionSetting != null) 
    { 
     this.ConvertAndDisplayInput(input, conversionSetting); 
    } 
    else 
    { 
     Console.WriteLine("Please enter two valid conversion types \n"); 
    } 
}