Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [C++] Разбить строку на числа и символы


Автор: m0zg 20.4.2008, 20:55
Задача такая:
Из входного потока вводится произвольное число строк, состоящих из последовательности десятичных многоразрядных чисел и слов, которые могут быть не разделены, либо разделены один/несколькими пробелами/знаками табуляции. Длина строки не превышает 80 символов. Конец ввода определяется концом файла.

При обработке строк сформитровать 2 новые, поместив в первую числа, во втроую слова. Числа и слова должны быть разделены только один пробелом. Полученные строки вывести на экран.


P.S. Ввод нужно сделать с помощью cin.getline(куда, максимум_сколько). Библиотечные функции обработки строк не использовать.

Вопрос такой для начала. Как в функции различать что есть символ, что есть цифра? И раскидать их по разным массивам.

Автор: piritus 20.4.2008, 22:00
Код

if (chr >= 'A' && chr <= 'Z'){...}


или если строка:
Код

int i;
for(i=0;i<strlen(chr);i++)
if (chr[i] >= 'A' && chr[i] <= 'Z'){...}

так же с цифрами

Автор: m0zg 20.4.2008, 22:11
нельзя использовать функции из string.h

Автор: Evjeny 20.4.2008, 23:06
Цитата(m0zg @  20.4.2008,  20:55 Найти цитируемый пост)
Вопрос такой для начала. Как в функции различать что есть символ, что есть цифра? И раскидать их по разным массивам.


Извиняюсь, че-то я ошибся, надо вот так

Код

    char str[20];

    char ch[20]; //массив для символов
    char num[20]; //массив для цифр

    cout << "Enter string: ";

    cin.getline(str, 20);

    int i = 0, j = 0,k = 0;

    while(str[i])
    {
        if((str[i]>='A'&&str[i]<='Z')||(str[i]>='a'&&str[i]<='z'))
            ch[j++] = str[i];

        if(str[i]>='0'&&str[i]<='9')
            num[k++] = str[i];

        i++;
    }

Автор: m0zg 24.4.2008, 01:33
Я тут пишу эту программку и возникла проблемка. Почему функция filter не вырезает символы-разделители?

Код
#include <iostream>

using namespace std;
const int SIZE = 80;

void form(char *in, char *out);
void filter(char *from, char *to);

int main(){
    char buf[SIZE], outbuf[SIZE], tmp[SIZE];
    while(cout << "Enter string: ", cin.getline(tmp, SIZE)){
        filter(tmp, buf);
        //form(buf, outbuf);
        //cout << "Result string: " << outbuf << endl;
        cout << "Result string: " << buf << endl;
    }
}

void form(char *in, char *out){
    int i = 0, j = 0, k = 0;
    int num[80];
    char chr[80];
    while(in[i])
    {
        if((in[i]>='A' && in[i]<='Z')||(in[i]>='a' && in[i]<='z')){
            chr[j++] = in[i];
        }
        if(in[i]>='0' && in[i]<='9'){
            num[k++] = in[i];
        }
        i++;
    }
}

void filter(char *from, char *to){
    int i = 0, j = 0;
    while(from[i]!='\0'){
        if(from[i]!=' ' && from[i]!='\t'){
            to[j++] = from[i];
        }
        if(from[i+1]==' ' || from[i+1]=='\t' || from[i+1]=='\0'){
            to[j++] = ' ';
        }
        i++;
    }
    to[i-1] = '\0';
}

Автор: piritus 24.4.2008, 07:40
Код

void filter(char *from,char *to){
int i=0,j=0;
bool flag=0;

    while(from[i]!='\0'){
        if(from[i]==' ' || from[i]=='\t')
            if(flag==0){
              to[j]=' ';
              j++;
              flag=1;
            }

        if(from[i]!=' ' && from[i]!='\t'){
            to[j]=from[i];
            j++;
            flag=0;
        }
        i++;
    }
    to[j]='\0';
}

Автор: m0zg 3.5.2008, 21:19
Вот, что у меня тут получается, но какой-то непонятный для меня глюк после ввода происходит. Когда после Enter string я нажимаю на enter, даже ничего не вводя, выводиться какая-то кракозябра. А если ввожу сиволы и цифры, то тоже хрень какая-то происходит. Мне препод подсказывал, подсказывал, так я правильно и не смог написать. Или может что-то не дописал? Я вообще с этими указателями не очень дружу )). В чем тут может быть дело?

Код

#include <iostream>

using namespace std;
const int SIZE = 80;

void form(char *in, char *outDigits, char *outLetters);
char *skip(char *str);
char *copyDigits(char *&from, char *to);
char *copyLetters(char *&from, char *to);

int main(){
    char buf[SIZE], outDigits[SIZE], outLetters[SIZE];
    while(cout << "Enter string: ", cin.getline(buf, SIZE)){
        form(buf, outDigits, outLetters);
        cout << "Result string: " << outDigits << endl << outLetters << endl;
    }
}

void form(char *in, char *outDigits, char *outLetters){
    while( *(in = skip(in)) ){
        if(*in >= '0' && *in <= '9'){
            outDigits = copyDigits(in, outDigits);
        } else {
            outLetters = copyLetters(in, outLetters);
        }
    }
}

// в этой функции пропускаем все, кроме букв и цифр
char *skip(char *str)
{
    while(*str && (*str<'0' && *str>'9' || *str<'A' && *str>'Z' || *str<'a' && *str>'z')){
        str++;
    }
    return str;
}

//формирую строку с цифрами
char *copyDigits(char *&from, char *to)
{
    while(*from >= '0' && *from <= '9'){
        *to++ = *from++;
    }
    *to++ = ' ';
    *to = '\0';
    return to;
}

//строку с буквами
char *copyLetters(char *&from, char *to)
{
    while(*from >= 'A' && *from <= 'Z' && *from >= 'a' && *from <= 'z'){
        *to++ = *from++;
    }
    *to++ = ' ';
    *to = '\0';
    return to;
}

Автор: m0zg 10.5.2008, 14:51
Правильный вариант. Проверенный и зачтенный smile

Код

#include <iostream>

using namespace std;
const int SIZE = 80;

void form(char *in, char *outDigits, char *outLetters);
char *skip(char *str);
char *copyDigits(char *&from, char *to);
char *copyLetters(char *&from, char *to);

int main(){
    char buf[SIZE], outDigits[SIZE], outLetters[SIZE];
    while(cout << "Enter string: ", cin.getline(buf, SIZE)){
        form(buf, outDigits, outLetters);
        cout << "Result string: " << outDigits << endl << outLetters << endl;
    }
}

void form(char *in, char *outDigits, char *outLetters){
    while( *(in = skip(in)) ){
        if(*in >= '0' && *in <= '9'){
            outDigits = copyDigits(in, outDigits);
        } else {
            outLetters = copyLetters(in, outLetters);
        }
    }
    *outDigits = '\0';
    *outLetters = '\0';
}

char *skip(char *str)
{
    while(*str && ((*str<'0' || *str>'9') && (*str<'A' || *str>'Z') && (*str<'a' || *str>'z'))){
        str++;
    }
    return str;
}

char *copyDigits(char *&from, char *to)
{
    while(*from >= '0' && *from <= '9'){
        *to++ = *from++;
    }
    *to++ = ' ';
    return to;
}

char *copyLetters(char *&from, char *to)
{
    while(*from >= 'A' && *from <= 'Z' || *from >= 'a' && *from <= 'z'){
        *to++ = *from++;
    }
    *to++ = ' ';
    return to;
}



Теперь нужно эту прогу переделать со списками и динамической памятью.
Каждая строка представлена списком; первое поле элемента списка - символ строки; второе - указатель на следующий элемент списка или NULL в конце списка. Ввод по такой же схеме, пока не конце - cin.getline(); сформировать список; обработать список в соответствии с условием задачи; вывести результат и освободить память, выделенную под список.

Автор: m0zg 11.5.2008, 19:02
Народ, подскажите в чем проблема и где? Я тут написал сам толком не понимаю что сделал  :blink:  После ввода строки с буквами и цифрами (по заданию, оно написано выше) програма вылетает с ошибкой сегментации.

Код

#include <iostream>

using namespace std;
const int SIZE = 80;

struct Item {
    char s;
    Item *next;
};

Item *erase(Item *&str);
Item *createList(char *str);
void *form(Item *in, Item *outDigits, Item *outLetters);
Item *skip(Item *str);
Item *copyDigits(Item *&from, Item *to);
Item *copyLetters(Item *&from, Item *to);
void showDigits(Item *outDigits);
void showLetters(Item *outLetters);

int main(){
    Item *list = NULL, *outDigits = NULL, *outLetters = NULL;
    char buf[SIZE];
    while(cout << "Enter string: ", cin.getline(buf, SIZE)){
        list = createList(buf);
        form(list, outDigits, outLetters);
        cout << "Result string: ";
        showDigits(outDigits);
        cout << endl;
        showLetters(outLetters);
        cout << endl;
        erase(outDigits);
        erase(outLetters);
        erase(list);
    }
}

void *form(Item *in, Item *outDigits, Item *outLetters){
    while(in = skip(in)){
        if(in->s >= '0' && in->s <= '9'){
            outDigits = copyDigits(in, outDigits);
        } else {
            outLetters = copyLetters(in, outLetters);
        }
    }
}

Item *skip(Item *str)
{
    while(str && ((str->s < '0' || str->s > '9') && (str->s < 'A' || str->s > 'Z') && (str->s < 'a' || str->s > 'z'))){
        str->s = str->s++;
    }
    return str;
}

void showDigits(Item *outDigits){
    Item *k = outDigits;
    while(k){
        cout << k->s;
        k = k->next;
    }
    cout << " ";
}

void showLetters(Item *outLetters){
    Item *k = outLetters;
    while(k){
        cout << k->s;
        k = k->next;
    }
    cout << " ";
}

Item *createList(char *str){
    Item *begin = NULL, *end = NULL;
    if(str == ""){
        return NULL;
    }
    while(*str){
        Item *k = new Item;
        k->s = *str++;
        k->next = NULL;
        if(begin == NULL){
            begin = k;
        } else {
            end->next = k;
        }
        end = k;
    }
    return begin;
}

Item *erase(Item *&str){
    Item *tmp;
    while(str){
        tmp = str;
        str = str->next;
        delete tmp;
    }
    return NULL;
}

Item *copyDigits(Item *&from, Item *to)
{
    Item *last = from;
    while(from->s >= '0' && from->s <= '9'){
        Item *k = new Item;
        k->s = to->s;
        k->next = NULL;
        if(last == NULL){
            from = k;
        } else {
            last->next = k;
        }
        last = k;
        to = to->next;
    }
//    to->s++ = ' ';
    return to;
}

Item *copyLetters(Item *&from, Item *to)
{
    Item *last = from;
    while(from->s >= 'A' && from->s <= 'Z' || from->s >= 'a' && from->s <= 'z'){
        Item *k = new Item;
        k->s = to->s;
        k->next = NULL;
        if(last == NULL){
            from = k;
        } else {
            last->next = k;
        }
        last = k;
        to = to->next;
    }
    //to->s++ = ' ';
    return to;
}


Автор: m0zg 16.5.2008, 01:23
Народ, помогите отладить программу  smile .
Ввожу строку, например: erttt3456345fhfsgh rth  5673567 356.

А результат: 3456345 0 0 05673567 0356
erttt fhfsgh rth

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

Код

#include <iostream>

using namespace std;
const int SIZE = 80;

struct Item {
    char s;
    Item *next;
};

Item *erase(Item *&str);
Item *createList(char *str);
void *form(Item *in, Item *&outDigits, Item *&outLetters);
Item *skip(Item *str);
Item *copyDigits(Item *&from, Item *&to);
Item *copyLetters(Item *&from, Item *&to);
void showItem(Item *list);

int main(){
    Item *list = NULL, *outDigits = NULL, *outLetters = NULL;
    char buf[SIZE];
    while(cout << "Enter string: ", cin.getline(buf, SIZE)){
        list = createList(buf);
        form(list, outDigits, outLetters);
        cout << "Result string: ";
        showItem(outDigits);
        cout << endl;
        showItem(outLetters);
        cout << endl;
        erase(outDigits);
        erase(outLetters);
        erase(list);
    }
}

//создаю список из введенной строки
Item *createList(char *str){
    Item *begin = NULL, *end = NULL;
    if(str == ""){
        return NULL;
    }
    while(*str){
        Item *k = new Item;
        k->s = *str++;
        k->next = NULL;
        if(begin == NULL){
            begin = k;
        } else {
            end->next = k;
        }
        end = k;
    }
    return begin;
}

//создаю головные элементы, фильтрую и раскидываю по соответствующим спискам
void *form(Item *in, Item *&outDigits, Item *&outLetters){
    Item headDigits = {' ', NULL}, headLetters = {' ', NULL};
    outDigits = &headDigits;
    outLetters = &headLetters;
    while(in = skip(in)){
        if(in->s >= '0' && in->s <= '9'){
            outDigits = copyDigits(in, outDigits);
        } else {
            outLetters = copyLetters(in, outLetters);
        }
    }
    outDigits = headDigits.next;
    outLetters = headLetters.next;
}

//фильтр
Item *skip(Item *str)
{
    while(str && ((str->s < '0' || str->s > '9') && (str->s < 'A' || str->s > 'Z') && (str->s < 'a' || str->s > 'z'))){
        str->s = str->s++;
    }
    return str;
}

//создаем список цифр
Item *copyDigits(Item *&from, Item *&to)
{
    while(from!=NULL && (from->s >= '0' && from->s <= '9')){
        Item *k = new Item;
        k->s = from->s;
        k->next = NULL;
        to->next = k;
        to = k;
        from = from->next;
    }
    to->next = new Item;
    to = to->next;
    to->s = ' ';
    to->next = NULL;
    return to;
}

//создаем список букв
Item *copyLetters(Item *&from, Item *&to){
    while(from!=NULL && (from->s >= 'A' && from->s <= 'Z' || from->s >= 'a' && from->s <= 'z')){
        Item *k = new Item;
        k->s = from->s;
        k->next = NULL;
        to->next = k;
        to = k;
        from = from->next;
    }
    to->next = new Item;
    to = to->next;
    to->s = ' ';
    to->next = NULL;
    return to;
}

//выводим список
void showItem(Item *list){
    while(list){
        cout << list->s;
        list = list->next;
    }
}

//очищаем память
Item *erase(Item *&str){
    Item *tmp;
    while(str){
        tmp = str;
        str = str->next;
        delete tmp;
    }
    return NULL;
}


Автор: Evjeny 16.5.2008, 11:48
В функции
Код

Item *skip(Item *str);

исправь строку
Код

str->s = str->s++;

на
Код

str = str->next;

Автор: m0zg 16.5.2008, 12:19
Блиин, точно! Спасибо большое  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)