0

Now I am trying to check for correct format in this ID number entered by the user in this program. Now I am aware of the match case, but I'm trying to avoid doing that. I was considering a foreach loop, but the ID is in XX-9999 format and I don't know how to check different data types in that kind of loop.

I tried to use a for loop because my thinking was since a string is just an array of characters, that I can treat it as such. But I think that my index is being checked instead of the string characters.

Either way, here is my method:

public bool Validate_Employee_ID()
        {
            const int VALID_LENGTH = 7;  // Length of a valid string
            bool valid = true;   // Flag to indicate validity
            string strEmployeeID = txtEmployeeID.Text.Trim();  // get trimmed string from txtEmployeeID
            string[] stringEmpIDSplit = strEmployeeID.Split('-');

            if (strEmployeeID.Length == VALID_LENGTH)
            {
                // Check the first two characters in string.
                for (int i = 0; i <= strEmployeeID[1]; i++)
                {
                    // if the character is not a letter, valid equals false
                    if (!char.IsLetter(strEmployeeID[i]) == true)
                    {
                        MessageBox.Show("1) The employee ID must be in the following format: XX-9999.", "Entry Check", MessageBoxButton.OK, MessageBoxImage.Information);
                        txtEmployeeID.Focus();
                        // first two chars are not letters
                        valid = false;
                        return valid;
                    }
                }
                // Check the rest of the string to check the format.
                for (int j = strEmployeeID[3]; j <= strEmployeeID[6]; j++)
                {
                    // if the character is not a letter, valid equals false
                    if (!char.IsDigit(strEmployeeID[j]) == true)
                    {
                        MessageBox.Show("2) The employee ID must be in the following format: XX-9999.", "Entry Check", MessageBoxButton.OK, MessageBoxImage.Information);
                        txtEmployeeID.Focus();
                        // last 4 chars are not numbers
                        valid = false;
                        return valid;
                    }
                }
            }
            else valid = true;
            return valid;
        }
5
  • 1
    Consider using a regular expression - you can easily check a RegEx match online with a regex tester and use that instead of writing complex code, unless of course you need to write the code for some sort of assignment etc? Commented Apr 27, 2020 at 16:28
  • Assuming it needs to be 2 alpha characters in CAPS, then a dash, then 4 numerics, the following regex will work for that: ^[A-Z]{2}-[0-9]{4}$ - if you need additional characters you can add them to the match groups Commented Apr 27, 2020 at 16:29
  • Is this an assignment? For a real world use case, a regex would be the Correct Thing™, but this sounds like an assignment where you're being asked specifically to work with loops. Commented Apr 27, 2020 at 16:31
  • sorry, updated my comment to add start/end of string matchers in there too (otherwise you could add characters to start and end and still get a match) Commented Apr 27, 2020 at 16:31
  • Yes, it is for an assignment, but at this point, I'm considering just taking the points and doing the RegEx. But is there really no way to do it otherwise? I know at this point I'm confusing my index for my characters, but how would I check them? Commented Apr 27, 2020 at 16:51

2 Answers 2

1

In this case you don't really need a for loop since we have the All method from System.Linq which can help us check if all characters in a string meet some criteria:

const int validLength = 7;                   // Length of a valid string
var employeeID = txtEmployeeID.Text.Trim();  // Get trimmed string from txtEmployeeID
var empIDSplit = employeeID.Split('-');      // Split on the dash character

if (employeeID.Length != validLength ||      // Validate overall length
    empIDSplit.Length != 2 ||                // Validate number of parts after split
    empIDSplit[0].Length != 2 ||             // Validate first part length
    empIDSplit[1].Length != 4 ||             // Validate second part length
    !empIDSplit[0].All(char.IsLetter) ||     // Validate first part are letters
    !empIDSplit[1].All(char.IsDigit)         // Validate second part are digits
    )
{
    MessageBox.Show("1) The employee ID must be in the following format: XX-9999.",
        "Entry Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
    txtEmployeeID.Focus();
    return false;
}

return true;

If you do find yourself needing to use a for loop, along with a variable to track the validation result, here's a way to do that. We start with the assumption that the input is valid, and then we "fail fast" if we find that it's not.

When we find invalid data, we set the variable to false and then skip to the end of the method, where we display our message (if needed) and return the result:

public bool Validate_Employee_ID()
{
    const int validLength = 7;                   // Length of a valid string
    var isValid = true;                          // Validation result
    var employeeID = txtEmployeeID.Text.Trim();  // Trimmed string from txtEmployeeID
    var empIDSplit = employeeID.Split('-');      // Split on the dash character

    if (employeeID.Length != validLength ||      // Validate overall length
        empIDSplit.Length != 2 ||                // Validate number of parts after split
        empIDSplit[0].Length != 2 ||             // Validate first part length
        empIDSplit[1].Length != 4)               // Validate second part length
    {
        isValid = false;
    }
    else
    {
        foreach (var chr in empIDSplit[0])
        {
            if (!char.IsLetter(chr))
            {
                isValid = false;
                break;         // "Fail fast" by exiting the loop at the first bad data
            }
        }

        // "Fail fast" by not checking the second part if the first one failed
        if (isValid)          
        {
            foreach (var chr in empIDSplit[1])
            {
                if (!char.IsDigit(chr))
                {
                    isValid = false;
                    break;     // "Fail fast" by exiting the loop at the first bad data
                }
            }
        }
    }

    // Display an error message if the input was invalid
    if (!isValid)
    {
        MessageBox.Show("1) The employee ID must be in the following format: XX-9999.",
            "Entry Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
        txtEmployeeID.Focus();
    }

    return isValid;
}
Sign up to request clarification or add additional context in comments.

2 Comments

I was considering using split, but I couldn't implement it properly. This is genius on your part. Thank you.
Glad it worked for you! I added another sample that uses the foreach loops and a variable that tracks the validation result, since sometimes that's necessary. It shows how to "fail fast" as soon as we get bad data, to avoid unnecessary checking when we know we're going to fail anyway.
0

You're confusing your index for your characters

// Check the rest of the string to check the format.
for (int j = 3; j <= 6; j++)
{
    // if the character is not a letter, valid equals false
    if (!char.IsDigit(strEmployeeID[j]))
    { 
       //snip
    }
}

1 Comment

I was afraid of that, but what can I do to fix that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.