Сериализация чревата ловушками. Автоматическая поддержка сериализации этой формы делает часть внутренностей класса общедоступного API (который является, почему javadoc дает Вам сохраненные формы классов ).
Для долгосрочной персистентности, класс должен быть в состоянии декодировать эту форму, которая ограничивает изменения, которые можно внести для классификации дизайна. Это повреждает инкапсуляцию.
Сериализация может также привести к проблемам безопасности. Способностью сериализировать любой объект это имеет ссылку на, класс может получить доступ к данным, это обычно не было бы в состоянии к (путем парсинга результирующих данных байта).
существуют другие проблемы, такие как сериализированная форма внутренних классов, не являющихся четко определенным.
Создание всех сериализуемых классов усилило бы эти проблемы. Выезд Эффективный Java Второй Выпуск , в особенности Объект 74: Реализация, сериализуемая рассудительно .
ПРИМЕЧАНИЕ: Этот ответ неверен , так как "aa" должно следовать после "Z" ... (см. Комментарии ниже)
Вот алгоритм, который может работать:
каждая «строка» представляет собой число с заданным основанием (здесь: удвоенное количество букв в алфавите).
Таким образом, следующий шаг может быть вычислен путем анализа «числовой» -строки обратно в int, добавив 1 и затем отформатировав его обратно в базу.
Пример:
"a" == 1 -> step("a") == step(1) == 1 + 1 == 2 == "b"
Теперь ваша проблема сводится к синтаксическому анализу строки как числа с заданной базой и ее переформатированию. Быстрый поиск в Google предлагает эту страницу: http://everything2.com/title/convert+any+number+to+decimal
Как это реализовать?
РЕДАКТИРОВАТЬ: Эта ссылка выглядит еще более многообещающей: http://www.citidel.org/bitstream/10117/20/12/convexp.html
Достаточный набор подходов, вот мой: -
Функция:
private static string IncrementString(string s)
{
byte[] vals = System.Text.Encoding.ASCII.GetBytes(s);
for (var i = vals.Length - 1; i >= 0; i--)
{
if (vals[i] < 90)
{
vals[i] += 1;
break;
}
if (vals[i] == 90)
{
if (i != 0)
{
vals[i] = 97;
continue;
}
else
{
return new String('a', vals.Length + 1);
}
}
if (vals[i] < 122)
{
vals[i] += 1;
break;
}
vals[i] = 65;
break;
}
return System.Text.Encoding.ASCII.GetString(vals);
}
Тесты
Console.WriteLine(IncrementString("a") == "b");
Console.WriteLine(IncrementString("z") == "A");
Console.WriteLine(IncrementString("Z") == "aa");
Console.WriteLine(IncrementString("aa") == "ab");
Console.WriteLine(IncrementString("az") == "aA");
Console.WriteLine(IncrementString("aZ") == "ba");
Console.WriteLine(IncrementString("zZ") == "Aa");
Console.WriteLine(IncrementString("Za") == "Zb");
Console.WriteLine(IncrementString("ZZ") == "aaa");
public static class StringStep
{
public static string Next(string str)
{
string result = String.Empty;
int index = str.Length - 1;
bool carry;
do
{
result = Increment(str[index--], out carry) + result;
}
while (carry && index >= 0);
if (index >= 0) result = str.Substring(0, index+1) + result;
if (carry) result = "a" + result;
return result;
}
private static char Increment(char value, out bool carry)
{
carry = false;
if (value >= 'a' && value < 'z' || value >= 'A' && value < 'Z')
{
return (char)((int)value + 1);
}
if (value == 'z') return 'A';
if (value == 'Z')
{
carry = true;
return 'a';
}
throw new Exception(String.Format("Invalid character value: {0}", value));
}
}
Разделите входную строку на столбцы и обработайте каждый справа налево, как если бы это была простая арифметика. Примените любой код, который у вас есть, который работает с одним столбцом, к каждому столбцу. Когда вы получаете Z, вы «увеличиваете» следующий левый столбец, используя тот же алгоритм. Если следующего левого столбца нет, вставьте букву «а».
Простите, что вопрос сформулирован частично. Я отредактировал вопрос так, чтобы он соответствовал требованиям, без редактирования функция закончила бы n раз за шагом, увеличивая каждое слово со строчного a до верхнего регистра z без его «повторного анализа».
Пожалуйста, перечитайте вопрос, включая отредактированную часть
Это частный случай системы счисления. Он имеет базу 52. Если вы напишете синтаксический анализатор и логику вывода, вы можете выполнять любую арифметику, очевидно, здесь +1 (++). Цифры от «a» до «z» и от «A» до «Z», где «a» - ноль, а «Z» - 51
. Таким образом, вам нужно написать синтаксический анализатор, который берет строку и строит int или long от него. Эта функция называется StringToInt () и реализуется прямо (преобразование символа в число (0..51), умножение на 52 и получение следующего символа)
И вам нужна обратная функция IntToString, которая также реализуется прямо (по модулю int с 52 и преобразовать результат в цифру, разделить int на 52 и повторять это до тех пор, пока int не станет нулем)
С помощью этих функций вы можете делать что-то вроде этого: IntToString (StringToInt ("ZZ") +1) // Будет "ааа"
Это то, что я придумал. Я не полагаюсь на преобразование ASCII int, а скорее использую массив символов. Это должно делать именно то, что вы ищете.
public static string Step(this string s)
{
char[] stepChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
char[] str = s.ToCharArray();
int idx = s.Length - 1;
char lastChar = str[idx];
for (int i=0; i<stepChars.Length; i++)
{
if (stepChars[i] == lastChar)
{
if (i == stepChars.Length - 1)
{
str[idx] = stepChars[0];
if (str.Length > 1)
{
string tmp = Step(new string(str.Take(str.Length - 1).ToArray()));
str = (tmp + str[idx]).ToCharArray();
}
else
str = new char[] { stepChars[0], str[idx] };
}
else
str[idx] = stepChars[i + 1];
break;
}
}
return new string(str);
}
Вам необходимо учитывать A) тот факт, что у заглавных букв десятичное значение в таблице Ascii ниже, чем у младших случай те. B) Таблица не является непрерывной AZaz - между Z и a есть символы.
public static string stepChar(string str)
{
return stepChar(str, str.Length - 1);
}
public static string stepChar(string str, int charPos)
{
return stepChar(Encoding.ASCII.GetBytes(str), charPos);
}
public static string stepChar(byte[] strBytes, int charPos)
{
//Escape case
if (charPos < 0)
{
//just prepend with a and return
return "a" + Encoding.ASCII.GetString(strBytes);
}
else
{
strBytes[charPos]++;
if (strBytes[charPos] == 91)
{
//Z -> a plus increment previous char
strBytes[charPos] = 97;
return stepChar(strBytes, charPos - 1); }
else
{
if (strBytes[charPos] == 123)
{
//z -> A
strBytes[charPos] = 65;
}
return Encoding.ASCII.GetString(strBytes);
}
}
}
Вам, вероятно, понадобится некоторая проверка, чтобы убедиться, что входная строка содержит только символы A-Za-z
Править Приведен в порядок код и добавлена новая перегрузка для удаления избыточного байта [] -> строка -> преобразование байта []
LetterToNum
должен быть функцией, которая отображает "a" в 0 и «Z» до 51.
NumToLetter
обратное.
long x = "aazeiZa".Aggregate((x,y) => (x*52) + LetterToNum(y)) + 1;
string s = "";
do { // assertion: x > 0
var c = x % 52;
s = NumToLetter() + s;
x = (x - c) / 52;
} while (x > 0)
// s now should contain the result
Это очень похоже на то, как работали бы столбцы Excel, если бы они были неограниченными. Вы можете изменить 52 на ссылку chars.Length для упрощения модификации.
static class AlphaInt {
private static string chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static string StepNext(string input) {
return IntToAlpha(AlphaToInt(input) + 1);
}
public static string IntToAlpha(int num) {
if(num-- <= 0) return "a";
if(num % 52 == num) return chars.Substring(num, 1);
return IntToAlpha(num / 52) + IntToAlpha(num % 52 + 1);
}
public static int AlphaToInt(string str) {
int num = 0;
for(int i = 0; i < str.Length; i++) {
num += (chars.IndexOf(str.Substring(i, 1)) + 1)
* (int)Math.Pow(52, str.Length - i - 1);
}
return num;
}
}