Сегодня я расскажу о том, как формировать строки, помещая в них значения переменных различных типов. Я думаю, вы знаете, что любое значение можно преобразовать в строку через метод ToString(). Например, так:
var a = 10.50;
var message = "Сумма = " + a;
var message = "Сумма = " + a;
Но, используя такой метод, вы можете получить строковое представление значения только в одном формате, определенном вашей текущей культурой (CultureInfo).
Сейчас мы рассмотрим, каким образом можно задавать формат для значений при формировании строки. Для этого в .NET есть встроенная возможность, представленная “записывающими” методами различных классов. К таким, например, относятся:
- System.String.Format
- Console.WriteLine
- StreamWriter.Write
Я буду рассматривать форматирование на примере String.Format, но то же самое можно использовать и в остальных методах. Выглядит это так:
var a = 10.50;
var message = string.Format("Сумма = {0}", a);
var message = string.Format("Сумма = {0}", a);
Метод String.Format принимает первым параметром шаблон строки, в которую подставляются форматированные значения. Шаблон содержит маркеры – фигурные скобки, которые указывают, куда необходимо подставить значения. В простейшем случае этот маркер содержит одно число – номер параметра, который надо подставить (0 – соответствует первому параметру).
В следующем коде у меня производится формирование строки из двух параметров:
var a = 10.50;
var dt = new DateTime(2011, 09, 01);
var message = string.Format("Сумма = {0}, Дата = {1}", a, dt);
var dt = new DateTime(2011, 09, 01);
var message = string.Format("Сумма = {0}, Дата = {1}", a, dt);
Но, как я уже сказал, мы также можем влиять на формат значений, которые вставляются в строку.
var a = 10.50;
var dt = new DateTime(2011, 09, 01);
var message = string.Format("Сумма = {0:c}, Дата = {1:d}", a, dt);
var dt = new DateTime(2011, 09, 01);
var message = string.Format("Сумма = {0:c}, Дата = {1:d}", a, dt);
В этом примере я внутри маркера задал форматы для обоих значений: для суммы я указал формат Currency (“:c” внутри маркера), для даты – “краткий формат даты” (“:d” в маркере).
Это примеры встроенных в .NET форматов, и конечный результат их применения зависит от текущей культуры (CultureInfo), которая по умолчанию соответствует настройкам Windows. Если у вас в Windows выбраны российские региональные настройки, то в данном примере сумма выведется в рублях, а дата в российском формате даты.
Иногда бывает необходимо преобразовать набор чисел в строки таким образом, чтобы все строки были выравнены по левому или правому краю и имели равные длины. Числа при этом дополняются пробелами слева или справа:
var a1 = 1234;
var a2 = 12345;
Console.WriteLine(@"{0,5:d}", a1); //по правому краю
Console.WriteLine(@"{0,5:d}", a2); //по правому краю
Console.WriteLine(@"{0,-5:d}", a1);//по левому краю
Console.WriteLine(@"{0,-5:d}", a2);//по левому краю
var a2 = 12345;
Console.WriteLine(@"{0,5:d}", a1); //по правому краю
Console.WriteLine(@"{0,5:d}", a2); //по правому краю
Console.WriteLine(@"{0,-5:d}", a1);//по левому краю
Console.WriteLine(@"{0,-5:d}", a2);//по левому краю
В этом примере внутри шаблона указывается дополнительный параметр, через запятую после индекса параметра. Этот параметр указывает минимальное число символов, которое должно быть в строке. Если это положительное число, то строки выравниваются по правому краю, если отрицательное – по левому.
Встроенные форматы
Кроме приведенных форматов существует еще много других встроенных форматов:
Код | Тип | Описание |
c/C | Валюта | |
d/D | Цифровой | Только для целых типов, выводит целое (с “-“ для отрицательных) |
e/E | Научный | Выводит число в экспоненциальном формате. Регистр буквы “E” влияет на регистр этой буквы при форматировании |
f/F | Фиксированная точка | Выводит целое или дробное число |
g/G | Общий | Выбирает формат в соответствии с типом значения и размером значения – научный или фиксированная точка. |
n/N | Разделители групп разрядов | Выводит целое или дробное число, но при этом отделяет группы разрядов |
p/P | Процент | Умножает число на 100 и выводит со знаком процентов |
r/R | Обратный | Только плавающая точка и BigInt; переводит в строку таким образом, что значение можно без потерь точности преобразовать обратно |
x/X | Шеснадцатиричный | Только для целых, переводит в Hex-формат. Регистр буквы X влияет на регистр символов в выходной строке. |
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx
Вместе с символом формата можно также указать число – точность:
var a = 1234.34542;
Console.WriteLine(@"{0:N3}", a);
В этом примере число указывает число символов после запятой.Console.WriteLine(@"{0:N3}", a);
Теперь посмотрим, какие есть встроенные форматы дат:
Код | Тип | Пример |
d | Короткая дата | 01.09.2011 |
D | Длинная дата | 1 сентября 2011 г. |
t | Короткое время | 10:20 |
T | Длинное время | 10:20:30 |
f | Длинная дата/короткое время | 1 сентября 2011 г. 10:20 |
F | Длинная дата/длинное время | 1 сентября 2011 г. 10:20:30 |
g | Короткая дата/короткое время | 01.09.2011 10:20 |
G | Короткая дата/длинное время | 01.09.2011 10:20:30 |
M/m | Месяц и день | сентября 01 |
o/O | Обратный | 2011-09-01T10:20:30.0000000 |
r/R | RFC1123 | Thu, 01 Sep 2011 10:20:30 GMT |
s | Для сортировки | 2011-09-01T10:20:30 |
u | Локальное, в универсальном формате | 2011-09-01 10:20:30Z |
U | GMT | 1 сентября 2011 г. 6:20:30 |
Y | Год и месяц | Сентябрь 2011 |
CultureInfo влияет на множество аспектов – символ валюты, символы разделителей, символ “-”, количество знаков после запятой по умолчанию. То же самое и с датами. CultureInfo определяет символы разделителей, имена месяцев и дней недели, форматы времени.
Таким образом, если вы используете для форматирования значений только встроенные форматы, то вы автоматически получите глобализацию преобразований чисел и дат в строки. В каждой стране это преобразование будет происходить по своим правилам.
С другой стороны, если вам необходимо при преобразовании применить другую культуру, то это, как правило, можно сделать, используя соответствующую перегрузку метода.
var a = 10.50;
var dt = new DateTime(2011, 09, 01);
var info = new CultureInfo(1033);
var message = string.Format(info, "Сумма = {0:c}, Дата = {1:d}", a, dt);
В этом примере я применил другую культуру для преобразования значений.var dt = new DateTime(2011, 09, 01);
var info = new CultureInfo(1033);
var message = string.Format(info, "Сумма = {0:c}, Дата = {1:d}", a, dt);
Свой формат
Если нас не устраивает встроенный формат, то можно задавать формат самостоятельно. Суть этого процесса в том, что вы с помощью специальных символов и обычного текста создаете строку формата, эти символы я дальше покажу в таблице, а пока пример.
Я произведу форматирование серийного номера, который, например, в базе данных лежит в виде целого Int32:
var message = string.Format("Серийный = {0:000-000-000}", a);
Console.WriteLine(message);
Здесь у меня внутри маркера 000-000-000 – это шаблон, в нем каждый 0 – это специальный символ цифры (вставляется цифра, если она есть, либо ‘0’), дефис – это просто промежуточный текст.Console.WriteLine(message);
var a = 2345.43;
var message = string.Format(@"Сумма = {0:#.00р\.}", a);
Console.WriteLine(message);
Здесь строка формата “#.00р\.”. В ней символ “#”, который я могу опустить, означает цифры (до запятой в этом примере), “.” – это разделитель дроби, “00” – означает “взять и показать две цифры после запятой”, “р” – просто текст – рубли, “\.” – просто точка; я использовал символ “\” перед точкой, т. к. точка – специальный символ.var message = string.Format(@"Сумма = {0:#.00р\.}", a);
Console.WriteLine(message);
Вот краткое описание специальных символов, которые можно использовать в своих шаблонах:
Код | Тип | Пример | Результат | Описание |
Исходное число | 1234,567 | |||
0 | Цифра или ноль | 00000.0000 | 01234, 5670 | Если нет цифры, то вместо маркера ставится 0 |
0.00 | 1234,56 | |||
# | Цифра | #####.#### | 1234,567 | Если нет цифры, то вместо маркера ничего не ставится |
#.## | 1234,56 | |||
. | Разделитель дроби | 0.# | 1234,5 | Интерпретируется только первая из точек |
, | Разделитель тысяч | 00,0 или 0,000 или 00,0,000 | 1 234 | Интерпретируется только первая из запятых. Слева и справа от запятой должны быть “0” или “#”, но не обязательно рядом |
,. | Масштабирование | 0,.0 | 1,2 | Число уменьшается в 1000^N раз, где N – число запятых, точка позволяет задать дробную часть. |
0, | 1 | Если дробной части нет, запятые ставятся в конце | ||
0,,.000 | 0,001 | |||
% | Процент | 0% | 123456% | Умножает на 100 и добавляет знак процента |
e | Экспонента | 00.0e+00 | 12,3e+02 | Научный формат, цифры после “E” задают число разрядов порядка |
; | Разделитель секций | 0.##;(0.#);ноль | 1234,56 | Позволяет задать три секции: отдельно для положительных, отрицательных чисел и нуля |
0.##;(0.#);ноль | (1234,56) | Для значения “-1234.56” | ||
0.##;(0.#);ноль | Нуль | Для значения “0” | ||
\ | Escape | \.##.#\. | .1234,5. | Дает возможность вставлять спец-символы как обычный текст |
Число положительное, поэтому будет использоваться первая секция. Сначала будет произведено деление на 1000 (символы “,.”), затем приведение к экспоненте (“e+00”), при котором будет оставлено 4 цифры слева от точки (четыре нуля), затем будет произведено округление до сотых (“.##”), и в конце разделение тысяч (первая запятая).
Кроме специальных символов в шаблон можно вставлять обычный текст, так я вставил скобки в шаблон с разделителем секций. Текст можно вставлять в любое место.
Стоит обратить внимание еще на два момента:
1. Eсли количество цифр целой части больше числа символов “0” и “#” слева от точки в шаблоне, то целая часть выводится все равно полностью. При этом лишние левые цифры ставятся в соответствие крайнему символу “0” или “#”. Например, используя шаблон “(#)##” для числа 12345, получим строку “(123)45”.
2. Если в числе нет целой части, например в числе 0,34, то шаблон “#.##” даст результат “,34”. Чтобы перед разделителем дроби был ноль, необходимо слева от точки использовать маркер “0”, как, например, здесь “0.##”.
Теперь посмотрим, какой арсенал у нас имеется для форматирования дат своим форматом. Здесь такой же принцип – для построения шаблона используются специальные символы.
Код | Тип | Результат | Описание |
Значение | 01.01.2001 14:20:30.1234 | ||
y | Год 0-99 | 1 | |
yy | Год 00-99 | 01 | |
yyyy | Год, 4 цифры | 2001 | |
M | Месяц 1-12 | 1 | |
MM | Месяц 01-12 | 01 | |
d | День 1-31 | 1 | |
dd | День 01-31 | 01 | |
h | Час 1-12 | 2 | |
hh | Час 01-12 | 02 | |
H | Час 1-24 | 14 | |
HH | Час 01-24 | 14 | |
m | Минута 0-59 | 20 | |
mm | Минута 00-59 | 20 | |
s | Секунда 0-59 | 30 | |
ss | Секунда 00-59 | 30 | |
f – ffffff | Доли секунды | 12 (для шаблона ff) | Количество f соответствует количеству разрядов долей секунды |
F-FFFFFF | Доли секунды, если они не равны 0 | 12 (для шаблона FF) | Количество F соответствует количеству разрядов долей секунды |
MMM | Сокращенное имя месяца | янв | |
MMMM | Имя месяца | Январь | |
ddd | Короткое имя дня недели | Пн | |
dddd | Имя дня недели | понедельник | |
tt | Маркер для “AM” и “PM” 12-часового формата | PM | |
zz | Смещение временное зоны, короткое | +03 | |
zzz | Смещение временное зоны, полное | +03:00 | |
gg | Эра | A.D. | |
: | Разделитель времени | 14:20:30 | |
/ | Разделитель даты | 01.01.2001 | |
\ | Escape | Дает возможность вставлять спец-символы как обычный текст | |
% | Custom Format | “%d” даст “1” | Указывается перед символом, чтобы указать, что это не встроенный формат |
При формировании строки специальные символы и их последовательности можно размещать как угодно и совместно с обычным текстом.
Вот несколько примеров:
Console.WriteLine(@"{0:dd/MM/yyyy}", dt); // 01.01.2001
Console.WriteLine(@"{0:dd/MM/yyyy HH:mm:ss}", dt); // 01.01.2001 10:20:30
Console.WriteLine(@"{0:dd/MM/yyyy HH часов}", dt); // 01.01.2001 10 часов
Console.WriteLine(@"{0:MMMM yyyy г.}", dt); // Январь 2001 г.
Что еще важно знать.Console.WriteLine(@"{0:dd/MM/yyyy HH:mm:ss}", dt); // 01.01.2001 10:20:30
Console.WriteLine(@"{0:dd/MM/yyyy HH часов}", dt); // 01.01.2001 10 часов
Console.WriteLine(@"{0:MMMM yyyy г.}", dt); // Январь 2001 г.
1. Те же самые строки форматов можно использовать, вызывая перегрузку метода ToString у чисел и дат.
var a = 10.50;
var message = a.ToString("c");
2. Еще раз напоминаю, что CultureInfo влияет на то, как будут работать встроенные форматы. Но кроме того, CultureInfo влияет и на то, как ведут себя специальные символы и их комбинации во встроенных форматах.var message = a.ToString("c");
Например, от этого зависят имена месяцев и дней недели, символ разделителя дат и времени, символы разделителя дроби и разделитель тысяч и др.
3. По возможности старайтесь использовать встроенные форматы. Это сделает ваше приложение более гибким.
Источник: http://sharp-net.ru/blog/system-string-format/
Форматирование строк в языке c#
До сих пор для кода примеров этой книги нами было написано множество классов, и обычно они реализовывали метод ToString () для того, чтобы отображать содержимое экземпляров этих классов. Однако довольно часто у пользователей возникает потребность отобразить содержимое переменных другим способом — в зависимости от национальных и культурных стандартов. Класс .NET System. DateTime представляет наиболее очевидный пример этого. Например, может понадобиться отобразить одну и ту же дату как 10 June 2007, 10 Jun 2007, 6/10/07 (США), 10/6/07 (Великобритания), или 10.06.2007 (Германия).
Аналогично, структура Vector из главы 3 реализует метод Vector. ToString () для отображения вектора в формате (4, 56, 8). Однако существует другой общепринятый способ записи векторов — в форме 4i + 5 б j + 8 k. Если вы хотите, чтобы написанные вами классы были дружественными к пользователю, они должны предлагать средства для отображения своихстроковых представлений в любом из форматов, которые могут понадобиться пользователю. Исполняющая система .NET определяет стандартный способ достижения этого — интерфейс IFormattable. Описание способа добавления этого важного свойства к пользовательским классам и структурам и представляет собой тему настоящего раздела.
Как вам известно, формат, в котором нужно отобразить значение переменной, следует указывать при вызове Console .WriteLine (). Таким образом, мы используем здесь этот метод в качестве примера, хотя большая часть обсуждения относится к любой ситуации, когда возникает потребность в форматировании строки. Например, если требуется отобразить значение переменной в окне списка или текстовом поле, то при этом для получения соответствующего строкового представления переменной обычно используется метод String.Format (). Однако действительные спецификато¬ры формата, применяемые для указания конкретного формата, идентичны тем, что передаются методу Console .WriteLine (). Поэтому мы сосредоточимся на примере Console .WriteLine (). Начнем с рассмотрения того, что происходит, когда форматная строка применяется к примитивному типу, а отсюда станет ясно, как следует включать спецификаторы формата для пользовательских классов и структур.
В главе 2 строки формата применялись в Console. Write () и Console. WriteLine () следующим образом:
double d = 13.45;
int i = 45;
Console.WriteLine("Значение double равно {0,10:E}, a int содержит {1}", d, i);
Сама форматная строка содержит большую часть отображаемого текста, но всякий раз, когда в нее должно быть вставлено значение переменной, в фигурных скобках указывается индекс. В фигурные скобки может быть включена и другая информация, относящаяся к формату данного элемента, например, как та, что описана ниже.
Количество символов, которое займет представление элемента, снабженное префиксом-запятой. Отрицательное число указывает, что элемент должен быть выровнен по левой границе, а положительное — по правой. Если элемент на самом деле занимает больше символов, чем ему отведено форматом, он отображается полностью.
Спецификатор формата предваряется двоеточием. Это указывает, каким образом необходимо отформатировать элемент. Например, можно указать, должно ли число быть форматировано как денежное значение либо его следует отобразить в научной нотации.
В табл. 8.3 перечислены часто используемые спецификаторы формата для числовых типов, которые уже кратко упоминались в главе 2.
|
Если целое число требуется дополнить нулями, можно воспользоваться спецификатором формата 0 (ноль), повторив его столько раз, сколько составляет требуемая длина. Например, спецификатор формата 0000 отобразит 3 в виде 0003, 99 — в виде 0099 и так далее.
Мы не можем привести здесь полный список, поскольку другие типы данных добавляют свои собственные спецификаторы. Целью настоящего раздела будет показать, как определять собственные спецификаторы для пользовательских классов.