Ниске (стрингови)

Поред бројева, рачунари су веома добри и у раду са текстом. Текст се састоји од слова (малих и великих), цифара, размака, интерпункцијских знакова (на пример тачака, зареза, упитника, узвичника) и слично. Све те знакове једним именом називамо карактери. Неки програмски језици подржавају само веома узак скуп карактера (од слова је могуће користити само слова енглеске абецеде), међутим, програмски језик Python3 користи широк скуп карактера који обухвата и све карактере потребне за писање на већини језика света, укључујући и слова ћириличког и латиничког писма која се користе у српском језику.

Поменути основни скуп карактера довољан само за запис текста на енглеском језику назива се ASCII, док се овај шири скуп карактера назива Unicode.

Низ карактера чини ниску или стринг (од енглеске речи string која значи ниска). Ниске се у програму записују између наводника. На пример, ниске су "Zdravo" или "Programski jezik Python.". Уместо двоструких равноправно се могу користити и једноструки наводници (на пример, 'Zdravo'), међутим, да бисмо вас мање збуњивали ми ћемо увек користити двоструке наводнике.

Ако текст садржи знаке наводника или неке друге специјалне карактере потребно је те карактере обележити косим цртама. На пример, "Rekao je: \"Zdravo, svima\". Ове косе црте се не исписују приликом извршавања програма и штампања ниски.

Надовезивање ниски

Слично као и над бројевима и над нискама се могу вршити одређене операције. Једна од основних операција је спајање две ниске. Ова операција донекле подсећа на сабирање и обележава се знаком +. На пример, вредност израза "abraka" + "dabra" је "abrakadabra". Још једна интересантна операција је да се ниска помножи природним бројем. Слично као што код бројева множење представља узастопно сабирање, исти је случај и овде и може се наслутити да множење ниске бројем заправо представља њено понављање одређени број пута. На пример, вредност израза "ba"*2 је "baba".

    Који од наредних израза крију у себи исправно записан назив воћа?
  • (A) "ba" + "na" * 2
  • Тачно! "banana"
  • (B) "a" + "na" * 2 + "s"
  • Тачно! "ananas"
  • (C) "ba" * 2 + "na"
  • Нетачно! "babana"
  • (D) "an" * 2 + "nas"
  • Нетачно! "anannas"

Допуни наредни програм тако да исправно испише име и презиме (у овом примеру треба да се испише Петар Петровић).

Учитавање ниски

Ниске могу бити задате у програму између наводника, могуће их је добити од других ниски (као што смо ime_i_prezime израчунали на основу ниске ime и ниске prezime), а могуће их је и учитати тј. захтевати од корисника вашег програма да их унесе. За то можемо употребити функцију input. На пример, наредни програм пита корисника како се зове, а онда га поздрави.

Дужина ниске, издвајање делова ниске

Дужину ниске тј. број њених карактера можемо добити помоћу функције len. Тако је len("Zdravo") једнако 6, јер ниска "Zdravo" има тачно 6 карактера.

Вредност len("Popokatepetl") је Изброј карактере у речи

Вредност len("Супер Марио 3!") је Изброј карктере у речи рачунајући посебно и празнине и интерпункцијске знаке

Карактери у ниски имају своје редне бројеве тј. позиције. Први карактер се налази на позицији 0, други на позицији 1 и тако даље. На пример, карактери у ниски "Zdravo svima!" се броје на следећи начин.

0 1 2 3 4 5 6 7 8 9 10 11 12
Z d r a v o   s v i m a !

Могуће је издвојити појединачни карактер из ниске. На пример, ако је ime = "Zorana" тада се карактер Z може добити изразом ime[0], а карактер r изразом ime[2].

Подржани су и негативни индекси тако што -1 означава последњи карактер, -2 претпоследњи и тако даље.

-13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1
Z d r a v o   s v i m a !

На пример, ако је ime = "Zorana" тада је ime[-1] карактер a док је ime[-3] карактер r.

Још једна операција која је често корисна је издвајање дела ниске. Приликом издвајања може се навести распон позиција, при чему се издвајају карактери из тог распона рачунајући прву, а не рачунајући другу наведену позицију. На пример, ime[2:5] издваја карактере имена на позицијама 2, 3 и 4 (распон [2:5] је полуотворен тј. позиција 2 је урачуната, а позиција 5 није). Ако је ime = "Predrag" тада је ime[2:5] једнако "edr". Ако се горња граница не наведе, тада се издваја део ниске до њеног краја. Тако је ime[3:] једнако "drag".

Дата је ниска s = "Programiranje je mnogo zabavno". Вредност израза s[0:4] је Карактер са последње наведене позиције се не узима Издвајају се карактери на позицијама 0, 1, 2 и 3 Израз којим је из ниске s могуће издвојити реч mnogo је Пажљиво преброј позиције. Можеш да користиш било позитивне индексе (слева на десно), било негативне индексе (сдесна на лево).

Претрага ниске

Често је потребно да проверимо да ли једна ниска садржи неки карактер или садржи неку другу ниску. То можемо урадити коришћењем find. На пример, ако је ime_i_prezime = "Љубица Љубичић" тада је вредност ime_i_prezime.find(" ") једнака 7, јер се размак може наћи на позицији 7. Ако потражимо карактер којег ниска не садржи (на пример, ime_i_prezime.find(",")), добићемо вредност -1. Уместо find можемо употребити и index, међутим, када се оно што се тражи не налази у ниски, find враћа вредност -1, док index даје грешку при извршавању програма.

Ово можемо употребити да бисмо, на пример, издвојили име и презиме из датог имена и презимена (што је управо супротно од задатка у којем смо на основу посебног имена и презимена и добили спојено име и презиме).

Овај задатак има и лепше решење које користи функцију split о којој ће више речи бити у поглављу о листама.

Осим што можемо пронаћи позицију на којој се неко слово или нека подниска јавља унутар ниске, можемо и избројати колико се пута оно појављује. За то можемо користити count. На пример, број појављивања слова a у неком имену можемо израчунати помоћу ime.count("a").

А шта је са цифрама у ниски?

Ниске у себи могу да садрже цифре, па чак могу да буду састављене искључиво од цифара. Међутим, када се на две ниске примени оператор + ниске се надовезују. Тако је резултат операције "12" + "34" једнак "1234", а не 46 како би неки очекивали. Помоћу input уноси се увек текст тј. резултат ове операције је увек ниска, чак иако тај текст садржи само цифре. Имајући ово у виду покушај да предвидиш шта ће израчунати наредни програм, када након његовог покретања корисник унесе 3, а затим и 5.

    Који је резултат извршавања претходног програма ако корисник унесе прво 3, а затим 5.
  • (A) 8
  • Нетачно! Иако корисник куца цифре, prvi_sabirak и drugi_sabirak нису бројеви него ниске (текст) и зато се оператором + оне надовезују.
  • (B) 15
  • Нетачно! Покушај поново.
  • (C) "35"
  • Тачно!
  • (D) "8"
  • Нетачно! Иако корисник куца цифре, prvi_sabirak и drugi_sabirak нису бројеви него ниске (текст) и зато се оператором + оне надовезују.

Ако текст садржи само цифре, онда се број представљен тим цифрама може добити помоћу int. На пример, int("123") је број 123. Тако је int("12") + int("34") једнако 12 + 34 тј. 46. Стога се учитавање броја може постићи помоћу int(input("Unesi broj: ")). Тако се претходни програм који сабира два учитана броја може поправити на следећи начин:

Ниска може да садржи и децимални запис неког броја и тада се број представљен том ниском може добити помоћу float. На пример, float("123.45") je број 123.45. Претварање ниске у број је и у овом случају веома важно урадити, јер се у супротном оператор + односи на надовезивање ниски, а не на сабирање бројева. Провери да ли ово добро разумеш.

    Покушај поново
  • float("3.5") + float("3.5")
  • 7.0
  • "3.5" + "0.5"
  • "3.50.5"
  • 3.5 + "3.5"
  • greška
  • float("2.5") + 1.5
  • 4.0

Тако се децимални број може унети са broj = float(input("Unesi decimalan broj:")).

Задаци са нискама

Решимо сада неколико једноставних задатака примењујући ово што смо до сада научили.

Нинџа-корњача

Нинџа-корњача се креће кроз лавиринт тако што слуша упутства на тајном језику. Горе се на том језику каже rif, доле el, лево oma, а десно lun. Напиши програм који помаже корњачи да пронађе излаз из лавиринта.

_images/string_kornjaca_lavirint.png

ЈМБГ

Сваки грађанин Републике Србије има свој јединствени матични број (ЈМБГ). У њему прве две цифре одређују дан рођења, друге две месец, а наредне три цифре одређују годину рођења. Наредне две цифре одређују општину рођења, наредне три цифре су јединствене за ту особу при чему се из њих може одредити пол (комбинације од 000 до 499 се додељују дечацима, а од 500 до 999 девојчицама). Последња цифра је контролна. Она се израчунава применом једне посебне формуле на претходне цифре. За дати ЈМБГ одредите ког дана и месеца се особа родила.

Иако делује да је ЈМБГ број, њега је боље посматрати као ниску карактера тј. стринг. Наиме, обично смо заинтересовани само за издвајање одређених делова ЈМБГ, док на ЈМБГ никада не примењујемо аритметичке операције (нпр. нема смисла сабирати два ЈМБГ нити ЈМБГ множити са 2). Издвајање делова је веома једноставно ако ЈМБГ представимо у облику ниске.

Шифра

Лидијина шифра за gmail се састоји од 6 слова. Одлучила је да је закомпликује, али на правилан начин, тако да касније може да је се сети. Шифру ће закомпликовати тако што ће заменити редослед прва два и последња два слова, а средња два слова поновити два пута. На пример, ако јој је шифра била lidija закомпликована шифра јој је jadidili. Напиши програм који исписује закомпликовану шифру.

Врсте реченица

Дат је текст (ниска) који садржи неколико једноставних реченица. Одреди колико међу њима има обавештајних, колико има упитних и колико има узвичних реченица.

Обавештајне реченице се завршавају тачком, упитне знаком питања, а узвичне узвичником. Број реченица сваке врсте можемо одредити тако што пребројимо колико се пута јавља сваки од ова три карактера (карактер тачка ., карактер упитник ? и карактер узвичник !).

Робот у лавиринту

Робот се у просторији креће на основу задатог упутства. Упутство је низ команди Горе, Доле, Лево и Десно (на пример, uputstvo = "Горе Лево Лево Десно Лево Доле Горе Доле Горе Десно Горе"). У сваком кораку он се помера за једно поље. Поља квадратног облика су поређана као поља на шаховској табли и свако поље има свој број врсте и колоне. Централно поље у просторији је обележено са (0, 0), и од њега бројеви врста и колона расту на доле и на десно, а опадају на горе и на лево (као што је приказано на слици). Одреди на ком пољу ће се налазити робот након извшавања команди.

_images/grid_coordinates.png

Задатак можемо најлакше решити тако што одредимо колико пута се робот померио у сваком од четири смера. Број врсте у којој се налази на крају ће бити разлика између броја корака које је направио на доле и броја корака које је направио на горе, док ће број колоне бити разлика између броја корака које је направио на десно и броја корака које је направио на лево.

Исправе означене редове у наредном програму. Робот на крају завршава на пољу (-2, -1).

Број станова по спрату

У једној згради на сваком спрату има исти број станова, осим у приземљу, где је остављен већи простор за ходник, па су станови мањи и има их мање него на осталим спратовима. Напиши програм који од корисника тражи да унесе укупан број станова у згради и број станова по спрату и исписује колико има станова у приземљу и колики је број спратова (не рачунајући приземље).

Ако имамо \(n\) спратова (не рачунајући приземље) и на сваком спрату \(s\) станова, а у приземљу \(p\) станова, тада је укупан број станова \(u\) једнак \(n \cdot s + p\), при чему знамо да је \(0 \leq p < s\). Отуда следи да је \(n\) целобројни количник укупног броја станова и броја станова по спрату, а да је \(p\) остатак при том дељењу. Теби остаје да исправиш програм тако да од корисника тражи да унесе улазне податке и да на крају кориснику пријавиш одговарајуће резултате - потруди се да током уноса података и уз резултате испишеш и пропратни текст да би кориснику било што јасније шта твој програм ради.

Учитавање разломка

Корисник уноси текст који описује разломак (на пример, 3/4). Израчунај децималну вредност тог разломка.