Golden Basim Ответов: 2

C# инкрементная строка, содержащая число с особыми случаями ?


привет,
у меня есть строка, как А02540 или А02540а или 00A2052255c025 или 00501C2326 или 00801 , я хочу увеличить любой из них или любую другую строку один за другим (автоматическое увеличение), чтобы стать :
А02541 или А02540а1 или 00A2052255c026 или 00501C2327 или 00808

Что я уже пробовал:

string intPart = string.Join("", serialTXT.Reverse().TakeWhile(char.IsDigit).Reverse());
Int64 intP = Int64.Parse(intPart);
string newString = serialTXT.Remove(serialTXT.Length - intPart.Length) +
            (intP < 10 ? "0" + (intP + endnumber) : (intP + endnumber).ToString());


но в этом случае он игнорирует "ноль" 00801 и преобразовать его в 801

Richard MacCutchan

если строка, представляющая число, содержит ведущие нули, то вам нужно подсчитать их перед выполнением преобразования. Затем вы можете добавить их обратно в созданную вами новую строку.

Golden Basim

но эта проблема не возникает ни с одной строкой , содержащей букву типа (00501C2326), как это определить

Richard MacCutchan

Вам нужно создать алгоритм, который может работать для каждого типа чисел. Если часть его хранится в виде строки, то начальные нули будут сохранены. Но если вся строка числовая и вы преобразуете ее в целое число, то начальные нули будут потеряны.

Gerry Schmitz

Что о aa9?

Patrice T

Вы уверены насчет 00801 => 00808 ?
Что будет дальше для A99 ?

2 Ответов

Рейтинг:
18

BillWoodruff

Есть несколько крайних случаев, для которых вам нужно определить свою стратегию:

1 Что делать с ведущими нулями : xxxx09 должен стать xxxx10 или xxxx0010

2 xx23yyy или 23xxx : xx24yyy или 24xxx ?

3 Что делать, если строка не содержит цифр ?

Вот "отправная точка": ни один из крайних случаев, упомянутых выше, не обрабатывается, но вычисляется количество ведущих нулей ... Я оставил тебе места, чтобы ты понял, что делать.:

public string IncString(string input, int inc = 1)
{
    Char ch = input.Last();
    
    if (Char.IsDigit(ch))
    {
        StringBuilder sb = new StringBuilder();
        
        sb.Append(ch);
        
        int leadingzeroes = 0;
        
        int length = input.Length;
        
        for (int i = length - 2; i >= 0; i--)
        {
            ch = input[i];
        
            if (Char.IsDigit(ch))
            {
                sb.Insert(0, ch);
            }
            else
            {
                break;
            }
        }
        
        string snum = sb.ToString();
        
        leadingzeroes = snum.TakeWhile(chr => chr == '0').Count();
        
        int num = Int32.Parse(sb.ToString()) + inc;
        
        sb.Clear();
        
        // sb.Insert(?);
        
        // if (leadingzeroes > 0) sb.Append(?);
        
        // sb.Append(?);
        
        return sb.ToString();
    }
    
    return string.Empty;
}


Golden Basim

привет, спасибо за ваш ответ :
1 Что делать с ведущими нулями : xxxx09 должен стать xxxx10 или xxxx0010
xxxx09 должен стать xxxx10

2 xx23yyy или 23xxx : xx24yyy или 24xxx ?
нет , он должен стать xx23yyy1 ,23xxx2, а также xx23yyy99 должен стать xx23yyy100

3 Что делать, если строка не содержит цифр ?
Abcdf должен стать Abcdf0

как этого добиться ?

BillWoodruff

все части, которые вам нужны, находятся прямо там, в примере кода : изучайте, экспериментируйте, учитесь

[no name]

+5 место для улучшения, но красиво сделано

Рейтинг:
0

Luc Pattyn

Hi,

I would not rely on numeric types for this job, just operate on characters:

- use three state variables: bool carry (initially false), bool insideFirstNumber (initially false), and int countNumbers (initially zero);

- scan the string right to left;

- while finding digits:
    - if insideFirstNumber is false, set carry true, increment countNumbers, 
      and if it was zero, then and only then set insideFirstNumber true;
    - if insideFirstNumber and carry both true, emit incremented digit and clear carry,
      unless it was a "9", then emit "0" and set carry true;
    - otherwise just copy the digit.

- while finding non-digits but also when reaching start of string:
    - clear insideFirstNumber;
    -if carry is true, emit a "1" (number gets extra digit e.g. 99 -> 100) and clear carry;
    - copy the non-digit (not at start of string!).

All this would take about 20 lines of code, nothing fancy, no LINQ, no lambdas, just one StringBuilder object.

:)


PS: вышеизложенное превратило бы A02540a в A02541a; если вы действительно хотите получить A02540a1, то потребуются небольшие корректировки, все станет еще проще, так как теперь insideFirstNumber и carry изначально будут истинными, а countNumbers вообще не понадобятся.