CSBasicCourse2ndedPodbelsky / CSBasicCourse2ndedPodbelsky
.pdfСтрока форматирования "строка форматирования" включает неизменяемые символы и конструкции, называемые полями подстановок. Структура поля подстановки "поля подстановок" : {N[,W][:S[R]]}, где N – номер аргумента; W -
ширина поля; S - спецификатор формата; R – спецификатор точности.
Квадратные скобки в поля подстановки не входят и обозначают необязательность ограниченного ими фрагмента (элемента) поля. В поле подстановки разрешено опускать все элементы кроме фигурных скобок и номера аргумента. Именно поэтому все остальные элементы поля подстановки мы ограничили квадратными скобками. Воспользуемся этим правилом, чтобы привести
первый пример.
int num = 23, den = 6;
string result, // ссылка на строку, с результатом
form = "Числитель: {0}, знаменатель: {1}, дробь: {0}/{1}=={2}"; result = string.Format(form, num, den, num / den); Console.WriteLine(result);
В примере определены две ссылки |
result и form на объекты типа |
string. |
Значение строки, связанной со ссылкой |
form, определено инициализирующей |
строковой константой. В ней пять полей подстановок. Номера в полях указывают,
символьные представления значений каких (по счету, начиная с 0) аргументов будут подставлены вместо соответствующих полей. В обращении к методу Format()
первый аргумент – строка form, затем num – аргумент, с номером 0, den – аргумент,
которому соответствует номер 1, num/den – выражение, значение которого воспринимается как аргумент с номером 2. В результате выполнения подстановок метод Format() возвращает строку, ссылка на которую присвоена переменной result.
Выводя эту строку на консоль, получим:
Числитель: 23, знаменатель: 6, дробь: 23/6==3
(Обратите внимание на округление результата целочисленного деления.)
В приведённом примере поля подстановок "поля подстановок" содержали только номера аргументов. Разберём назначение других элементов, которые в поле
подстановки необязательны. Запятая и следующее за ним число (W - ширина поля)
в поле подстановки определяет количество позиций, выделяемых для изображения подставляемого значения. Если эти элементы (запятая и число) опущены, то число позиций определяется изображением выводимого значения, то есть ширина поля выбирается минимально достаточной для изображения значения. Если ширина поля указана, и она превышает длину помещаемого в поле значения, то при положительной длине поля W значение выравнивается по правой границе. Если перед шириной поля W стоит минус, то выравнивание выполняется по левой границе поля.
Спецификатор формата S задаёт вид изображаемого значения. Для разных типов данных этот спецификатор выбирается по-разному. Следующая за ним цифра
– спецификатор точности R – влияет на формируемое значение, и это влияние зависит от спецификатора формата.
Спецификаторы формата S и точности R |
Таблица 8.1. |
|
Спецификатор S |
Название формата |
Роль спецификатора |
С или с |
Валютный |
точности R |
Количество десятичных |
||
D или d |
Целочисленный |
разрядов |
Минимальное число |
||
E или e |
Экспоненциальный |
цифр |
Число разрядов после |
||
F или f |
С фиксированной точкой |
точки |
Число разрядов после |
||
N или n |
Число с разделителем |
точки |
Число знаков после |
||
P или p |
триад |
точки |
Значение в процентах |
Число знаков после |
|
G или g |
(%) |
|
|
Короткий из E или F |
точки |
X или x |
Шестнадцатеричный |
Подобен E или F |
Минимальное число |
||
|
|
цифр |
Пример :
double dou = 1234.567;
string form = "Спецификация Е4: {0:E4}, спецификация F4: {0:F4}"; string result = string.Format(form, dou);
Console.WriteLine(result);
В обоих полях подстановки строки форматирования опущена ширина поля, и
предполагается дважды использовать только один аргумент (с номером 0).
Выводимая строка:
Спецификация Е4: 1,2346E+003, спецификация F4: 1234,5670
Обратите внимание на округление при выводе по формату Е4 и на дополнительный нуль в изображении числа с фиксированной точкой при выводе по формату F4. Это определяется спецификатором точности, равным 4.
Пример с целочисленным значением, выводимым с разными основаниями в
поля из 4-х позиций. Обратите внимание, что ширина первого поля отрицательна: int num = 23;
string form = "Основание 10: {0,-4:D}\n основание 16: {0,4:X}"; Console.WriteLine(form, num);
Результат в консольном окне:
Основание 10: 23 основание 16: 17
В этом примере форматирование выполняется непосредственно при обращении к методу WriteLine(). Первый аргумент выступает в роли форматной строки, а вызов метода string.Format() осуществляется неявно.
Если в этом примере в полях подставки указать спецификаторы точности, то в
изображениях целых чисел могут появиться незначащие нули. Пример: int num = 23;
string form = "Основание 10: {0,-4:D3}\n основание 16: {0,4:X3}";
Console.WriteLine(form, num);
Результат:
Основание 10: 023 основание 16: 017
Примечание: если в поле подстановки указана ширина, недостаточная для представления выводимого значения, то ширина поля будет автоматически увеличена до необходимого количества позиций.
8.6. Строка как контейнер
Как мы уже знаем, оператор foreach "оператор: foreach" предназначен для последовательного перебора всех элементов некоторого контейнера. Если в качестве контейнера выступает массив, например, с элементами типа long, то для просмотра значений всех его элементов можно использовать цикл с заголовком
foreach (long cell in массив)
В этом цикле итерационная переменная cell имеет тот же тип, что и элементы массива и последовательно принимает значения его элементов.
Если нужно применить такой же цикл для перебора элементов объекта типа string, то используется итерационная переменная типа char. В качестве контейнера выступает строковый литерал, либо объект класса string (либо ссылка на такой объект). Пример со строковым литералом:
foreach (char numb in "0123") Console.Write("\t"+numb+"->"+(int)numb);
Результат:
0–>48 1->49 2->50 3->51
8.7. Применение строк в переключателях
Мы уже упоминали, что объекты класса string (и ссылки на них) могут
использоваться в метках переключателя "метка:метка переключателя" и служить значением переключающего выражения. Для иллюстрации этих возможностей рассмотрим схему решения такой задачи: "Ввести фамилию человека (например,
служащего компании) и вывести имеющиеся сведения о нём". Характер этих сведений и конкретные сведения нам не важны – покажем общую схему решения
подобных задач с использованием переключателя и строк.
Console.Write("Введите фамилию:"); string name= Console.ReadLine(); swich(name) {
case "Сергеев": Console.WriteLine("Фрол Петрович");
...Вывод данных о Сергееве ...
break;
case "Туров":
...Вывод данных о Турове ...
break;
. . . .
default: Console.Write ("Нет сведений");
}
8.8. Массивы строк
Как любые объекты, строки можно объединять в массивы. Хотя внимательный читатель заметит, что в массив помещаются не строки, а только ссылки на них, но при использовании массивов ссылок на строки "массив:массив ссылок на строки" не требуются никакие специальные операции для организации обращения к собственно строкам через ссылки на них. Поэтому в литературе,
посвящённой языку C#, зачастую говорят просто о массивах строк. В следующей программе создаётся массив ссылок на строки, по умолчанию инициализированный пустыми строками. Затем в цикле элементам массива (ссылкам) присваиваются значения ссылок на объекты-строки разной длины. Далее к массиву применяется оператор перебора контейнеров foreach, и строки выводятся на консоль.
// 08_01.cs - массивы строк...
using System;
class Program { static void Main() {
string [] stAr = new string[4]; for (int i = 0; i<star.Length; i++)
stAr[i] = new string('*', i + 1); foreach (string rs in stAr)
Console.Write("\t" + rs);
}
}
Результат выполнения программы:
* ** *** ****
В программе создан массив из четырёх пустых строк. Он представлен ссылкой stAr. Обратите внимание, что для создания объектов, адресуемых элементами
массива, применяется конструктор "конструктор" с прототипом string (char, int);
Этот конструктор создаёт строку в виде последовательности одинаковых символов,
количество которых определяет второй параметр. (Первый параметр позволяет задать повторяемый символ.) Итерационная переменная цикла foreach имеет тип string, так как просматриваемым контейнером служит массив типа string[ ].
Для иллюстрации применения методов Split() "метод: Split()" , Join() "метод:
Join()" , рассмотрим следующую задачу. Пусть значением строки является предложение, слова которого разделены пробелами. Требуется заменить каждый пробел последовательностью символов "-:-". Следующая программа решает
сформулированную задачу.
// 08_02.cs – декомпозиция "декомпозиция строк" и объединение строк. using System;
class Program
{
static void Main()
{
string sent = "De gustibus non est disputandum"; // о вкусах не спорят
string[] words; //ссылка на массив строк words = sent.Split(' ');
Console.WriteLine("words.Length = " + words.Length); foreach (string st in words)
Console.Write("{0}\t", st); sent = string.Join("-:-", words); Console.WriteLine("\n" + sent);
}
}
Результат выполнения программы: words.Length = 5
De gustibus non est disputandum De-:-gustibus-:-non-:-est-:-disputandum
В строке, связанной со ссылкой sent, помещены слова, разделённые пробелами.
Определена ссылка words на массив строк (объектов класса |
string). Обращение |
sent.Split(' ') "разбивает" строку, адресованную ссылкой sent, на фрагменты.
Признак разбиения – символ пробел ' ', использованный в качестве аргумента. Из
выделенных фрагментов формируется массив (объект класса string[ ]), и ссылка на него присваивается переменной words.
Выражение w o r d s . L e n g t h равно длине (количеству элементов)
сформированного массива. Напомним, что Length – свойство класса массивов string[ ], унаследованное от базового класса Array.
Оператор foreach перебирает элементы массива words, и итерационная переменная st последовательно принимает значения каждого из них. (Напомним, что особенность итерационной переменной состоит в том, что она позволяет только получать, но не позволяет изменять значения перебираемых элементов.) В теле цикла foreach один оператор – обращение к статическому методу Write() класса
Console. Его выполнение обеспечивает вывод значений элементов массива (строк).
Эскейп-последовательность '\t' в поле подстановки разделяет табуляцией выводимые слова.
Статический метод Join() предназначен для выполнения действий в некотором смысле обратных действиям метода Split(). Обращение string.Join("-:-", words)
объединяет (конкатенирует) строки массива, представленного ссылкой words, то есть соединяет в одну строку слова исходного предложения. Между словами вставляется строка, использованная в качестве первого аргумента метода Join(). Тем самым каждый пробел между словами исходной строки заменяется строкой "-:-".
8.8. Сравнение строк
Для объектов класса string определены только две операции сравнения
"сравнение строк" == и !=. Если необходимо сравнивать строки по их упорядоченности, например, в лексикографическом порядке, то этих двух операций недостаточно. Кроме уже упомянутого нестатического метода CompareTo() в классе string есть статический метод (точнее набор перегруженных методов) с именем
Compare, позволяющий сравнивать строки или их фрагменты. Так как сравнение и сортировка строк очень важны в задачах обработки текстовой информации, то
рассмотрим два варианта метода Compare() "метод: Compare()" .
Наиболее простой метод имеет следующий заголовок: int static Compare (string, string)
Сравнивая две строки, использованные в качестве аргументов, метод возвращает значение 0, если строки равны. Если первая строка лексикографически меньше второй – возвращается отрицательное значение. В противном случае возвращаемое значение положительно.
В следующем фрагменте программы определён массив ссылок на строки, из него выбирается и присваивается переменной res ссылка на лексикографически
наибольшую строку (08_03.cs):
string[] eng = {"one", "two", "three", "four"}; string res = eng[0];
foreach (string num in eng)
if (string.Compare(res, num) < 0) res = num;
Значением строки, связанной со ссылкой-переменной res, будет "two".
Проиллюстрированная форма метода C o m p a r e ( ) оценивает лексикографическую упорядоченность, соответствующую английскому алфавиту.
Следующий вариант этого метода позволяет использовать разные алфавиты.
int static Compare (string, string, Boolean,CultureInfo)
Первые два параметра – сравниваемые строки. Третий параметр указывает на необходимость учитывать регистр символов строк. Если он равен true, то регистры не учитываются и строки "New" и "nEw" будут считаться равными. Четвёртый параметр – объект класса System.Globalization.CultureInfo – позволяет указать алфавит, который необходимо использовать при лексикографическом сравнении строк. Для построения объекта, который может быть использован в качестве аргумента, заменяющего четвёртый параметр, используют конструктор класса
CultureInfo(string). Аргумент конструктора – строка, содержащая условное обозначение нужного алфавита. Точнее сказать, обозначается не алфавит, а
культура (Culture), которой принадлежит соответствующий язык. Для обозначения национальных культур, приняты имена и коды, таблицу которых можно найти в литературе и документации, (см. например, [13], Приложение 2). Мы в наших примерах будем использовать два алфавита: английский (имя культуры "en", код культуры 0х0009) и русский ("ru" и 0х0019).
В следующем фрагменте программы(08_03.cs), который построен по той же схеме, что и предыдущий, определён массив ссылок на строки с русскими названиями представителей семейства тетеревиных из отряда куриных. Из массива выбирается ссылки на лексикографически наименьшую строку, т.е. расположенную
после упорядочения по алфавиту в начале списка.
string[ ] hens = {"Куропатка белая", "Куропатка тундровая", "Тетерев", "Глухарь", "Рябчик" };
string res = hens[0]; foreach (string hen in hens)
if (string.Compare(res, hen, true,
new System.Globalization.CultureInfo("ru")) > 0) res = hen;
Console.WriteLine(res);
Результат, выводимый на консоль:
Глухарь
Обратите внимание, что четвёртый параметр метода Compare() заменён в вызове безымянным объектом класса CultureInfo, сформированным конструктором класса в выражении с операцией new. Аргумент конструктора – литерная строка
"ru" – обозначение нужного алфавита (в данном примере – русского языка). Если возвращаемый результат, больше нуля, то есть первая строка, именуемая ссылкой res, лексикографически больше второй, то вторая строка, связанная со ссылкой hen,
принимается в качестве претендента на наименьшее значение.
8.9. Преобразования с участием строкового типа
Рассматривая арифметические типы, мы привели правила неявных
преобразований и операцию явного приведения типов:
(тип) первичное_выражение
К строковому типу неявные преобразования не применимы, и невозможно
использование операции явного приведения типов.
Как уже отмечалось, для всех типов существует метод ToString() "метод:
ToString()" , унаследованный всеми классами от единого базового класса object.
Таким образом, значение любого типа можно представить в виде строки, например,
так:
int n = 8, m = 3;
Console.WriteLine(m.ToString()+n.ToString() + " попугаев");
Результат вывода на консоль:
38 попугаев.
Для обратного преобразования из строки в значение другого типа можно
воспользоваться статическими методами библиотечного класса Convert,
принадлежащего пространству имён System. Ещё один путь – применение
статического метода Parse() "метод: Parse()" или метода TryParse(). Указанные
методы (их применение кратко рассмотрено в главе 5) определены в каждом классе предопределённого типа, за исключением класса object (в котором они не нужны).
Эти методы часто применяется при чтении данных из входного консольного потока.
Метод Console.ReadLine() возвращает в виде строки набранную на клавиатуре последовательность символов. "Расшифровку" этой последовательности, то есть превращение символьного представления во внутреннее представление (в код)
соответствующего значения, удобно выполнить с помощью метода Parse() или
TryParse(). Наиболее просто, но совсем небезопасно, применить метод Parse(),
например таким образом:
int res = int.Parse(Console.ReadLine());
В данном случае изображение целого числа в виде набранной на клавиатуре