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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Что то не так с isspace(); Не могу разобраться, помогите!) 
V
    Опции темы
lllJollyRogerlll
Дата 26.1.2015, 23:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Не судите строго, но если считаете меня полным идиотом - можно прямо в лоб.
Ситуация такая - нужно решить задачку, она достаточно легкая(по крайней мере так написано на сайте, где я её нашел). Но у меня видимо не хватает мозгов для того что бы решить её. 
Вот суть:
Цитата

Исходные данные
Входной поток содержит набор целых чисел Ai (0 ≤ Ai ≤ 1018), отделённых друг от друга произвольным количеством пробелов и переводов строк. Размер входного потока не превышает 256 КБ.
Результат
Для каждого числа Ai, начиная с последнего и заканчивая первым, в отдельной строке вывести его квадратный корень не менее чем с четырьмя знаками после десятичной точки.

Я не хочу что бы вы за меня её решили, планирую сам разобраться. Для начала я решил поиграть со строками, а потом уже когда пойму что да как - перейду к вещественным числам. 
Итак, сейчас я написал немного кода, где создаю переменную, символьный массив, затем предлагаю пользователю инициализировать этот массив. Дальше - проверяю его, если идут символы - я копирую в массив, сохраненный в ДРП и так пока не встречается пробел, когда встречается пробел - указатель на строку отправляется в стек, и потом все по новой. В конце я вывожу это дело на экран и освобождаю стек. 
Звучит не плохо, но на деле не фурычит. Отладчиком проверяю - вылетает в 
Код
if (isspace(buffer[i]))
 этом месте, а что не правильно - понять не могу. В общем, если есть возможность - растолкуйте, вот код: 
Код

#include<iostream>
#include<Windows.h>
#include<stack>
#include<iomanip>

int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    char buffer[300];
    char* pChar;
    bool is_space = false;

    std::stack<char*> myArray;
    std::cout << "Введите данные, отделенные пробелами: ";
    std::cin.getline(buffer, 300);

    for (int i = 0; i < strlen(buffer); i++)
    {
        
        if (isspace(buffer[i]))
        {
            if (!is_space)
            {
                myArray.push(pChar);
                pChar = 0;
                pChar = new char[30];
                is_space = true;
            }
            else continue;
        }
        else
        {
            pChar[i] = buffer[i];
            is_space = false;
        }
    }

    for (int i = 0; i < myArray.size(); i++)
    {
        std::cout << *myArray.top() << std::endl;
        delete myArray.top();
        myArray.pop();
    }

    return 0;
}

Спасибо!

Модератор: используй тег CODE только для кода. Для цитирования заданий или сообщений об ошибках лучше подходит QUOTE - не нарушается отображение форума на длинных строках.

Это сообщение отредактировал(а) bsa - 27.1.2015, 11:41
PM MAIL   Вверх
baldina
Дата 27.1.2015, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(lllJollyRogerlll @  26.1.2015,  23:15 Найти цитируемый пост)
вылетает в if (isspace(buffer[i]))

определите buffer как unsigned char

Цитата(lllJollyRogerlll @  26.1.2015,  23:15 Найти цитируемый пост)
              
                myArray.push(pChar); // чему тут равно pChar?
                pChar = 0; // зачем обнулять перед присваиванием?
                pChar = new char[30]; // проще сделать stack<string>


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

int x;
while (...)
  cin>>x;
  // и не нужно проверок isspace, cin сам разберется


Цитата(lllJollyRogerlll @  26.1.2015,  23:15 Найти цитируемый пост)
std::cin.getline(buffer, 300);

так обработается всего одна строка (до '\n'), а не весь вход

конечно, задача предполагает эффективное решение, которое заключается в считывании всего буфера в память (он ограничен по условию), и затем обработке (перевернув, или, что быстрее, с конца) без хранения промежуточных данных. в этом случае посимвольная обработка потребуется, но более изощренным способом

Добавлено @ 00:35
Цитата(baldina @  27.1.2015,  00:33 Найти цитируемый пост)
так обработается всего одна строка (до '\n'), а не весь вход

кстати, если строка длиннее буфера, то в конце буфера вы, скорее всего, получите обрывок числа...

Добавлено @ 00:41
lllJollyRogerlll, если вы все еще хотите обрабатывать ввод вручную, вводите не по строкам, а посимвольно
Код

while ((c=cin.get()) != EOF) {
  if (!isspace(с))
     // добавить c к строке
  else {
     if (/*строка не пустая*/) {
       // добавить строку
       // обнулить строку
     }
  }
}


Это сообщение отредактировал(а) baldina - 27.1.2015, 00:41
PM MAIL   Вверх
lllJollyRogerlll
Дата 27.1.2015, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(baldina @ 27.1.2015,  00:33)
              
                myArray.push(pChar); // чему тут равно pChar?

ну вот же, пока в строке не встречается пробел - в pChar записывается наш буфер, 
Код

 else
        {
            pChar[i] = buffer[i];
            is_space = false;
        }

а когда встречается пробел - ссылка на pChar(строку без пробелов) - передается в стек, потом освобождаем *pChar и создаем новую строку, с чистого листа, так сказать. Но если этот пробел идет после другого пробела,  is_space = true; - ничего не делаем, продолжаем цикл. Идея была такой... )
Код

 if (isspace(buffer[i]))
        {
            if (!is_space)
            {
                myArray.push(pChar);
                pChar = 0;
                pChar = new char[30];
                is_space = true;
            }
            else continue;
        }

Кстати, попробовал вариант с unsigned char, даже компилироваться не хочет.
PM MAIL   Вверх
baldina
Дата 27.1.2015, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(lllJollyRogerlll @  27.1.2015,  10:21 Найти цитируемый пост)
ну вот же, пока в строке не встречается пробел - в pChar записывается наш буфер, 

по крайней мере при первом вызове pChar может быть не инициализирован (если данные с пробела начинаются)

Цитата(lllJollyRogerlll @  27.1.2015,  10:21 Найти цитируемый пост)
даже компилироваться не хочет

да ну! http://ideone.com/kgnJ2y
и что говорит?
unsigned кстати можно поставить и в настройках компилятора.

Добавлено через 4 минуты и 4 секунды
lllJollyRogerlll, разделите свой код на части - хотя бы сделайте функцию чтения числа и функцию, пропускающую пробелы.
отлаживать будет проще.
PM MAIL   Вверх
lllJollyRogerlll
Дата 27.1.2015, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(baldina @ 27.1.2015,  10:39)

да ну! 
и что говорит?

http://dim.st/i66414.jpg
PM MAIL   Вверх
baldina
Дата 27.1.2015, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



lllJollyRogerlll, забейте на unsigned (совет был неудачный; идея сводится к тому, что результат isspace определен только если вход лежит в опр. диапазоне), тут не в нем дело.
программа падает, потому что вы не инициализируете данные.
a) если первый символ - пробел, то в массив запихивается неинициализируемый указатель. это неправильно, но в месте вызова пока еще не страшно. однако в последующих вызовах
Код

pChar[i] = buffer[i];

приводит к краху, т.к. i может принимать значения до 299, а размер по адресу pChar - 30
б) если первый символ не пробел, то производится запись в pChar[0], а pChar указывает неизвестно куда. тут все падает. 

PM MAIL   Вверх
lllJollyRogerlll
Дата 27.1.2015, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Переписал, теперь у меня вылетает исключение вообще по каким то непонятным причинам, вот в этом месте:
Код

void Iterate_and_delete(std::stack<char*>& myArray)
{
    if (myArray.empty()) { return; }
    else
    {
        for (int i = 0; i < myArray.size(); i++)
        {
            std::cout << myArray.top() << std::endl;
            delete myArray.top();
            myArray.pop();
        }
    }
}

Вот код полностью:
Код

#include<iostream>
#include<Windows.h>
#include<stack>
#include<iomanip>

std::stack<char*>& foo(const char* const buffer, std::stack<char*>& Array);
void Iterate_and_delete(std::stack<char*>& Array);

int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);

    char buffer[300];
    std::cout << "Введите данные, отделенные пробелами: ";
    std::cin.getline(buffer, 300);
    std::stack<char*> myArray;
    foo(buffer, myArray);
    Iterate_and_delete(myArray);
    
    return 0;
}

std::stack<char*>& foo(const char* const buffer, std::stack<char*>& myArray)
{
    bool is_space = false;
    char* ch = new char[300];
    int i = 0;
    int j = 0;
    for (i = 0, j = 0; i < strlen(buffer); i++)
    {
        if (isspace(buffer[i]))
        {
            if (!is_space)                                //прошлый символ - НЕ символ пробела?
            {
                ch[j] = '\0';                            //перед отправлением строки в стек, добавим символ завершения строки
                myArray.push(ch);                        
                ch = 0;
                ch = new char[300];
                j = 0;
                is_space = true;                        //прошлый символ - символ пробела!
            }
            else continue;                                //пробел не добавляем в стек
        }
        else
        {
            ch[j] = buffer[i];                            //копируем символы без пробелов из буфера во временную строку
            j++;
            is_space = false;
        }
    }
    ch[j] = '\0';
    myArray.push(ch);
    return myArray;
}

void Iterate_and_delete(std::stack<char*>& myArray)
{
    if (myArray.empty()) { return; }
    else
    {
        for (int i = 0; i < myArray.size(); i++)
        {
            std::cout << myArray.top() << std::endl;
            delete myArray.top();
            myArray.pop();
        }
    }
}

Дуристика какая то выходит вообще, не понимаю, для чего я это все написал, если это не поможет решению задачи. Но уже интересно тем не менее довести до конца хоть такой вариант, раз мне не дано решить задачу..
PM MAIL   Вверх
baldina
Дата 27.1.2015, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



у меня работает (правда выкинул windows.h)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


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

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


 




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


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

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