Loading...
Filipbg avatar Filipbg 26 Точки

05. Invalid Input

#include <iostream>
#include <sstream>
#include <vector>
using namespace std;

int main()
{
    string input;
    getline(cin, input);
    istringstream iss;
    vector<int> numbers;
    int total = 0;
    int number;
    iss >> input;
    while(iss >> number)
    {
       total += number;
       numbers.push_back(number);
    }

    cout << total;
    return 0;
}

Нещо забих на тази задача. Исках да извадя сбора на числата и след това да се опитам да принтирам остатъка от стриима, но не влиза дори в while цикъла.

Тагове:
0
C++ Fundamentals
m.nikolov97 avatar m.nikolov97 25 Точки
Best Answer

Здравей, Филип!

Започнал си добре, но виждам няколко грешки в подхода ти. Ще си позволя да ти дам няколко съвета, спрямо методът, по който аз съм решил въпросната задача:

  1. Входът ти е стринг. След това ти използваш променлива number, която трябва да е от друг тип, за да сработи програмата.
  2. Четеш правилно от потока, но в него трябва да разграничиш числата от думите. Има много лесен начин, за който може да прочетеш тук: https://www.tutorialspoint.com/isalpha-and-isdigit-in-c-cplusplus.
  3. Когато си сигурен, че входът, който обработваш е число (тук има една особеност, защото в тази задача числото може да е и отрицателно, т.е. да започва с -), трябва да си направиш една променлива, в която чрез stoi да вземаш стойността на числото и да я добавяш някъде (в твоя случай - total).
  4. Ако попаднеш на дума, трябва да я добавиш към друга променлива, в която да държиш output-a от думи (добавяйки ги с +, както числата). Това се налага, защото се иска да записваме и думите накрая.

Надявам се да съм помогнал! Ако все още имаш проблеми, може да прегледаш моето решение: https://pastebin.com/2LMr4LM4.

2
Filipbg avatar Filipbg 26 Точки

Благодаря зя отговора. Логиката ме обърка. Не се сещах как да ги извадя едно от друго числата и стринговете. 

0
krstoilo avatar krstoilo 3 Точки

Здравейте!

Аз също забих с това, как да оставя само думите в стринга и след 500 различни опита, все пак използвах показания в този пост начин.

Всичко работи супер, но не разбирам защо точно този момент конкретно работи по този начин:

std::istringstream lineStrm(line);
    std::string words;
    std::string printWord;

    while(lineStrm >> words){

        if(isalpha(words[0])){

            printWord += words + " ";
        }
    }

Потокът се записва в string и след това проверяваме дали всеки елемент от този string е буква или не. Ако е буква - се записва във втори string, който после се принтира. Как обаче се разграничава че потокът се състои от отделни думи и програмата знае кога да сложи white space, след като ги въртим елемент по елемент от string-а? Не трябва ли така както е записано,да слага white space след всяка отделна буква, която засече?

Слагам цялото решение, в случай че не става ясно какво точно питам (то и аз не съм сигурна вече blush);

http://pastebin.com/PMfeCjdk

Благодаря предварително! :)

Кремена

0
dmartinov avatar dmartinov 37 Точки

Един съвет от мен - ако се опитваш да четеш чужд код и не успяваш да схванеш логиката му сложи си един брейкпойнт на подходящо място (обикновено там където имаш цикъл от някакъв тип или пък четеш/подаваш нещо) и върви стъпка по стъпка, за да го видиш какво прави като задължително следиш промените на променливите, за да си обясниш какво всъщност прави това парче от кода, на което си в момента.

За конкратния случай - когато ползваш потоци които ще подавш към някаква променлива е важен от какъв тип ще е променливата, за да можеш да извлечеш съответния тип. В случая това е стринг. Стандартния delimiter е space. Тоест извличането става дума по дума, а не символ по символ. 

int main() {

    std::string input;

    getline(std::cin, input);

    titleCase(input);

    return 0;
}


std::istringstream lineStrm(line);
    std::string words;
    std::string printWord;

    while(lineStrm >> words){ --> тук казваш - докато потока може да се излива в стринга words, върти цикъла. Какво се случва - докато от потока успява да чете стрингове ги взима и записва цялата дължина на стринга (цялата дума) докато не срещне space.

        if(isalpha(words[0])){ --> ако горното условие е вярно значи сме срещнали стринг и тук проверява не символ по символ, а дали първият символ е буква

            printWord += words + " ";  --> в случай, че предходната проверка е вярна, към стринга printWords добави стринга който от потока се е записал в стринга words, след което добавя space.
        }
    }

След първата итерация на цикъла, while(lineStrm >> words), сме извлякли първата дума и следва второ завъртане на цикъла. Ако отново срещне стринг, прави проверките, и следва трето завъртане на цикъла. Ако срещне нещо различно от стринг ще излезе от цикъла и продължава с изпълнението на останалия код от програмата.

Или накратко казано, нещата които са те объркали в случая са, че когато поток се записва в стринг, то той записва цялата дължина на стринга до срещане делимитер-а който е space. И второто нещо, е че не си обърнала внимание на if проверката, която не проверява символ по символ, а само първия, след което, ако проверката е вярна, към стринга printWord добавя извлечения стринг и след него слага спейс. Логиката в това е, че е достатъчно само първия елемент от стринга да е буква, за да кажем, че това е стринг, защото знаем, че ако е цифра, то стрийма не би го подал към стринга.

Ето ти и моето решение, да го разгледаш. Доста е сходно, проверките ми са малко по-различни, но е базирано на същата логика:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>

void titleCase(std::string input) {

    std::istringstream iss(input);
    std::string temp;
    int found = 0;
    std::vector<int> numbers;
    std::vector<std::string> issText;

    while (!iss.eof()) {
        iss >> temp;
        if(std::istringstream(temp) >> found) {
            numbers.push_back(found);
        } else {
            issText.push_back(temp);
        }
    }
    int numbersSize = numbers.size();
    int issTextSize = issText.size();
    int sum = 0;
    for (int i = 0; i < numbersSize; ++i) {
        sum += numbers[i];
    }
    std::cout << sum << std::endl;

    for (int i = 0; i < issTextSize; ++i) {
        std::cout << issText[i] << " ";
    }
}

int main() {

    std::string input;

    getline(std::cin, input);

    titleCase(input);

    return 0;
}

1
08/10/2019 10:55:13
krstoilo avatar krstoilo 3 Точки

Много благодаря за съвета и за подробния отговор! :) yes


Определено си прав, за записването на потока в стринг имах предположение че става нещо такова, но абсолютно бях пропуснала момента, че проверява само първия символ от конкретния стринг! Което в случая работи добре за задачата, но като цяло е сериозен пропуск.

 

0
dmartinov avatar dmartinov 37 Точки

Включвам се отново, за да се самокорегирам :) Там където казвам "...достатъчно само първия елемент от стринга да е буква, за да кажем, че това е стринг, защото знаем, че ако е цифра, то стрийма не би го подал към стринга.", не съм съвсем прав. Ако имаме например 6fun стрийма няюа да извлече само fun, ами 6fun защото 6 е част от стринга. В такъв случай проверката if(isalpha(word[0])) ще фейлне защото първия символ от стринга не е буква. За конкретната задача (доколкото помня условието) това не е проблем, защото цифрите са отделени от стринга. Но ако не бяха, това щеше да е проблем и да се изисква по-различен подход от сорта на този, който е необходим в задачата signal and the noise.

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.