1629295403-b876e2087bddebea4bc9666fb2377a02 (846199), страница 24
Текст из файла (страница 24)
В данном случае программа это делает для массива, состоящего из пяти элементов типа d o u b l e . Программа выполняет n u m E l e m e n t s итераций цикла, считывая вводимые пользователем значения и заполняя ими массив.После того как пользователь введет указанное им ранее число данных, программа использует тот же алгоритм, что и в программе F i x e d A r r a y A v e r a g e для вычислениясреднего значения последовательности чисел.В последней части генерируется вывод среднего значения вместе с введенными числами в привлекательном виде (по крайней мере с моей точки зрения).Этот вывод не так уж и прост, как может показаться.
Внимательно проследите,как именно программа выводит открывающую скобку, знаки сложения, числапоследовательности и закрывающую скобку.Программа V a r i a b l e A r r a y A v e r a g e , возможно, не удовлетворяет вашим представлениям о гибкости. Может статься, что вам бы хотелось позволить пользователю вводить числа, а после ввода какого-то очередного числа дать команду вычислить среднее значение введенных чисел. Кроме массивов, С# предоставляет программисту и другие типы коллекций; некоторые из них могут при необходимостиувеличивать или уменьшать свой размер.
В главе 15, "Обобщенное программирование", вы познакомитесь с такими альтернативами массивам.Свойство LengthВ программе V a r i a b l e A r r a y A v e r a g e для заполнения массива использованцикл f o r :Глава 6.Объединение данных - классы и массивы129//Объявляемdoublet]//массивdArrayНакапливаемfor(inti==необходимогоnewзначения0;i<размераdouble[numElements];вмассивеnumElements;i++){// Приглашение пользователю для ввода чиселC o n s o l e . W r i t e ( " В в е д и т е ч и с л о типа d o u b l e №"+(i + 1) + " : »,),,;s t r i n g sVal = C o n s o l e .
R e a d L i n e О ;double dValue=Convert.ToDouble(sVal);//ВносимчислоdArray[i]=вмассивdValue;}Массив d A r r a y о б ъ я в л е н к а к и м е ю щ и й д л и н у n u m E l e m e n t s . Таким о б р а з о м , пон я т н о , п о ч е м у ц и к л в ы п о л н я е т и м е н н о n u m E l e m e n t s и т е р а ц и й д л я п р о х о д а п о массиву.Вообще г о в о р я , не с л и ш к о м - т о и у д о б н о т а с к а т ь п о в с ю д у в м е с т е с м а с с и в о м пер(м е н н у ю , в к о т о р о й х р а н и т с я е г о д л и н а . Но, к с ч а с т ь ю , э т о н е я в л я е т с я н е и з б е ж н ы м иу м а с с и в а е с т ь с в о й с т в о L e n g t h , к о т о р о е с о д е р ж и т е г о д л и н у , т а к ч т о d A r r a y .
Lengtklв данном случае содержит то же значение, что и n u m E l e m e n t s .Таким о б р а з о м , п р е д п о ч т и т е л ь н е е и с п о л ь з о в а т ь т а к о й в и д ц и к л а f o r ://Накапливаемfor(inti=0;значенияi<вмассивеdArray.Length;i++)О т л и ч и е массивов фиксированной и переменной д л и н ыС п е р в о г о в з г л я д а б р о с а е т с я в г л а з а , н а с к о л ь к о о т л и ч а е т с я с и н т а к с и с м а с с и в о в фик|сированной и переменной длины:double[]doublet]dFixedLengthArray ={5,2,7,3.5,6.5,8,1,9,1,3};d V a r i a b l e L e n g t h A r r a y = new d o u b l e [ 1 0 ] ;Однако C# п ы т а е т с я с э к о н о м и т ь в а ш и у с и л и я , а п о т о м у п о з в о л я е т И с п о л ь з о в а т ь ита|кой код для выделения памяти для массива с его одновременной инициализацией:doublet]dFixedLengthArray =new d o u b l e [ 1 0 ]{5,2,7,3.5,6.5,8,1,9,1,3 } ;Здесь п а м я т ь в ы д е л я е т с я к а к д л я м а с с и в а п е р е м е н н о й д л и н ы , н о е г о инициализацвыполняется так же, как и для массива фиксированной длины.П р о г р а м м и с т а м о ч е н ь ч а с т о п р и х о д и т с я р а б о т а т ь с н а б о р а м и п о л ь з о в а т е л ь с к и х объе к т о в ( к л а с с о в ) .
С к а ж е м , п р о г р а м м е д л я у н и в е р с и т е т а т р е б у е т с я н е к а я с т р у к т у р а , описы-]вающая студентов, например, такая:publicclassStudent{publicpublicstringdoublesName;dGPA;//Среднийбалл}130Часть III. Объектно-основанное программированиеЭтот простейший класс содержит только имя студента и его успеваемость. В следующемфрагменте объявляется массив из n u m ссылок на объекты типа S t u d e n t :Student []students=newStudent[num];Выражение n e w S t u d e n t [ n u m ]объявляет н е массив объектов S t u d e n t ,а массив ссылок на объекты S t u d e n t .Итак, каждый элемент s t u d e n t s [ i ] представляет собой ссылку на нулевой объект,так как С# инициализирует новые, неопределенные объекты значением n u l l .
Можносформулировать это и иначе, сказав, что ни один из элементов s t u d e n t s [ i ] после выполнения рассматриваемого оператора n e w не ссылается на объект типа S t u d e n t . Такчто сначала вы должны заполнить массив следующим образом:for(inti=0;i<students. Length;=newi + +){students[i]Student();}Теперь в программе можно вводить свойства отдельных студентов таким образом:students [ i ]=newstudents [ i ] . sNamestudents [ i ] . dGPAStudent ();=="My N a m e " ;dMyGPA;Все это можно увидеть в программе A v e r a g e S t u d e n t G P A , которая получает информацию о студентах и вычисляет их среднюю успеваемость.// A v e r a g e S t u d e n t G P A// Вычисляет среднююusing S y s t e m ;namespaceуспеваемостьAverageStudentGPAмножествастудентов..fpublicclassStudent{publicpublicstringsName;d o u b l e dGPA;//Среднийбалл}public{classpublicPrograms t a t i cvoidMain(string[]args){// Определяем количество студентовConsole.WriteLine("Введитеколичествостудентов");string s = Console.ReadLine();int nNumberOfStudents = Convert.ToInt32(s);// Выделяем массив объектов S t u d e n tStudent[]students// Заполняем массивf o r ( i n t i = 0; i <=newStudent[nNumberOfStudents];students.Length;Глава 6.
Объединение данных - классы и массивыi++)131{//////CoПриглашение для ввода информации. Единицаприбавляется в связи с тем,что индексациям а с с и в о в в С# н а ч и н а е т с я с н у л яn s o l e . W r i t e ( " В в е д и т е имястудента"+ ( i + 1) + " : ") ;s t r i n g sName = C o n s o l e . R e a d L i n e О ;Console.Write("Введитесредний балл студента:s t r i n g sAvg = C o n s o l e . R e a d L i n e О ;d o u b l e dGPA = C o n v e r t . T o D o u b l e ( s A v g ) ;// Создаем объектStudent thisStudenthisStudent.sNamethisStudent.dGPA//Добавляемstudents[i]на основе введеннойt = new S t u d e n t ( ) ;= sName;= dGPA;созданный=объектв" ) ;информациимассивthisStudent;}//Усредняем успеваемостьd o u b l e dSum = 0 .
0 ;for(inti=0;i<студентовstudents.Length;i++){dSum+=students[i].dGPA;}doubledAvg=dSum/students.Length;// Выводим в ы ч и с л е н н о еConsole.WriteLine();значениеC o n s o l e . W r i t e L i n e ( " С р е д н я я у с п е в а е м о с т ь по"+students.Length+ " студентам - " + dAvg);//ОжидаемподтвержденияпользователяConsole.WriteLine("Нажмите <Enter> для " +"завершения программы...");Console.Read();}}}П р о г р а м м а п р е д л а г а е т п о л ь з о в а т е л ю в в е с т и к о л и ч е с т в о р а с с м а т р и в а е м ы х студенп о с л е ч е г о с о з д а е т м а с с и в с о о т в е т с т в у ю щ е г о р а з м е р а , э л е м е н т а м и к о т о р о г о являюссылки н а объекты типа S t u d e n t .П о с л е э т о г о п р о г р а м м а в х о д и т в ц и к л f o r , в к о т о р о м п р о и с х о д и т з а п о л н е н и е массва. П о л ь з о в а т е л ю п р е д л а г а е т с я в в е с т и и м я к а ж д о г о с т у д е н т а и е г о с р е д н и й б а л л —данные используются для создания объекта S t u d e n t .П о с л е з а п о л н е н и я м а с с и в а п р о г р а м м а в х о д и т в о в т о р о й ц и к л , в к о т о р о м усредняй]с я у с п е в а е м о с т ь с т у д е н т о в , а п о с л е в ы ч и с л е н и й п о л у ч е н н ы й с р е д н и й б а л л выводите]на экран.132Часть III.
Объектно-основанное программированаВот как выглядит типичный результат работы программы:Введитеколичествостудентов3ВведитеВведитеВведитеВведитеВведитеВведитеимя с т у д е н т асредний баллимястудентасредний баллимя с т у д е н т асредний баллСредняяуспеваемостьНажмите<Enter>для1:Randyстудента:2:Jeffстудента:3:Carrieстудента:по33.03.54.0студентамзавершения-3.5программы...Имя ссылочной переменной лучше делать состоящим из одного слова, как, например, s t u d e n t . В имя переменной желательно каким-то образом включитьимя класса, как, например, b a d S t u d e n t , g o o d S t u d e n t и т.п.
Имя массива(или другой коллекции) предпочтительнее делать простым и очевидным, такимкак s t u d e n t s , p h o n e N u m b e r sили p h o n e N u m b e r s I n M y P a l m P i l o t . Какобычно, этот совет всего лишь отражает личное мнение а в т о р а — С# совершенно безразлично, какие именно имена вы будете давать вашим переменным.Рассмотрим е щ е р а з , к а к и м е н н о в ы ч и с л я е т с я с р е д н я я у с п е в а е м о с т ь с т у д е н т о в :publicclassStudent{publicpublicstringdoublesName;dGPA;//Среднийбалл)publicclassProgram(publics t a t i cvoidMain(string[]args){// ...Создаем массив...// Усредняем успеваемостьd o u b l e dSum = 0 . 0 ;for(inti=0;i<students.Length;i++){dSum+=students[i].dGPA;}}d o u b l e dAvg = dSum / s t u d e n t s .
L e n g t h ;// . . . Прочие д е й с т в и я с массивом . . .Цикл f o r проходит по всем элементам массива.Переменная s t u d e n t s . L e n g t h содержит количество элементов в массиве.Глава 6.Объединение данных - классы и массивы133С# предоставляет программистам особую конструкцию f o r e a c h , которая спроектирована специально для итеративного прохода по контейнерам, таким как массивы. Ошработает следующим образом:// Усредняем успеваемостьd o u b l e dSum = 0 . 0 ;foreach(Studentstudinstudents){dSum +=stud.dGPA;}d o u b l e dAvg = dSum / s t u d e n t s . L e n g t h ;При первом входе в цикл из массива выбирается первый объект типа S t u d e n t и сохраняется в переменной s t u d .
При каждой последующей итерации цикл f o r e a c h выбирает из цикла и присваивает переменной s t u d очередной элемент массива. Управление покидает цикл f o r e a c h , когда все элементы массива оказываются обработанными.Обратите внимание, что в выражении f o r e a c h нет никаких индексов. Это позволяетсущественно снизить вероятность появления ошибки в программе.Программистам на С, С++ или J a v a цикл f o r e a c h покажется на первый взгляднеудобным, однако этот уникальный оператор С# (точнее, .NET) — простейший способ организации циклической обработки всех элементов массива.На самом деле цикл f o r e a c h мощнее, чем можно представить из приведенногопримера.