如何在 C# 中增加混合字母数字?

How to increment mixed Alphanumeric in C#?

我在一个项目中有要求生成连续的行和列,它们是字母数字值。

最终用户将传递他想要开始的行和列的起始值,以及他想要生成多少行和多少列。

对于字母,最大值为 Z

对于数字,最大值为 9

如果最终用户传递了这些参数:

开始行 = 0A

起始列 = A9Z

行数 = 2

列数 = 5

我想得到这个结果:

我想出了一个非常简单的解决方案来实现它,我想分享这个控制台应用程序:

class Program
{
    static void Main(string[] args)
    {
        var row = "0A";
        var column = "A9Z";
        var rowsCount = 2;
        var columnsCount = 5;
        var rowCharArray =row.ToArray().Reverse().ToArray();
        var columnCharArray = column.ToArray().Reverse().ToArray();
        for (int i = 0; i < rowsCount; i++)
        {
            for (int j = 0; j < columnsCount; j++)
            {
                columnCharArray = incrementChar(columnCharArray);
                var currentColumn = string.Join("", columnCharArray.Reverse().ToArray());
                var currentRow= string.Join("", rowCharArray.Reverse().ToArray());

                Console.WriteLine(currentRow  + "-" + currentColumn);
            }
            columnCharArray = column.ToArray().Reverse().ToArray();
            rowCharArray= incrementChar(rowCharArray);
            Console.WriteLine("-------------------------------");
        }

        Console.ReadLine();
    }

    static char[] incrementChar(char[] charArray,int currentIndex=0)
    {
        char temp = charArray[currentIndex];

        if (charArray.Length -1 == currentIndex && (temp == '9' || temp == 'Z'))
            throw new Exception();

        temp++;
        if(Regex.IsMatch(temp.ToString(),"[A-Z]"))
        {
            charArray[currentIndex] = temp;
        }
        else
        {
            if (Regex.IsMatch(temp.ToString(), "[0-9]"))
            {
                charArray[currentIndex] = temp;
            }
            else
            {
                currentIndex++;
                incrementChar(charArray, currentIndex);
            }
        }
        if (currentIndex != 0)
            charArray = resetChar(charArray, currentIndex);

        return charArray;
    }

    static char[] resetChar(char[] charArray,int currentIndex)
    {
        for (int i = 0; i < currentIndex; i++)
        {
            if (charArray[i] == 'Z')
                charArray[i] = 'A';
            else if (charArray[i] == '9')
                charArray[i] = '0';
        }
        return charArray;
    }
}

您可能需要重新考虑您的方法。与其维护字母数字值并尝试递增它,不如将值维护为包含 RowColumn 值的 class,然后使用 ToString 将其转换为字母数字表示。像这样:

class RowCol
{
    private int _row;
    private int _col;

    public int Row
    {
        get { return _row; }
        set
        {
            // Row is of the form <digit><letter
            // giving you 260 possible values.
            if (value < 0 || value > 259)
                throw new ArgumentOutOfRangeException();
            _row = value;
        }
    }

    public int Col
    {
        get { return _col; }
        set
        {
            // Col is <letter><digit><letter>,
            // giving you 6,760 possible values
            if (value < 0 || value > 6759)
                throw new ArgumentOutOfRangeException();
            _col = value;
        }
    }

    public string RowString
    {
        get
        {
            // convert Row value to string
            int r, c;
            r = Math.DivMod(_row, 26, out c);
            r += '0';
            c += 'A';
            return string.Concat((char)r, (char)c);
        }
        set
        {
            // convert string to number.
            // String is of the form <letter><digit>
            if (string.IsNullOrEmpty(value) || value.Length != 2
                || !Char.IsDigit(value[0] || !Char.IsUpper(value[1]))
                throw new ArgumentException();
            _row = 26*(value[0]-'0') + (value[1]-'A');
        }
    }

    public string ColString
    {
        get
        {
            int left, middle, right remainder;
            left = Math.DivRem(_col, 260, out remainder);
            middle = Math.DivRem(remainder, 26, out right);
            left += 'A';
            middle += '0';
            right += 'A';
            return string.Concat((char)left, (char)middle, (char)right);
        }

        set
        {
            // Do standard checking here to make sure it's in the right form.
            if (string.IsNullOrEmpty(value) || value.Length != 3
                || !Char.IsUpper(value[0] || !Char.IsDigit(value[1]) || !Char.IsUpper(value[2]))
                throw new ArgumentException();

            _col = 260*(value[0] - 'A');
            _col += 26*(value[1] - '0');
            _col += value[2] - 'A';
        }
    }

    public override string ToString()
    {
        return RowString + '-' + ColString;
    }

    public RowCol(int row, int col)
    {
        Row = _row;
        Col = _col;
    }

    public RowCol(string row, string col)
    {
        RowString = row;
        RowString = col;
    }
}

(代码尚未测试,但这是总体思路。)

这比您拥有的代码多一点,它隐藏了 RowCol class 中的复杂性,而不是强迫您在主程序逻辑中处理它。这里的重点是您只想增加行或列;您不需要考虑如何完成。它使您的主要程序逻辑更容易理解。例如:

string startRow = "0A";
string startCol = "B0A";
RowCol rc = new RowCol("0A", "B0A");
for (int r = 0; r < rowsCount; r++)
{
    rc.ColString = "B0A";
    for (int c = 0; c < columnsCount; c++)
    {
        Console.WriteLine(rc);
        rc.Row = rc.Row + 1;
    }
    rc.Col = rc.Col + 1;
}

通过将其转换为简单的转换问题并将其封装在 class 中,我使代码更加健壮和灵活,并且更易于测试、理解和使用。