0

First, my apologies if this is posted twice. I think the site may have burped.

I have an apparently impossible requirement for a clinical trials pharma application in my C# course. Please, someone tell me if I'm interpreting this part of the assignment incorrectly (copied verbatim from handout):

"MONTHS      NUMBER OF TREATMENTS (use a Switch command)

    1 -19        10 -30
    20 - 39      31 -60
    40 - 59      61 - 100
    60 - 79      101 - 130
    80 - 99      131 - 180

For Example:

If the randomly chosen # of months is from 20 through 39 - the number of treatments will be a random number from 31 through 60. If the # of months is 82 - the number of treatments is from 131 through 180."

The number of months the patient is available for the trial is input directly into a text box; my code supplies the random ACTUAL months the patient is participating in the clinical trial. I already know that ranges CANNOT be used in switch commands. Since this instructor also teaches Visual Basic, which apparently does support ranges in a switch command, she may have gotten the two confused (which, sadly, happens with alarming frequency). At any rate, everything I have read said this is flatly impossible with a switch case.

I have no idea how to accomplish this without an if/else tree instead of a switch. Can anyone give me any ideas? PLEASE, no regex or LINQ. We are not covering either one.

Here's all of my code. What is here works; file read/write isn't implemented yet, but I already understand that part.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace NallyKProgram3ClinicalTrials
{
    public partial class NallyKClinicalTrialsForm : Form
    {
        public NallyKClinicalTrialsForm()
        {           InitializeComponent();      }

        private StreamWriter outputFile;
        private StreamReader inputFile;

        int numberOfMonthsInTrialRangeInteger;
        int numberAssignedToPatientInteger;
        int numberOfMonthsInTrialInteger;
        int numberOfTreatmentPlanInteger;
        int numberOfTreatmentsInteger;

        // const string CASE_STRING; this attempt didn't work

        Random rndNumber = new Random();

        Boolean duplicateNameBoolean;

        private void NallyKClinicalTrialsForm_Load(object sender, EventArgs e)
        {

            reportLabel.ResetText();
            removePatientButton.Enabled = false;
            writeFileButton.Enabled = false;

        }

        private void addPatientButton_Click(object sender, EventArgs e)
        {

            if (patientNameTextBox.Text.Trim() != string.Empty)
            {

                checkForDuplicateNames();

                generatePatientNumber(rndNumber);

                if (duplicateNameBoolean == false)
                {

                    if (numberOfMonthsTextBox.Text.Trim() != string.Empty)
                    {

                        if (int.TryParse(numberOfMonthsTextBox.Text.Trim(), out numberOfMonthsInTrialRangeInteger))
                        {

                            if (numberOfMonthsInTrialRangeInteger < 1 || numberOfMonthsInTrialRangeInteger > 99)
                            {

                                errorProvider1.SetError(numberOfMonthsTextBox, "The number of months available for participation in this trial must not be less than 1 or greater than 99.");
                                numberOfMonthsTextBox.Focus();
                                numberOfMonthsTextBox.SelectAll();

                            }

                            else
                            {

                                generateNumberOfMonthsInTrial(rndNumber);
                                generateTreatmentPlan(rndNumber);
                                // determineCaseString(); NOPE!
                                // determineNumberOfTreatments(rndNumber); TO DO
                                addToListBox();
                                addToNamesListBox();
                                readFileButton.Enabled = false;
                                removePatientButton.Enabled = true;
                                writeFileButton.Enabled = true;

                            }

                        }

                        else
                        {

                            errorProvider1.SetError(numberOfMonthsTextBox, "Please enter a number.");
                            numberOfMonthsTextBox.Focus();
                            numberOfMonthsTextBox.SelectAll();

                        }

                    }

                    else
                    {

                        numberOfMonthsTextBox.Text = "          ";
                        errorProvider1.SetError(numberOfMonthsTextBox, "You must enter a number of months.");
                        numberOfMonthsTextBox.Focus();
                        numberOfMonthsTextBox.SelectAll();

                    }

                }

                else
                {

                    errorProvider1.SetError(namesListBox, patientNameTextBox.Text + " is a duplicate name. Please enter a different name.");
                    patientNameTextBox.Focus();
                    patientNameTextBox.SelectAll();

                }

            }

            else
            {

                patientNameTextBox.Text = "          ";
                errorProvider1.SetError(patientNameTextBox, "You must enter a patient name.");
                patientNameTextBox.Focus();
                patientNameTextBox.SelectAll();

            }


        }

        private void checkForDuplicateNames()
        {

            int indexInteger = 0;
            duplicateNameBoolean = false;

            while (indexInteger < namesListBox.Items.Count)
            {

                if (patientNameTextBox.Text.ToLower().Trim() ==
                    namesListBox.Items[indexInteger].ToString().ToLower())
                {

                    duplicateNameBoolean = true;

                    indexInteger = namesListBox.Items.Count;

                }

                indexInteger++;

            }


        }

        private Random generatePatientNumber(Random rndNumber)
        {

            numberAssignedToPatientInteger = rndNumber.Next(1000, 9999);
            return rndNumber;

        }

        private Random generateNumberOfMonthsInTrial(Random rndNumber)
        {

            numberOfMonthsInTrialInteger = rndNumber.Next(1, numberOfMonthsInTrialRangeInteger);
            return rndNumber;

        }

        private Random generateTreatmentPlan(Random rndNumber)
        {

            numberOfTreatmentPlanInteger = rndNumber.Next(1, 5);
            return rndNumber;

        }

        //private void determineCaseString() NOPE, NOPE, NOPE
        //{

        //  if ((numberOfTreatmentPlanInteger >= 1) && (numberOfTreatmentPlanInteger < 20)) CASE_STRING = "a"; // clever, but error!
        //  if ((numberOfTreatmentPlanInteger >= 20) && (numberOfTreatmentPlanInteger < 40)) CASE_STRING = "b";
        //  if ((numberOfTreatmentPlanInteger >= 41) && (numberOfTreatmentPlanInteger < 60)) CASE_STRING = "c";
        //  if ((numberOfTreatmentPlanInteger >= 60) && (numberOfTreatmentPlanInteger < 80)) CASE_STRING = "d";
        //  if ((numberOfTreatmentPlanInteger >= 80) && (numberOfTreatmentPlanInteger < 100)) CASE_STRING = "e";

        //}

        //private Random determineNumberOfTreatments(Random rndNumber)
        //{

        //  numberOfTreatmentsInteger = rndNumber.Next(10, CASE_STRING); 

        //}

        private void addToListBox()
        {

            patientInformationListBox.Items.Insert(0, numberAssignedToPatientInteger.ToString() + "," + numberOfTreatmentPlanInteger + "," + numberOfMonthsInTrialInteger + "," + Environment.NewLine); // number of treatments goes after the final comma

        }

        private void addToNamesListBox()
        {

            namesListBox.Items.Insert(0, patientNameTextBox.Text.Trim());

        }

        private void exitButton_Click(object sender, EventArgs e)
        {

            this.Close();

        }

        private void removePatientButton_Click(object sender, EventArgs e)
        {

            if (patientInformationListBox.SelectedIndex > -1)
                patientInformationListBox.Items.RemoveAt(patientInformationListBox.SelectedIndex);

            else MessageBox.Show("You must select an entry you wish to remove from the list.", "SELECT AN ITEM TO REMOVE", MessageBoxButtons.OK, MessageBoxIcon.Information);

        }

        private void patientNameTextBox_TextChanged(object sender, EventArgs e)
        {

            errorProvider1.SetError(patientNameTextBox, "");
            errorProvider1.SetError(patientInformationListBox, "");

        }

        private void numberOfMonthsTextBox_TextChanged(object sender, EventArgs e)
        {

            errorProvider1.SetError(numberOfMonthsTextBox, "");

        }

    }

}
2
  • C# does not allow you to use ranges in switch-statements, but it does allow you to concatenate them so that you can list all the cases and then write a single block of code, so you can do this: switch (months) { case 1: case 2: case 3: case 4: .... case 19: treatments = r.Next(10, 31); break; case 20: case 21: case 22: ... case 39: treatments = r.Next(30, 61); break; Commented Nov 22, 2015 at 19:30
  • However, but this may be of no help to you if you have to use a switch statement, this is the wrong tool for the job. Either a series of if-statements with range checks, or a table would be a much better fit for this kind of problem. Commented Nov 22, 2015 at 19:31

2 Answers 2

4

You're right in that C# does not allow you to use ranges in the switch-statement. In fact, C# only allows you to write a case X: where X is a single constant literal value.

However, C# does allow you to fall through from one case to another, and thus allows you to list all the cases for which you can write one single body of code to execute.

As such, you can write the code like this:

switch (months)
{
    case 1:
    case 2:
    case 3:
    ...
    case 19:
        treatments = r.Next(10, 31);
        break;
    case 20:
    case 21:
    case 22:
    ...
    case 39:
        treatments = r.Next(30, 61);
        break;
    case 40:
        ...

Now, is that the best you can do?

No. You can notice a pattern in the ranges here. Each range goes from X to X+19, where X is a number divisible by 20, so you can use the fact that integer division will truncate downwards:

int monthsSection = months / 20; // 0-19 --> 0, 20-39 --> 1, etc.
switch (monthsSection)
{
    case 0: // 0-19
        treatments = r.Next(10, 31);
        break;
    case 1: // 20-39
        treatments = r.Next(30, 61);
        break;
    case 2: // 40-59
    ...

Yes, this will include 0 as well. If that is a problem then I would simply add a specific if-statement in front to filter it out.

Sign up to request clarification or add additional context in comments.

2 Comments

Interesting, and thanks! I honestly didn't even notice that there was a pattern to the ranges. In the reading I did trying to figure this out, it was implied that fall-through was something to be avoided, so I didn't even consider taking advantage of it. Thanks a LOT; I think I can tackle this and get it finished now!
Consider marking one of the answers here as accepted if you've verified that it solves your problem.
1

If you have to use a switch, you could divide your months by 20, and then do a switch on that. Something like this:

int monthValue = numberOfTreatmentPlanInteger / 20;
switch (monthValue)
{
   case 0:
      // between 10 and 30 treatments
      break;
   case 1: 
      // between 31 and 60 treatments
      break;
   case 2:
      // between 61 and 100 treatments
      break;
   // and so on
}

2 Comments

But fix your comments
@Steve What do you mean fix my comments?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.