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


Автор: Vokunya 23.3.2010, 22:24
Поиск дает много чего по такого рода примерам: из, например, "hfuh7jho87jan23" вытащить все числа. Здесь все понятно.
Я стопорюсь с такой задачей:
Дана строка, содержащая слова, целые и вещественные числа. Переставить элементы строки так, чтобы сначала располагались целые числа, потом слова, а потом вещественные числа

Т.е., например: из "16.2 jdfjfsff 45 76jhsk 74.2" получить "45 jdfjfsff 76jhsk 16.2 74.2"
Мои умозаключения сводились к следующему:
1. Разбиваем строку при помощи strtok;
2. Как-то надо узнать что мы получили: целое или вещественное число, или просто слово... я придумал только такое, на мой взгляд, извращение:  smile 
Код

 oneWord = strtok (str, sprs);
    while (oneWord)
    {
        sscanf (oneWord, "%d", &tmpInt);
        sprintf (st, "%d", tmpInt);
        if (strlen (oneWord) == strlen (st))
...

т.е конвертнули слово в int, затем обратная операция, сравнили длину исходного слова и получившегося после конвертирования, если длины равны - то целое число ))
затем аналогичные действия для float, а то что осталось - просто слова 

Вопрос: есть другие решения или мой вариант вполне жизнеспособен?  smile 

Автор: djamshud 23.3.2010, 23:35
Самое верное на мой взгляд решение - написать элементарнейший парсер из десяти строк: разбить строку на поток лексем "слово", "целое", "дробное"" и потом расставить их в нужном порядке.

Автор: GoldFinch 23.3.2010, 23:56
используйте регулярные выражения.

Автор: Vokunya 24.3.2010, 00:02
Цитата

разбить строку на поток лексем "слово", "целое", "дробное"

я же и интересуюсь реализацией этой задачи  smile 

Цитата

используйте регулярные выражения

хм... даже не задумывался над этим  smile  завтра почитаю что-нибудь, т.к. совсем не имею опыта работы с регэкспами.

Автор: GoldFinch 24.3.2010, 09:09
хотя регулярки это пожалуй сложновато для такой задачи,
проще перебирать символы в слове и проверять их на "0"-"9" для целых и "." для вещественных

Автор: Vokunya 24.3.2010, 09:40
Цитата

проще перебирать символы в слове и проверять их на "0"-"9" для целых и "." для вещественных

вероятно да

Цитата

регулярки это пожалуй сложновато для такой задачи

но регулярки теперь уже интересны для саморазвития smile  может есть какие-нибудь ресурсы по регулярным выражениям в си, а то беглый просмотр гугла что-то вразумительных результатов не дал

эээ... я плохо смотрел или в стандарте С99 нет библиотеки для регэкспов?

Автор: Earnest 24.3.2010, 09:47
Я бы использовала функцию strtod (хотя не уверена, что она стандартная, но вроде да). Фокус в том, что она возвращает кроме смого числа указатель на место в строке, где ее парсинг закончился (т.е. где число закончилось). Оттуда и нужно начинать следующий парсинг. Можно вообще не париться с анализом - вернула указатель туда же откуда начала - стало быть не число. Но можно сначала сканировать и искать первый символ, который может быть числом. Самому написать, конечно, можно, но  коррекстно распарсить все варианты double - упаришься - все это E-04 и т.д.

Автор: xvr 24.3.2010, 10:03
Цитата(Earnest @ 24.3.2010,  09:47)
Я бы использовала функцию strtod

+1
Добавлю к рекомендации - использовать ее вместе с strtol. Если strtod отработала успешно, на это же слово запускается strtol. Если она вернет тот же поинтер в качестве конца парсинга, то число целое, иначе вещественное

Автор: GoldFinch 24.3.2010, 11:05
вместо С99 проще использовать язык более подходящий для задач связанных с обработкой текста %)

Автор: Earnest 24.3.2010, 12:20
xvr, точно, чтобы совсем самому не напрягаться smile 

Автор: azesmcar 24.3.2010, 12:49
Цитата(GoldFinch @  24.3.2010,  11:05 Найти цитируемый пост)
вместо С99 проще использовать язык более подходящий для задач связанных с обработкой текста %) 

дай угадаю.. питон? smile 

Автор: GoldFinch 24.3.2010, 13:11
azesmcar, не обязательно.
я бы сделал макрос для ворда или notepad++

Автор: Vokunya 24.3.2010, 13:27
Цитата

вместо С99 проще использовать язык более подходящий для задач связанных с обработкой текста %)

это же задание контрольной работы - только С99  smile 

Earnest, xvr сейчас на скорую руку набросал код с использованием strtod и strtol... вроде парсит  smile 
сейчас нет времени, но сегодня вечером/завтра отпишусь о результатах 

Автор: Vokunya 24.3.2010, 20:20
Итак, в результате наваял вот это:
Код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(int argc, char * argv [])
{

    //исходное предложение
    char   sentence [101];
    //слово, полученное в результате работы strtok
    char * word;
    //массив символов-разделителей 
    char seps[] = " ,";
    //вторые аргументы для strtod и strtol
    char * endptrDbl;
    char * endptrInt;

    //числа, полученные в результате работы strtod и strtol
    double dblWord;
    int intWord;

    //массивы для хранения уже обработанных word
    char   intPart [101] ="";
    char  dblPart [101] = "";
    char  charPart [101] = "";


    printf ("Input the sentence:\n");
    gets(sentence);

    word = strtok(sentence, seps);
    while (word)
    {
        //если преобразование удалось и преобразованы все символы, которые есть в word
        if ( (dblWord = strtod(word, &endptrDbl)) != 0 && (*endptrDbl == '\0'))
        {
            //над этим же word работает уже strtol
            intWord = strtol (word, &endptrInt, 10);
            //если strtol вернула тот же указатель конца парсига, что и strtod то число целое
            if (endptrDbl == endptrInt)
            {
                //записываем число в предназначенный массив
                strcat(intPart, word);
                strcat(intPart, " ");
            }
            //в противном случае число вещественное
            else
            {
                strcat (dblPart, word);
                strcat (dblPart, " ");
            }
        }
        // если же преобразование не удалось либо обработаны не все символы в word, то это слово
        else
        {
            strcat (charPart, word);
            strcat (charPart, " ");
        }

        word = strtok (NULL, seps);
    }

    sentence [0] = '\0';
    puts ("\nResult sentence:");
    strcat(sentence, intPart);
    strcat(sentence, charPart);
    strcat(sentence, dblPart);
    puts (sentence);

    return 0;
}



Наверняка что-нибудь можно подправить, буду благодарен за предложения!

Автор: Dov 26.3.2010, 13:11
Вот такое предложение:
Код
#define SIZE 101
#define CHARSET "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"

int main(int argc, char * argv [])
{    
    char   sentence[SIZE] = "";   // исходное предложение
    char   intPart [SIZE] = "";   // массивы для хранения уже обработанных word
    char   dblPart [SIZE] = "";    
    char   charPart[SIZE] = "";     
    char   seps[]         = " ,\n"; // массив символов-разделителей
    char * word;                  // слово, полученное в результате работы strtok
    
    printf ("Input the sentence:\n");
    fgets(sentence, SIZE, stdin);
    
    word = strtok(sentence, seps);
    while (word)
    {
        if (strpbrk(word, CHARSET))
            sprintf(charPart + strlen(charPart), "%s ", word);
        else if(strchr(word, '.'))
            sprintf(dblPart + strlen(dblPart), "%s ", word);
        else
            sprintf(intPart + strlen(intPart), "%s ", word);
        
        word = strtok (NULL, seps);
    }
    
    sprintf(sentence, "\nResult sentence:\n%s%s%s", intPart, charPart, dblPart);
    puts (sentence);
    
    return 0;
}

Автор: Vokunya 26.3.2010, 13:44
Вот и дождался еще одного варианта  smile 
Благодарю всех за обсуждение - вопрос решен.
Отдельное спасибо Earnest, xvr и Dov  smile 

Автор: xvr 26.3.2010, 15:40
Цитата(Dov @ 26.3.2010,  13:11)
Вот такое предложение:

Неа - 123e-5 не будет распознанно как double

Автор: Dov 26.3.2010, 16:02
Цитата(xvr @  26.3.2010,  14:40 Найти цитируемый пост)
Неа - 123e-5 не будет распознанно как double

Не вижу никаких трудностей для человека... с интеллектом прикрутить эту фичу к коду.   smile 
А ты видишь, xvr?   smile 

Автор: Earnest 26.3.2010, 18:14
... Человек с интеллектом должен искать способ сделать все наиболее простым способом... smile Мозги лучше использовать для серьезных задач. Говорят, ресурс не бесконечен; по крайней мере, жизнь уж точно... smile  smile  smile 

Автор: Dov 26.3.2010, 20:37
Цитата(Earnest @  26.3.2010,  17:14 Найти цитируемый пост)
... Человек с интеллектом должен искать способ сделать все наиболее простым способом... 

Трудно с этим не согласиться.  smile 
Цитата(Earnest @  26.3.2010,  17:14 Найти цитируемый пост)
Мозги лучше использовать для серьезных задач. 

Мозги лучше использовать всегда.  smile 
Цитата(Earnest @  26.3.2010,  17:14 Найти цитируемый пост)
Говорят, ресурс не бесконечен; по крайней мере, жизнь уж точно...

Про ресурс не скажу, ибо не знаю. А, вот, по поводу жизни,  с прискорбием могу это подтвердить...  smile 

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