Другое > Hard'n'Soft
Програмирование на C++
<< < (18/25) > >>
gepar:

--- Цитата: HoRRoR ---Ты не ищешь вхождение, ты разбиваешь на лексемы
--- Конец цитаты ---
Я нахожу лексемы и беру только числа содержащие в начале новой лексемы, это то какраз и будут ID  :) Смысла копировать n символов и их преобразовать через atoi я не вижу так как atoi всё равно вернёт число до первого символа.

--- Цитата: ALEX_230_VOLT ---дело в том, что у меня тип строки string, а НЕ массив из char
--- Конец цитаты ---
В с++ как строку часто воспринимают и массив символов так как им довольно удобно пользоваться, у HoRRoR как видишь тоже указатель на char.

--- Цитата: ALEX_230_VOLT ---а вот как использовать функцию HoRRoR я что то не понял
--- Конец цитаты ---
А вот это плохо так как при написании курсовой уже надо уметь вызывать функции

--- Код: ---#include <cstring>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;

void findIDs(const char *str, vector<int>& ids)
{
    char buf[7] = "";
    while(str = strstr(str, "ID"))
    {
        str += 3;
        strncpy(buf, str, 6);
        ids.push_back(atoi(buf));
    }
}

int main()
{
    char *string="Bla bla ID 100500 bla bla ID 200300 bla bla ID 300400";
    vector <int> abc;
    findIDs(string,abc);
    cout<<"Result for string \""<<string<<"\" is:\n";
     for(int i=0;i<abc.size();i++)
      cout<<abc[i]<<endl;
}

--- Конец кода ---


Добавлено позже:

--- Цитата: HoRRoR ---Это не символ, это конец потока. Как ты из файла уберёшь конец файла, например?
--- Конец цитаты ---
Ну через cin.clear() убрал же очистив флаги состояний  :)
HoRRoR:

--- Цитата ---Я нахожу лексемы и беру только числа содержащие в начале новой лексемы, это то какраз и будут ID
--- Конец цитаты ---
И что? Говорю же - из пушки по воробьям. Тебя бы на работу не взяли, если бы ты тестовое задание решил так.


--- Цитата ---Смысла копировать n символов и их преобразовать через atoi я не вижу так как atoi всё равно вернёт число до первого символа.
--- Конец цитаты ---
Как ты тогда возьмёшь именно N цифр? Ты не видишь, а я вижу.


--- Цитата ---Ну через cin.clear() убрал же очистив флаги состояний
--- Конец цитаты ---
Что ты убрал? Ничего ты не убрал, а именно что очистил флаги состояний.

Добавлено позже:
К слову, совсем забыл, если ты почитаешь спецификацию strtok, то ты поймёшь, что использование этой функции - ошибка. Попробуй на строке "ID 123214 ololo sfdb sd I sdfs D  sdfsdfpi I III DDDD ID 234234".
gepar:

--- Цитата: HoRRoR ---Что ты убрал? Ничего ты не убрал, а именно что очистил флаги состояний.
--- Конец цитаты ---
Всё я убрал  :) Вот наглядно будет:

--- Код: ---# include <iostream>
using namespace std;

int main()
{
    int n=127;
    char ch1[n];
    char ch2[n];
    cout<<"cin.get in ch1: ";
    cin.get(ch1,n, EOF);
    cout<<"\n\n!!!cin.eof() before cin.clear()="<<cin.eof();
    cin.clear();
    cout<<"\n!!!cin.eof() after cin.clear()="<<cin.eof();
    cout<<"\n\ncin.get in ch2: ";
    cin.get(ch2,n, EOF);
    cout<<"\n\nCh1 is: "<<ch1<<"\nCh2 is: "<<ch2;
}
--- Конец кода ---

Теперь после конца ввода в первую символьную переменную и нажатия ctrl+z будет идти считывание во вторую переменную чего я и добивался. При cin.clear() очищается состояние флагов, в том числе и cin.eof().

Добавлено позже:

--- Цитата: HoRRoR ---И что? Говорю же - из пушки по воробьям. Тебя бы на работу не взяли, если бы ты тестовое задание решил так.
--- Конец цитаты ---
Ну вот тебе на  :'( Но я не вижу в чём преимущество твоего кода. Функция strstr возвращает указатель на вхождение ID, функция strtok тоже возвращает указатель на вхождение ID.  Дальше ты копируешь 6 символов (если ID больше то надо считать, а это ещё плюс строки и переменные) и корректируешь адрес своей строки (str += 3), если после ID не будет пробела то ID считано вовсе будет не верно так что ещё и тут надо проверку добавлять ... а если пробел не 1 а 2 или больше ( ещё + проверка) ... в итоге объём кода и количество проверок для переменной для столь простой задачи и правда будет больше похож на курсовую (ALEX_230_VOLT, задумайся над этим  :D).
В общем может это я по неопытности не вижу преимущества всех твоих проверок и использования функции strstr вместо strtok (ну блин, они же тоже самое делают) так что пусть будет так. Если при приёме на работу попросят такую программу написать - буду знать что делать :)
HoRRoR:

--- Цитата ---(ну блин, они же тоже самое делают)
--- Конец цитаты ---
Во-первых, strstr не изменяет строку (работает с const char*, что важно).
Во-вторых, strtok разделяет на лексемы, поиск не является её применением по назначению. Это как минимум архитектурная ошибка. К тому же, при таком способе требуется копирование памяти, чтобы сохранить оригинал. Это бред.
В-третьих, функция strtok не ищет строку, она ищет первый попавшийся символ из строки, а не всю строку целиком. Если у тебя в тексте отдельно встречаются I и D, он на них тоже среагирует.


--- Цитата ---Если при приёме на работу попросят такую программу написать - буду знать что делать
--- Конец цитаты ---
Я вот устраиваюсь, мне дали восемь заданий, в первом надо примерно такой сложности косяки исправить. Так что всё может быть.

В общем, ты просто упёртый.
gepar:

--- Цитата: HoRRoR ---В-третьих, функция strtok не ищет строку, она ищет первый попавшийся символ из строки, а не всю строку целиком. Если у тебя в тексте отдельно встречаются I и D, он на них тоже среагирует.
--- Конец цитаты ---
А вот этого не знал, и правда на I отдельно реагирует, я всегда думал что она ищет указанную строку, а не просто вхождение первого символа из указанной строки, тогда и правда не пойдёт она для такой цели.

Добавлено позже:

--- Цитата: HoRRoR ---Я вот устраиваюсь, мне дали восемь заданий, в первом надо примерно такой сложности косяки исправить. Так что всё может быть.
--- Конец цитаты ---
Даёшь в публичный доступ, интересно же что за задания, ато на хабре была статья с вопросами на собеседовании так вот всё  были по основам и я смог ответить сразу же почти на все (несмотря на то что даже Дейтела ещё не дочитал) так что хочу видеть серьёзные тестовые задания, которые дают при приёме на работу  :)
AjaxVS:

--- Цитата: HoRRoR от 15 Май 2011, 22:27:19 ---Я вот устраиваюсь, мне дали восемь заданий, в первом надо примерно такой сложности косяки исправить.
--- Конец цитаты ---
о, я таким интересуюсь. можно задания на мыло? за какое время надо решать? и если не секрет - что за уровень фирмы (читай - какая зарплата)?
HoRRoR:

--- Цитата: gepar от 16 Май 2011, 01:13:14 ---Даёшь в публичный доступ
--- Конец цитаты ---
Только лично. См. ЛС.


--- Цитата ---о, я таким интересуюсь. можно задания на мыло? за какое время надо решать? и если не секрет - что за уровень фирмы (читай - какая зарплата)?
--- Конец цитаты ---
См. ЛС.
DeniSS:

--- Цитата: HoRRoR от 16 Май 2011, 11:48:48 ---Только лично. См. ЛС.
См. ЛС.

--- Конец цитаты ---
О, если можно, форвард мне пожалуйста.
gepar:
Тааак, задам экстремальный вопрос:
В общем была себе перегрузка оператора ввода в одном примере, рассчитана на ввод 14 символов и их сохранение в разных переменных, а теперь вот захотелось мне добавить изначально проверку содержимого, но хитро - так чтобы предыдущий написанный код не редактировать. Так вот проверку входящего потока я пририсовал, а вот теперь хочу чтобы если всё хорошо с потоком то из моего символьного массива всё запихивалось в поток на ввод, те: создать для программы впечатление что во входящем потоке уже есть 14 символов из моего массива и теперь при следующем cin>> оно сначала сжевало мои запихнутые 14 символов, а потом уже принималось за ввод с клавиатуры. Можно так?  :)
Изначально вообще код был такой

--- Код: ---istream &operator>>( istream &ainput, PhoneNumber &number )
{
   ainput.ignore(); // skip (
   ainput >> setw( 3 ) >> number.areaCode; // input area code
   ainput.ignore( 2 ); // skip ) and space
   ainput >> setw( 3 ) >> number.exchange; // input exchange
   ainput.ignore(); // skip dash (-)
   ainput >> setw( 4 ) >> number.line; // input line
   return ainput; // enables cin >> a >> b >> c;       
}; // end function operator>>

--- Конец кода ---

Теперь такой

--- Код: ---istream &operator>>( istream &ainput, PhoneNumber &number )
{
   char c[15];
   ainput.get(c,14);
   if (ainput.gcount()<14)
    ainput.clear(ios::failbit);
   if (c[1]==1 || c[1]==0)
    ainput.clear(ios::failbit);
   if (c[2]!=0 && c[2]!=1 )
    ainput.clear(ios::failbit);
// ВОТ ЗДЕСЬ НАДО БЫ КАК-ТО ПОДПИХНУТЬ В ПОТОК СОДЕРЖИМОЕ МАССИВА СИМВОЛОВ C, НУ КРОМЕ СИМВОЛА '\0' КОНЕЧНО ЖЕ
   if (!(ainput.fail()))
   {
   ainput.ignore(); // skip (
   ainput >> setw( 3 ) >> number.areaCode; // input area code
   ainput.ignore( 2 ); // skip ) and space
   ainput >> setw( 3 ) >> number.exchange; // input exchange
   ainput.ignore(); // skip dash (-)
   ainput >> setw( 4 ) >> number.line; // input line
   return ainput; // enables cin >> a >> b >> c;       
   }
}; // end function operator>>

--- Конец кода ---

Добавлено позже:
Написал тут очередное задание по Дейтелу и удостоверился что для проверки данных уходит слишком много усилий. Если интересно Complex.h

--- Код: ---#include <iostream>
using namespace std;

class complex
{
friend istream &operator>>(istream&, complex&);
friend ostream &operator<<(ostream&, const complex&);
public:
    complex()
    :real(0),image(0)
    {

    }

private:
    int real;
    double image;
};

istream &operator>>(istream& input, complex& c)
{
    char a[20];
    input.get(a,20);
    //если получено число либо символ + либо символ i
    for (int i=0;i<input.gcount()-1;i++)
     if (((((int)a[i])>=48) && (((int)a[i])<=57)) || ((int)a[i]==43) || ((int)a[i]==105)); //то ничего не делаем
    else
     input.clear(ios::failbit); //иначе установим флаг ошибки
    if (a[input.gcount()-1]=='i' && !(input.fail())) //если есть мнимая часть
    {
        //проверим есть ли реальная часть (будем искать знак +)
        for (int i=0;i<input.gcount()-1;i++)
         if ((int)a[i]==43) //если плюс найден
         {
             c.real=atoi(a);
             c.image=atoi(&a[i+1]);
         }
        else //иначе у нас только мнимая часть
         c.image=atoi(a);
    }
    else //иначе у нас нет мнимой части и есть только реальная
     if(!(input.fail()))
      c.real=atoi(a);
    return input;
}

ostream &operator<<(ostream& output, const complex& c)
{
    if (cin.fail()) // если при вводе были ошибки
    {
        output<<"WRONG INFORMATION"<<endl;
        return output;
    }
    if(c.real!=0) // если есть реальная часть
     output<<c.real;
    if (c.real!=0 && c.image!=0) // если есть и реальная и мнимая части
     output<<" + ";
    if (c.image!=0) // если есть мнимая часть
     output<<c.image<<'i';
    output<<endl;
    return output;
}

--- Конец кода ---

Main.cpp

--- Код: ---#include <iostream>
#include "Complex.h"

using namespace std;

int main()
{
    complex abc;
    cin>>abc;
    cout<<abc;
}


--- Конец кода ---
Собственно работает, хотя надо бы ещё было добавить наверное проверку что i и знак + встречаются только один раз, но что-то уже не хочеться  :)


Добавлено позже:
И ещё один вопрос:
В Дейтеле как-то косвенно упомянута хитрая возможность, вот текст

--- Код: ---Элемент-функция operator! из basic_ios возвращает true, если установлен
или badbit, или failbit, или оба бита. Элемент-функция operator void * 
возвращает false (О), если установлены badbit и/или failbit. Эти функции удобны
при обработке файлов, когда в операторе выбора или повторения проверяется
условие true/false.

--- Конец кода ---
К чему применять оператор ! и что приводить к указателю на void чтобы узнать установлен ли badbit и failbit вместе? Помоему переводчик что-то пропустил, в книге уже такое было не раз, но раньше я дешифровывал что же написано не так, а тут не могу. Подскажите же пожалуйста  :)
DeniSS:
! - это ж логическое отрицание.
gepar:
DeniSS, это ты так тонко пошутил, да?  :lol:
Уж после того как мне полгода читали курс с++ я как-то заметил уж, поначалу не верил, но потом заметил тождество что каждый раз когда его пишу так и идёт отрицание  :D
К чему отрицание применять чтобы сразу проверить и badbit и failbit? Переводчик видать пропустил.
HoRRoR:
gepar, ну читай же ты спецификацию, прежде чем глупые вопросы задавать.
http://www.cplusplus.com/reference/iostream/ios/operatornot/

К потоку применяй. !cin = cin.fail().
gepar:
HoRRoR,аааа, ясно. А что с запихиванием данных назад в поток? Или так нельзя?
gepar:
По поводу баловства с потоком: нашёл такую штуку как unget, но она может возвратить только один последний считанный символ что неудобно (результат последующих вызовов не определён). Потом наткнулся на  putback, но тем не менее работает она странно при каскадировании ... хотелось бы посмотреть что же творится во входящем потоке в это время через дебагер, но не знаю как это сделать. Подскажите как следить за данными в потоках, ато что-то code::blocks и devc++ предлагают следить только за переменными.
GManiac:
офф: gepar, если составлять представление о языке по этой теме, то возникает такое чувство, что цпп сделан, чтобы усложнить жизнь нормальным людям. По большей части за это я его не люблю. Языки должны наоборот, облегчать жизнь и понимание написанного. Вспоминаю сравнение перла и питона. А в сях некоторые простые вещи делаются через ж*пу, а при желании можно заставить и остальные вещи делать через ж*пу, макросами или перегрузкой.
Можно было сделать синтаксис намного проще и понятней, без всяких закорючек, строгих (или индусских) последовательностей закорючек, двусмысленностей и т.д., при этом с такой же функциональностью. И с нормальной совместимостью между компиляторами/средами или хотя бы их версиями. Но люди не ищут лёгких путей!
Вспоминаю, как часто путался в указателях и ссылках и const'ами на ссылку или на значение. Как путался, ставя точку вместо -> для классов. Да, формально так и должно быть, но почему-то дельфисты решили, что человек важнее, поэтому не стали никому морочить голову, и в структурах, и в классах ставится точка. Кстати, структуры в новых дельфях - это почти полноценные классы, единственное отличие - их не надо создавать через конструктор.

Если не согласны насчёт сложности и заморочек, сравните, сколько страниц в ЭТОЙ теме и в теме про паскаль.

Это как: чтобы включить свет, надо передвинуть рычаг коробки передач (рядом с выключателем) в строгой последовательности. А если сделаешь неправильно, будет пожар. Или хочешь открыть холодную воду, поворачиваешь вентиль, а вместо этого на тебя льётся кипяток из душа. Примеры утрированы.
gepar:
GManiac,ты утрируешь  :) Особенно здесь
--- Цитата: GManiac ---Вспоминаю, как часто путался в указателях и ссылках и const'ами на ссылку или на значение. Как путался, ставя точку вместо -> для классов.
--- Конец цитаты ---
В моей теме по паскаль меньше страниц потому что у паскаля возможностей же меньше, я за пол года его практически полностью изучил (кстати ничего себе полезного так на нём и не написал, разве что по чм каким-то методом решал уравнение , методом Симпсона вроде) а вот дельфи после паскаля что-то показалась мечтой быдло-программиста (программирование мышкой же!) и я после созданий пары кнопок да окошек (без путеводителя найти ничего невозможно, даже банально откомпилировать скопипащенный код) закинул это дело. Ну и на данный момент меня всё же привлекает с++, а для тех кому хочется в коде видеть больше не сокращённых понятных слов  есть си решётка  :)
Mr2:

--- Цитата: GManiac ---Как путался, ставя точку вместо -> для классов.
--- Конец цитаты ---
Можешь также вызывать указатель на класс  без ->.
(*obj).one;

--- Цитата: GManiac ---Можно было сделать синтаксис намного проще и понятней, без всяких закорючек
--- Конец цитаты ---
Что же не сделал? :)

--- Цитата: GManiac ---А в сях некоторые простые вещи делаются через ж*пу, а при желании можно заставить и остальные вещи делать через ж*пу, макросами или перегрузкой.
--- Конец цитаты ---
Это зависит не от языка, а от выбора программиста.Можешь писать через Ж, можеш через.....Свобода.
gepar:

--- Цитата: Mr2 ---Что же не сделал?
--- Конец цитаты ---
Не, он о cout например (взглянув не зная синтаксиса можно не догадаться что это), writeln  в этом случае выглядите логичние, но само слово то длиннее . А вообще все эти разделения на процедуры , bigin /end'ы ({} короче же и не менее понятно да ещё и выделяются хорошо  :) ).

Добавлено позже:
Кстати о веслых штуках в с++

--- Код: ---int main ()
{
    int i=1;
    i=++i + ++i;
    cout<<i;
}


--- Конец кода ---
Почему шесть?  :lol:
topos84:

--- Цитата: gepar ---Почему шесть?
--- Конец цитаты ---
А не 5. :) Одна из операций ++i выполняется 2 раза?
Fly:
Наверное сначала выполняются обе операции ++i, а потом уже сложение получившихся i. Получается 3+3=6.
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

Перейти к полной версии