Преамбула
Простая учебная задача, но почему-то до моего решения долюбились, в конце объясню, почему долюбились, и почему, в случае C#, это зря было.
Решение
И так, задача состоит в том, чтобы всякие кратные единицы перевести в байты (кому надо обратную задачу, либо все во все — пишите в комментарии). Для этого достаточно сделать следующую функцию, исходя из того, что 1 Кб == 1024 Б, 1 Мб = 1024 Кб, 1 Гб = 1024 Мб. В функцию добавим некую переменную-модификатор, для консольного приложения было проще сделать строковую, в ином случае, может и есть сделать отдельный Enum
для единиц, но я обошелся строковой.
Переменная-модификатор (modificator
) принимает строковые значения G
(g
), M
(m
) и K
(k
), соответственно для гига- мега- и килобайта.
Функция получается такая:
public static ulong ToBytes(ulong bytes, string modificator)
{
ulong Ret = 0;
switch (modificator)
{
case "":
{
Ret = bytes;
} break;
case "K":
case "k":
{
Ret = bytes * 1024;
} break;
case "M":
case "m":
{
Ret = bytes * 1024 * 1024;
} break;
case "G":
case "g":
{
Ret = bytes * 1024 * 1024 * 1024;
} break;
default:
{
throw new ArgumentException("Wrong modificator ["
+ modificator + "]. Set K(k), M(m), G(g)");
}
}
return Ret;
}
Почему не стал заморачиваться с Enum’ом
Задача была очень простая, чисто учебная. Консольная программа принимает в качестве одного параметра число с единицей без пробела, т.е. команда вида program.exe 10G
, должна вывести количество байт. Надо ли Enum
городить, ну красиво было бы, но до Enum
‘ов они не добрались 🙂
В основной программе надо отрезать последний символ из параметра, проверить ли является он нужной буквой (K/M/G
) и пересчитать. Если буквы нету, а только цифры — значит оно уже сразу байты.
В функции Main()
отрезаем последний символ от первого параметра командной строки, если он K/M/G
, считаем, что все остальное число, отрезаем его, а все остальное пытаемся сконвертировать в ulong (Int64)
и передать функции ToBytes()
с отрезанным символом, как модификатором для расчета. Если нет — просто считаем, что вся строка число, пытаемся конвертировать, а функции передаем пустой модификатор.
Ошибки конвертации ловим try/catch
:
string size_s = args[1];
try
{
string mdf = size_s.Substring(size_s.Length - 1, 1);
if ((mdf != "K") && (mdf != "k") && (mdf != "M") && (mdf != "m") &&
(mdf != "G") && (mdf != "g"))
{
mdf = "";
//in parameter only numbers or param wrong...
}
else // remove modificator
{
size_s = size_s.Substring(0, size_s.Length - 1);
}
BytesCount = ToBytes(Convert.ToUInt64(size_s), mdf);
}
catch (Exception ex)
{
Console.WriteLine("Wrong <size> parameter!");
Console.WriteLine(ex.Message);
Console.Write("Press Enter...");
Console.ReadLine();
return 2;
}
Пример целиком на GitHub
Почему долюбились
За вот эти вот конструкции:
Ret = bytes * 1024;
Ret = bytes * 1024 * 1024;
Ret = bytes * 1024 * 1024 * 1024;
Типа «ну тут числа, ты бы их сначала перемножил, результат записал , а потом на переменную помножил».
Почему зря.
Дебилы, бля, как говорил Лавров. В интерпретируемых языках или старом Трупопоскакале под DOS, может это и какой-то рояль играет, но в C# компилятор перемножает константы до сборки экзешника, а 1024*1024*1024
для компилятора константы, во время компиляции. Т.е. процессору скормят 1073741824
. А код останется более понятен и читабелен.