1

Тема: Робота з рядками

Добрий вечір. Щось я давно не бачив лаб в нас на форумі, потрібно це виправити :)

Щож, є завдання (далі тролейбусною мовою): Людина вирішила переглянути та замовити білет на рейс. Створити програму яка при вводі місця для сидіння вказувала де знаходиться це місце: window (вікно), aisle (прохід), nether (ні прохід, ні вікно).

На схемі зображено 3 відділення літака (преміум-клас, бізнес-клас, економ-клас), де 1..65 - ряди місць, A..K - позиція місця (ви можете помітити, що між H та J відсутня буква I, але в умові сказано, що позиція місць в економ-класі позначається буквами від A..K окрім I).

Схема розташування місць в літаку:

http://screenshot.su/img/4e/c0/dc/4ec0dc8c7a4d735ad344353889ccfd28.jpg

Приклад вхідних даних та результату:
3С  aisle
24A  window
55B  neither
Код програми:
#include "stdafx.h"
#include <iostream>
#include <string>

using namespace std;

int main()
{
    string Row, Place, Number;
    string RowPlace, RowNumber;
    int CountRowTwo = 0;
    int CountRowThree = 0;
    setlocale(0, "");

    cout << "Введiть номер мiсця: " << endl;
    cin >> Row;

    CountRowTwo = Row.length();
    CountRowThree = Row.length();

    RowPlace = Row;
    RowNumber = Row;
    if (CountRowTwo == 2)
    {
        Place = RowPlace.erase(0, 1);
        Number = RowNumber.erase(1);
    }
    else
        if (CountRowThree == 3)
        {
            Place = RowPlace.erase(0, 2);
            Number = RowNumber.erase(2);
        };
    
    system("pause");
    return 0;
}

В коді я розділяю номер та місце на дві змінних.
Питання таке: якою функцією можна перевести значення типу string в int (наприклад як в Delphi, StrToInt()) для подальшої роботи з числами.

P.S. Вибачте за недолугий малюнок схеми.

2

Re: Робота з рядками

1. sprintf() + MyString.c_str()
2. stringstream
3. atoi()

Щось я давно не бачив лаб в нас на форумі, потрібно це виправити

Бракує тега сарказму :).

3 Востаннє редагувалося koala (07.12.2013 23:24:14)

Re: Робота з рядками

Найпростіший нативний C++ спосіб переводити string в int - це пхати його в stringstream і витягати звітди. Але тут можна і простіше:

    int row;
    char place;
    cin >> row >> place;

4 Востаннє редагувалося Logans (07.12.2013 23:36:15)

Re: Робота з рядками

Bartash написав:

1. sprintf() + MyString.c_str()
2. stringstream
3. atoi()

Щось я давно не бачив лаб в нас на форумі, потрібно це виправити

Бракує тега сарказму :).

Я однозначно "за" за такий тег)

Команди приведені вище використав ось так:

Прихований текст
    int IntegerPlace = 0;
    int IntegerNumber = 0;
    IntegerPlace = atoi(Place.c_str());
    IntegerNumber = atoi(Number.c_str());

    cout << IntegerNumber << " " << IntegerPlace << endl;

Але вийшло ось так:

Вивід:
3С 0
34С 0
45В 0

Тобто на букву виводить одні нулі. З цифрою все нормально.


koala написав:

Найпростіший нативний C++ спосіб переводити string в int - це пхати його в stringstream і витягати звітди. Але тут можна і простіше:

    int row;
    char place;
    cin >> row >> place;

Тобто використовувати для вказування ряду int-значення, а для вказування місця char-значення?
Звісно це логічніше, але за умовою завдання я маю зробити цю програму використовуючи лише string (а потім зробити і для char) рядки.

5 Востаннє редагувалося User 298 (07.12.2013 23:37:52)

Re: Робота з рядками

Logans написав:

зробити цю програму використовуючи лише string (а потім зробити і для char) рядки.

Складність розв'язку прямо пропорційна хитрості тарганів викладача: інноватори приймуть зі stringstream, консерватори змусять писати свій sprintf для string. :)

Тобто на букву виводить одні нулі. З цифрою все нормально.

cppreference написав:

If the converted value would be out of the range of representable values by an int, it causes undefined behavior

6

Re: Робота з рядками

Bartash написав:
Logans написав:

зробити цю програму використовуючи лише string (а потім зробити і для char) рядки.

Складність розв'язку прямо пропорційна хитрості тарганів викладача: інноватори приймуть зі stringstream, консерватори змусять писати свій sprintf для string. :)

Хотілося б вміти використовувати обидва рішення, можливо можете навести приклади використання?

7 Востаннє редагувалося User 298 (07.12.2013 23:41:20)

Re: Робота з рядками

Logans написав:

Хотілося б вміти використовувати обидва рішення, можливо можете навести приклади використання?

stringstream приклад навів koala. А самописні велосипеди, як правило, далі лаб не слід поширювати.

8

Re: Робота з рядками

Bartash написав:
Logans написав:

Хотілося б вміти використовувати обидва рішення, можливо можете навести приклади використання?

stringstream приклад навів koala. А самописні велосипеди, як правило, далі лаб не слід поширювати.

Ну, якщо подивитись з іншого боку, то мені і переводу числа буде достатньо. Дякую)

9

Re: Робота з рядками

Приклад з практики: StackOverflow.

10

Re: Робота з рядками

Logans написав:

Ну, якщо подивитись з іншого боку, то мені і переводу числа буде достатньо.

Я в одному з проектів віддав перевагу stringstream під час парсингу текстового файлу з подальшим формуванням масиву чисел.

11 Востаннє редагувалося Logans (08.12.2013 00:01:19)

Re: Робота з рядками

Кому цікаво, ось приклад повної програми.

Не знаю, чи правильно перевірку зробив, здається дещо некоректно, але іншого варіанту не придумав.

Код
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
#include <string>

using namespace std;

int main()
{
    string Row, Place, Number;
    string RowPlace, RowNumber;
    int CountRowTwo = 0;
    int CountRowThree = 0;
    setlocale(0, "");

    cout << "Введiть номер мiсця: " << endl;
    cin >> Row;

    CountRowTwo = Row.length();
    CountRowThree = Row.length();

    RowPlace = Row;
    RowNumber = Row;
    if (CountRowTwo == 2)
    {
        Place = RowPlace.erase(0, 1);
        Number = RowNumber.erase(1);
    }
    else
        if (CountRowThree == 3)
        {
            Place = RowPlace.erase(0, 2);
            Number = RowNumber.erase(2);
        };
    
    int IntegerNumber = 0;
    IntegerNumber = atoi(Number.c_str());
    if (IntegerNumber <= 2)
    {
        if ((Place == "A") || (Place == "D"))
            cout << "window" << endl;
        else
            if ((Place == "B") || (Place == "C"))
                cout << "aisle" << endl;
    }
    else
        if ((IntegerNumber >= 3) && (IntegerNumber <= 20))
        {
            if ((Place == "A") || (Place == "F"))
                cout << "window" << endl;
            else
                if ((Place == "B") || (Place == "C") ||
                    (Place == "D") || (Place == "E"))
                    cout << "aisle" << endl;
        }
        else
            if ((IntegerNumber >= 21) && (IntegerNumber <= 65))
            {
                 if ((Place == "A") || (Place == "K"))
                     cout << "window" << endl;
                 else
                     if ((Place == "C") || (Place == "D") ||
                         (Place == "G") || (Place == "H"))
                         cout << "aisle" << endl;
                     else
                         if ((Place == "B") || (Place == "E") ||
                             (Place == "F") || (Place == "J"))
                             cout << "nether" << endl;
            };


    system("pause");
    return 0;
}

Щодо параметрів які не відповідають цьому діапазону, я перевірку не робив.

Дякую за допомогу. :)

12

Re: Робота з рядками

Logans написав:

за умовою завдання я маю зробити цю програму використовуючи лише string (а потім зробити і для char) рядки.

Вам допомагати - як з шулером грати: тільки здається, що ти виграєш, аж тут виявляється, що ви це партія не в шашки, а в го. Може, варто в майбутньому все ж повністю умову викладати?

13

Re: Робота з рядками

koala написав:
Logans написав:

за умовою завдання я маю зробити цю програму використовуючи лише string (а потім зробити і для char) рядки.

Вам допомагати - як з шулером грати: тільки здається, що ти виграєш, аж тут виявляється, що ви це партія не в шашки, а в го. Може, варто в майбутньому все ж повністю умову викладати?

Вибачаюсь, просто я гадав, що написаного буде достатньо)

14

Re: Робота з рядками

Я б додав купу цікавого, що можна виправити/покращити, але, мабуть, там в умові було написано, щоб вийшов неефективний бидлокод, тому просто скопіюю його на govnokod.ru, якщо не заперечуєте.

15

Re: Робота з рядками

koala написав:

Я б додав купу цікавого, що можна виправити/покращити, але, мабуть, там в умові було написано, щоб вийшов неефективний бидлокод, тому просто скопіюю його на govnokod.ru, якщо не заперечуєте.

Якщо бажаєте щось добавити, то будь-ласка, покажіть, що саме. Умова була дана лише для того, щоб програма функціонувала, а чомусь цікавому я завжи радий навчитись, якщо звісно ви захочете це продемонструвати.

А фразу "якщо не заперечуєте", я гадаю потрібно писати перед тим, як зробити те, що комусь може не сподобатись, якщо вже скопіювали то так і буде.

16

Re: Робота з рядками

Logans написав:

Якщо бажаєте щось добавити, то будь-ласка, покажіть, що саме. Умова була дана лише для того, щоб програма функціонувала, а чомусь цікавому я завжи радий навчитись, якщо звісно ви захочете це продемонструвати.

CountRowTwo якось відрізняється від CountRowThree? Якщо ні - нащо там дві змінні? І нащо два виклики Row.length()?
Замість erase тут краще використовувати substr. І дотримуватися DRY:

int rowLength = Row.length();
RowPlace  = Row.substr( rowLength - 1,  1);
RowNumber = Row.substr( 0, rowLength - 1 );

І ще незрозуміло, чи треба казати, чи знаходится місце 1A біля проходу. З фактом - так. Ваша програма каже window і все... але може то за умовою так треба?

Logans написав:

А фразу "якщо не заперечуєте", я гадаю потрібно писати перед тим, як зробити те, що комусь може не сподобатись, якщо вже скопіювали то так і буде.

Де я скопіював? У вас прекешування з майбутнього встановлено? Підкажіть, як?

Подякували: Logans1

17

Re: Робота з рядками

Дякую за корисні речі, CountRowTwo\Three я раніше намагався зробити через одну змінну, очевидно, що після використання однієї я забув в if переписати, дякую. За substr я не знав, також вельме вдячний :)

І ще незрозуміло, чи треба казати, чи знаходится місце 1A біля проходу. З фактом - так. Ваша програма каже window і все... але може то за умовою так треба?

слід розцінювати як біля вікна, пріорітет: window (вікно) - aisle (прохід) - nether (ні то, ні то).

Де я скопіював? У вас прекешування з майбутнього встановлено? Підкажіть, як?

Можливо я занадто різко зреагував, вибачте. З вашого повідомлення я зробив висновок, очевидно, що не вірний, що ви вже відправили код.

18

Re: Робота з рядками

Logans написав:

За substr я не знав, також вельме вдячний :)

З erase код виходить практично такий самий, тільки erase/insert менш ефективні за substr і copy. Хоча, звісно, в цьому коді це практичного значення не має.

19 Востаннє редагувалося Logans (08.12.2013 09:05:30)

Re: Робота з рядками

koala написав:
Logans написав:

За substr я не знав, також вельме вдячний :)

З erase код виходить практично такий самий, тільки erase/insert менш ефективні за substr і copy. Хоча, звісно, в цьому коді це практичного значення не має.

Дякую, вже використав і справді корисна річь, меньше коду це справді те, що мені потрібно.

А для цього перебору (пошук згідно літери), можете щось порекомендувати? Тому, що досить не гарно виглядить код з таким багажем перевірок.

20 Востаннє редагувалося koala (08.12.2013 10:50:25)

Re: Робота з рядками

#include <stdlib.h>
#include <iostream>
#include <string>
 
using namespace std;

const string w = "window",
             a = "aisle",
             n = "neither";
const int salonCount = 3;

struct Salon
{

  int firstRow;
  const string *placeTypes[20];
}  airBus[salonCount] = {
                { 1,  {&w,             &a,         &a,             &w} },
                { 3,  {&w,     &a,     &a,         &a,     &a,     &w} },
                { 21, {&w, &n, &a,     &a, &n, &n, &a,     &a, &n, &w} }
              };

int main()
{
    string Row;
    setlocale(LC_ALL, "");
 
    cout << "Введiть номер мiсця: " << endl;
    cin >> Row;
 
    int rowLength = Row.length();
    string Place  = Row.substr( rowLength - 1, 1             ),
           Number = Row.substr( 0,             rowLength - 1 );
    int IntegerNumber = atoi(Number.c_str());
    int salonNumber=0;
    while( ( salonNumber < salonCount) && ( IntegerNumber >= airBus[salonNumber].firstRow ) )
            ++salonNumber;
      
    char Litera = Place[0];
    if( Litera > 'I' ) --Litera;
    cout << *airBus[salonNumber - 1].placeTypes[Litera - 'A'];
    
    return 0;
}

Додати stdafx та паузу за смаком.
todo: зробити завантаження схеми літаку з файлу :)