开发者

Stuck in a loop

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
    开发者_如何学Go    {
            Console.WriteLine("Please enter two valid conversion types \n");
            break;
        }
        line = convert.ReadLine();
    }
}

The file consists of the following:

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

The user will input something like 6,ounce,gram

The idea is that it finds the correct line by checking if the first and second words in the file are the same as the second and third the user enters.

The problem is that if it checks the first line and it fails the if statement, if goes through to the else statement and stops. I am trying to find a way where it will stop after the it finds the correct line but not until. If someone types in a value that isn't in the file, then it should show an error.


Remove the break statement in the else clause. That's causing it to exit the loop.

You could really improve this code by reading the conversion factors into an internal data structure, perhaps a dictionary keyed by the "from" conversion unit with the value be a dictionary of possible output units and their conversion factor -- or a custom key/value pair if you only have a single possible output unit. This would turn your inner loop into a two-stage look up (much faster) and save you the trouble of having to re-read the conversion file each time. As @Ben points out, the error message is in the wrong place, too. It needs to be outside the loop/lookup, and only executed if no match was found.

Sample code -- note there is no input validation in this 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");
    }
}


I'm guessing you understand what your code is doing so I don't have to point out that the break is causing it to stop. You're just asking for what to do to accomplish what you want. The break inside your if block is correct, and will make it stop when a match is found.

A continue won't work either, it's right now saying it's an error if the first line doesn't match.

Why do you have the outer while loop? Particularly, why are you reading the file inside the loop? Read it once, then loop.

I think what you want is to set something like bool found = false; above your line reading loop. Then inside the successful if block, set found = true; before the break. Get rid of the else block entirely, as that is not an error. It just means you haven't found it yet. Then outside the loop, put

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

Use found to determine whether to proceed or not, after looping through the whole file.


The else should be removed completely.

Introduce boolean 'success' flag, initialize to false and set it to true when you find a value.

Then, outside the while loop,

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


To fix this, I'd extract parts of the algorithm into separate methods so you can isolate the flow control. I'd start by writing a method that searches a file for conversion settings that match the user's input:

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
}

Next, create a method called ConvertAndDisplayInput to isolate the code you want to execute once you've found a match - it's just like your success condition above, so I won't repeat it here.

Finally, I'd write the control logic (shown for a single conversion here, you might want a caller to loop over this until the user hits a carriage return or something):

// 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");
    }
}


if tvanfosson answer does not work. you can replace the break he mentioned by continue. It will make the execution go to the next loop

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜