Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [C++] Работа со строкой без использования String 
V
    Опции темы
Fally
Дата 16.5.2007, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 17.8.2006
Где: Dahla

Репутация: нет
Всего: 4



Люди, помогите пожалуйста. Написал программу, но в ней где-то в алгоритме ошибка. Если есть возможность помогите. Завтра сдавать... у самого уже мозги не работают. Вот программа, в ней и условие записано:

Код

/***************************************************************************************
 * Слова текста из малых латинских букв записаны не менее чем через один пробел;       *
 * текст оканчивается точкой БЕЗ ИСПОЛЬЗОВАНИЯ конструкции STRING:                     *
 *    а) написать программу ввода такого текста с клавиатуры;                          *
 *    б) напечатать все слова, входящие в текст по одному разу.                        *
 ***************************************************************************************/
#include "stdafx.h"
#include <vector> // Тип вектор потому, что количество символов в строке не определено.
#include <cctype> // Для использования функция isspace(), isalpha и т.д.
#include <iostream> // Стандартный поток ввода вывода.
using namespace std;
int main() {
    vector<char> UserString; // Символьный вектор, содержащий символы строки, введенной пользователем.
    char Symbol = '0'; // Считываемый сивол, по умолчанию в 0, чтоб не сглючило случайно.
    char PredSymbol = '0'; // предыдущий символ для текущего.
    cout << "Vvedite stroku: ";
    while(cin.get(Symbol)) { // Посимвольно считываем введённую пользователем строку.
        if(('.' == Symbol)) break; // Если символ - точка, то прекращаем ввод.
        else if('.' == Symbol && isspace(PredSymbol)) break; // Если символ точка, и предыдущий - пробел, то прекращаем ввод.
        else if('\n' == Symbol)  continue; // Если есть символ новой строки, то не записываем его.
        else if(ispunct(Symbol)) continue; // Не записываем различные знаки препинания
        else if(isspace(Symbol) && isspace(PredSymbol)) continue; // Если текущий символ, как и предыдущий - пробел, то не записываем его.
        else if(isspace(Symbol) && !isspace(PredSymbol)) UserString.push_back('\40'); // Текущий - пробел, предыдущий - не пробел, записываем вектор в пробел.
        else if(isalpha(Symbol)) UserString.push_back(tolower(Symbol)); // Если буква, то записываем её в нижнем регистре.
        else continue;
        PredSymbol = Symbol;
    }
    // Защита от ввода единственной точки.
    if(0 == UserString.size()) {
        cout << "Vy vveli tol'ko odin simvol, etot simvol '.'!" << endl;
    }
    // Защита от ввода пробела(-ов) и точки.
    else if(1 == UserString.size() && '\40' == UserString[0]) {
        cout << "Vy vveli tol'ko probel!" << endl;
    }
    else {
        // Проверяем конец вектора, на наличие в нём пробелов.
        for(vector<char>::iterator i = (UserString.end() - 1); i >= UserString.begin(); i--) {
            if(isspace(*i)) UserString.pop_back(); // если последний символ - пробел, то удаляем его.
            else break;
        }
        vector<char> TmpWord;
        cout << endl << endl << "Slova vhodyaschie po odnomu razu: " << endl;
        vector<char>::iterator iter = UserString.begin();
        vector<char>::iterator ChkWBegin; // Начало проверяемого слова.
        vector<char>::iterator ChkWEnd; // Конец проверяемого слова.
        vector<char> ChkWord; // Проверямое слово.
        enum setPos {N, Y};
        setPos FlagWBeg = N;
        setPos FlagWEnd = N;
        setPos RepeatFlag = N;
        for(; iter != UserString.end(); iter++) { // Начинаем с начала введённой строки и до её конца.
            if(!isspace(*iter)) { 
                TmpWord.push_back(*iter); // Если текущий символ - не пробел, то записываем его в обрабатываемое словл.
            }
            else { // если симвот - пробел, тогда начинаем обработку записанного слова.
                if(1 <= TmpWord.size() && !isspace(TmpWord[0])) { // если длина слова больше 1, и первый символ не пробел - то продолжаем обработку слова.
                    for(vector<char>::iterator getWBE = iter; getWBE != UserString.end(); getWBE++) {
                        if(N == FlagWBeg && N == FlagWEnd && '\40' != *getWBE) {
                            ChkWBegin = getWBE; // Фиксируем начало проверяемого слова.
                            FlagWBeg = Y; // Запомнили, что установили позицию начала слова.
                        }
                        if(Y == FlagWBeg && N == FlagWEnd && '\40' == *getWBE) {
                            ChkWEnd   = getWBE; // Фиксируем конец проверямого слова.
                            FlagWEnd = Y; // Запомнили, что установили позицию конца слова.
                        }
                        if(Y == FlagWBeg && Y == FlagWEnd) {
                            for(vector<char>::iterator j = ChkWBegin; j != ChkWEnd; j++) {
                                //cout << *j;
                                ChkWord.push_back(*j);
                            }
                            // Пока в конце проверяемого слова есть пробелы, удаляем их.
                            while('\40' == ChkWord[ChkWord.size() - 1]) ChkWord.pop_back();
                            if(TmpWord == ChkWord) { // Если текущее повторяется, то удаляем из вектора повтор.
                                RepeatFlag = Y;
                                FlagWBeg = N;
                                FlagWEnd = N;
                                TmpWord.clear();
                                ChkWord.clear();
                                break;
                            }
                            if(Y == RepeatFlag) break;
                        }
                    }
                    //-------------------------------
                    if(Y != RepeatFlag) {
                        vector<char>::iterator j = TmpWord.begin();
                        for(; j != TmpWord.end(); j++) {
                            cout << *j;
                        }
                        cout << endl;
                        TmpWord.clear();
                        ChkWord.clear();
                        FlagWBeg = N;
                        FlagWEnd = N;
                    }
                    else {
                        RepeatFlag = N;
                        continue;
                    }
                    //-------------------------------
                }
                else { // если длина меньше 1, или 1-ый символ в слове является пробелом, тогда очищаем текущее слово и начинаем считывать новое.
                    TmpWord.clear();
                }
            }
        }
    }
    cout << endl << endl;
    int WaitExit; // Просто для ожидания ввода с клавиатуры.
    cin >> WaitExit; // Ожидаем ввод и нажатие клавиши enter, и завершаем программу.
    return 1; 
}


Из-за поставленного задания пришлось в качестве хранилища введённой строки  использовать переменную типа вектор, т.к. использования строк в стиле С тоже запрещено. Всё приходиться делать вручную.

Это сообщение отредактировал(а) Fally - 16.5.2007, 17:19


--------------------
Прежде чем задать вопрос на форуме воспользуйтесь поиском.
user posted image
user posted image
PM MAIL   Вверх
GIK
Дата 16.5.2007, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Добрый человек
**


Профиль
Группа: Участник
Сообщений: 985
Регистрация: 3.6.2005
Где: я только не небыв ал

Репутация: 4
Всего: 14



Предлагая такой вариант (твой код не вкурил пока): можно фиксировать значение итераторов которые указывают на пробелы, создать обычный буфер - массив char относительно большого размера, например 21 символ. Считываем слово от пробела до пробела в ran массив и прогоняем по всему вектору, если слово встретилось один раз, то это единственое слово. 
Если не засну то напишу smile  


--------------------
Математика=>пиво=> програмирование, три вещи последовательны и совместимы !!!
Программирование - это не деятельнось! Программирование - это состояние души!
Бог - самый крутой программист.
PM MAIL ICQ   Вверх
GIK
Дата 17.5.2007, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Добрый человек
**


Профиль
Группа: Участник
Сообщений: 985
Регистрация: 3.6.2005
Где: я только не небыв ал

Репутация: 4
Всего: 14



Вот, кое что сделал, правда не проверял, на работе щас smile
Если что посмотрите кто может, уж очень интересная задача показалась smile 
Код


#include <vcl.h>
#pragma hdrstop

#pragma argsused

/***************************************************************************************
 * ????? ?????? ?? ????? ????????? ???? ???????? ?? ????? ??? ????? ???? ??????;       *
 * ????? ???????????? ?????? ??? ????????????? ??????????? STRING:                     *
 *    ?) ???????? ????????? ????? ?????? ?????? ? ??????????;                          *
 *    ?) ?????????? ??? ?????, ???????? ? ????? ?? ?????? ????.                        *
 ***************************************************************************************/


#include <vector>
#include <cctype>
#include <iostream>

#include <cstdio>
#include <conio>
using namespace std;
int main() {

    vector<char> UserString; // ?????????? ??????, ?????????? ??????? ??????, ????????? ?????????????.
    char Symbol = '0'; // ??????????? ?????, ?? ????????? ? 0, ???? ?? ???????? ????????.
    char PredSymbol = '0'; // ?????????? ?????? ??? ????????.
    cout << "Vvedite stroku: ";
    while(cin.get(Symbol)) { // ??????????? ????????? ????????? ????????????? ??????.
        if((46 == Symbol)) break; // ???? ?????? - ?????, ?? ?????????? ????.
        else if(46 == Symbol && isspace(PredSymbol)) break; // ???? ?????? ?????, ? ?????????? - ??????, ?? ?????????? ????.
        else if('\n' == Symbol)  continue; // ???? ???? ?????? ????? ??????, ?? ?? ?????????? ???.
        else if(ispunct(Symbol)) continue; // ?? ?????????? ????????? ????? ??????????
        else if(isspace(Symbol) && isspace(PredSymbol)) continue; // ???? ??????? ??????, ??? ? ?????????? - ??????, ?? ?? ?????????? ???.
        else if(isspace(Symbol) && !isspace(PredSymbol)) UserString.push_back('\40'); // ??????? - ??????, ?????????? - ?? ??????, ?????????? ?????? ? ??????.
        else if(isalpha(Symbol)) UserString.push_back(tolower(Symbol)); // ???? ?????, ?? ?????????? ?? ? ?????? ????????.
        else continue;
        PredSymbol = Symbol;
    }
    
    if(0 == UserString.size()) {
        cout << "Vy vveli tol'ko odin simvol, etot simvol '.'!" << endl;
    }
    
    else if(1 == UserString.size() && '\40' == UserString[0]) {
        cout << "Vy vveli tol'ko probel!" << endl;
    }

    vector<char>::iterator iter= UserString.begin(), iter2;
    char ran[21]={0}, ranG[21]={0};
    int itt=0, eee=0;
    vector<char>::iterator rannn[21]={0}; //итераторы для пробелов

    for(; iter != UserString.end(); iter++) {
            if(isspace(*iter)){ rannn[itt] = iter; itt++;} //фиксируем итераторы на пробелы

    }
    int i=0, k=0, j=0, f=0;
    iter = UserString.begin();
    iter2 = UserString.begin();

//Если выше происходит корректное удаление лишних пробелов и символов, то алгоритм должен работать :)
    for(i=0; i<itt; i++){
      //Вытаскиваем слова поочередно
       while(*iter2!=32 && *iter2!=46){
         ran[k]=*iter2;
         k++;
         iter2++;
       };
      //Прогоняем вытащенное слово через весь массив
     iter = UserString.begin();
     while(*iter!=46){  //пока не дойдем до точки
       if(*iter!=32 && *iter!=46) ranG[f]=*iter;
       else //Если дошли до пробела или точки, сравниваем слова
        {
          if(strcmp(ran, ranG)==0) eee++;
          for(j=0; j<f; j++) ranG[j]=0; //Чистим массив
          f=-1;          
         }
       iter++; f++;
     }     
     if(eee==1) //Если слово в одном экземпляре (слово нашло сомо себя)
     {
       std::cout<<"--"<<ran<<"--"<<'\n';
     }
     for(j=0; j<k; j++)
       ran[j]=0; //обнуляем слово

     k=0; f=0; eee=0; //Обнуляем переменные
     iter2 =rannn[i]; //iter2 вытаскивает слово поочередно, получает адрес начала слова
     iter2++; //следующий символ после пробела
    }

   getch();
    return 1; 
}



--------------------
Математика=>пиво=> програмирование, три вещи последовательны и совместимы !!!
Программирование - это не деятельнось! Программирование - это состояние души!
Бог - самый крутой программист.
PM MAIL ICQ   Вверх
Fally
Дата 20.5.2007, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 17.8.2006
Где: Dahla

Репутация: нет
Всего: 4



спасибо за пример, только он у меня в паре мест не работал. Но задачу я всё-таки решил. Вот код:
Код

/***************************************************************************************
 * Слова текста из малых латинских букв записаны не менее чем через один пробел;       *
 * текст оканчивается точкой БЕЗ ИСПОЛЬЗОВАНИЯ конструкции STRING:                     *
 *    а) написать программу ввода такого текста с клавиатуры;                          *
 *    б) напечатать все слова, входящие в текст по одному разу.                        *
 ***************************************************************************************/
#include <vector> // Тип вектор потому, что количество символов в строке не определено.
#include <cctype> // Для использования функция isspace(), isalpha и т.д.
#include <iostream> // Стандартный поток ввода вывода.
using namespace std;
int main() {
    vector<char> UserString; // Символьный вектор, содержащий символы строки, введенной пользователем.
    char Symbol = '0'; // Считываемый сивол, по умолчанию в 0, чтоб не сглючило случайно.
    char PredSymbol = '0'; // предыдущий символ для текущего.
    cout << "Vvedite stroku: ";
    while(cin.get(Symbol)) { // Посимвольно считываем введённую пользователем строку.
        if(('.' == Symbol)) break; // Если символ - точка, то прекращаем ввод.
        else if('.' == Symbol && isspace(PredSymbol)) break; // Если символ точка, и предыдущий - пробел, то прекращаем ввод.
        else if('\n' == Symbol)  continue; // Если есть символ новой строки, то не записываем его.
        else if(ispunct(Symbol)) continue; // Не записываем различные знаки препинания
        else if(isspace(Symbol) && isspace(PredSymbol)) continue; // Если текущий символ, как и предыдущий - пробел, то не записываем его.
        else if(isspace(Symbol) && !isspace(PredSymbol)) UserString.push_back('\40'); // Текущий - пробел, предыдущий - не пробел, записываем вектор в пробел.
        else if(isalpha(Symbol)) UserString.push_back(tolower(Symbol)); // Если буква, то записываем её в нижнем регистре.
        else continue;
        PredSymbol = Symbol;
    }
    // Защита от ввода единственной точки.
    if(0 == UserString.size()) {
        cout << "Vy vveli tol'ko odin simvol, etot simvol '.'!" << endl;
    }
    // Защита от ввода пробела(-ов) и точки.
    else if(1 == UserString.size() && '\40' == UserString[0]) {
        cout << "Vy vveli tol'ko probel!" << endl;
    }
    else {
        // Проверяем конец вектора, на наличие в нём пробелов.
        while(isspace(UserString[UserString.size() - 1])) UserString.pop_back();
        vector<char> LastWord; // последнее слово в нормальном виде.
        vector<char> TmpLastWord; // Для считывания последнего слова в обратном порядкею
        cout << "Poslednee slovo: " << endl;
        // "Вытаскиваем" из введённой пользователем строки последнее слово, в обратном виде, т.е. было "слово", а стало "оволс".
        for(vector<char>::iterator iter = (UserString.end() - 1); iter >= UserString.begin(); iter--) {
            if(0 !=  TmpLastWord.size() && isspace(*iter)) break; // если размер вектора отличен от нуля,
                                                                  // и текущий символ - пробел, то выходим из цикла.
            if(isalpha(*iter)) {
                TmpLastWord.push_back(*iter); // Если текущий символ строки - буква, записываем в вектор.
            }
            else continue; // иначе, следующая итерация цикла.
        }
        // В этом цикле записываем последнее слово в привычном для человека виде.
        iter = (TmpLastWord.end() - 1);
        for(; iter >= TmpLastWord.begin(); iter--) {
            LastWord.push_back(*iter);
        }
        vector<char> TmpWord;
        cout << endl << endl << "Slova vhodyaschie po odnomu razu: " << endl;
        vector<char>::iterator iter = UserString.begin();
        vector<char> ChkWord; // Проверямое слово.
        unsigned int countOfEquals = 0;
        for(; iter != UserString.end(); iter++) { // Начинаем с начала введённой строки и до её конца.
            if(!isspace(*iter) && (iter + 1) != UserString.end()) { 
                TmpWord.push_back(*iter); // Если текущий символ - не пробел, то записываем его в обрабатываемое словл.
            }
            else { // если символ - пробел, тогда начинаем обработку записанного слова.
                countOfEquals = 0;
                if(1 <= TmpWord.size() && !isspace(TmpWord[0])) { // если длина слова больше 1, и первый символ не пробел - то продолжаем обработку слова.
                    for(vector<char>::iterator getWord = UserString.begin(); getWord != UserString.end(); getWord++) {
                        if(!isspace(*getWord)) {
                            ChkWord.push_back(*getWord);
                        }
                        else {
                            if(1 <= ChkWord.size() && !isspace(ChkWord[0])) {
                                // Записываем текущее слово.
                                if(TmpWord == ChkWord) {
                                    countOfEquals++;
                                    continue;
                                } else if(TmpWord == LastWord) { // Если проверяемое слово равно последнему.
                                    countOfEquals++;
                                    continue;
                                }
                                else {
                                    ChkWord.clear();
                                    continue;
                                }
                            }
                            else {
                                ChkWord.clear();
                                continue;
                            }
                        }
                    }
                    //-------------------------------
                    if(1 == countOfEquals) {
                        vector<char>::iterator j = TmpWord.begin();
                        for(; j != TmpWord.end(); j++) {
                            cout << *j;
                        }
                        cout << endl;
                        TmpWord.clear();
                        ChkWord.clear();
                        countOfEquals = 0;
                        continue;
                    }
                    else {
                        TmpWord.clear();
                        ChkWord.clear();
                        countOfEquals = 0;
                        continue;
                    }
                    //-------------------------------
                }
                else { // если длина меньше 1, или 1-ый символ в слове является пробелом, тогда очищаем текущее слово и начинаем считывать новое.
                    TmpWord.clear();
                    ChkWord.clear();
                    continue;
                }
            }
        }
    }
    cout << endl;
    int WaitExit; // Просто для ожидания ввода с клавиатуры.
    cin >> WaitExit; // Ожидаем ввод и нажатие клавиши enter, и завершаем программу.
    return 1; 
}



--------------------
Прежде чем задать вопрос на форуме воспользуйтесь поиском.
user posted image
user posted image
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.0512 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.