LINUX.ORG.RU

C++ распарсить строку разделенную пробелами

 


0

1

Задача такая (не знаю как проще объяснить, так что..): есть строка (преобразованный вектор) вида «1.0 45.0 20.0», так вот, ее нужно преобразовать опять в float. Как это сделать ясно, не ясно как распарсить каждое из чисел через пробел в отдельную переменную, что бы на выходе получить float x(1.0),y(45.0),z(20.0) ?



Последнее исправление: raycast (всего исправлений: 1)

в ansi c: strsep / strtok и atof, в плюсах может что-то другое есть.

beastie ★★★★★
()
Ответ на: комментарий от note173

Но вообще это плохо. Лучше парсить вручную и обрабатывать ошибки.

#if !defined(__cplusplus)
#error You should use C++ compiler to parse string with my superiour method
#endif

#if defined(_MSC_VER)
#error You should use qualitative C++ compiler to parse string with my superiour method
#endif

void readVec(const char *string, float &x, float &y, float &z)
{
    assert(string && "String cannot be nullptr");
    assert(isdigit(*string) || (*string == '.') && "String should start with digit or dot");
    const char *temp = string;
    const float *coords[] = {&x, &y, &z};
    for (int i = 0; i < 3; ++i, ++coords) {
        float *coord = coords[i];
        float num = 0.0;
        bool didPassedDot = false;
        float tailFactor = 1.0;
        while (isdigit(*temp) || *temp == '.') {
            if (*temp == '.') {
                assert(!didPassedDot && "One float value should not have two dots");
                didPassedDot = true;
            }
            else {
                if (didPassedDot) {
                    num *= 10;
                    num += (*temp - '0');
                } else {
                    tailFactor *= 0.1;
                    num += (*temp - '0') * tailFactor;
                }
            }
            ++temp;
        }
        if (*temp == '\0') {
            assert(i == 2 && "String should contain three floats");
            *coord = num;
            break;
        } else {
            assert(*temp == ' ' && "Floats should be splitted with exactly one space!");
            assert(i != 2 && "String cannot have any character after third float");
            *coord = num;
            ++temp;
            assert((isdigit(*temp) || *temp == '.') && "Floats should be splitted with exactly one space!");
            continue;
        }
    }
}

Можно assert заменить исключениями, по вкусу.

quiet_readonly ★★★★
()
Ответ на: комментарий от quiet_readonly

++i, ++coords
float *coord = coords

бага

while (isdigit(*temp) || *temp == '.')

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

wota ★★
()
Ответ на: комментарий от quiet_readonly

А ещё надо писать 2 == i, а не i == 2 - это ещё на первом курсе сиплюсплюсоведческого факультета любого аграрно-промышленного института проходят.

kiverattes ★☆
()
Ответ на: комментарий от quiet_readonly

Написал так:

std::string pos,vx,vy,vz;
    pos = vecxEditBox->getCaption();
    sscanf(pos.c_str(), "%f %f %f", &vx, &vy, &vz);
    vecx = atof(vx.c_str());vecy = atof(vy.c_str());vecz = atof(vz.c_str());
    mNode->setPosition(Ogre::Vector3(vecx,vecy,vecz));
При компеляции валятся предупреждения и приложение при запуске крешится:
../Game.cpp:331:50: предупреждение: format «%f» expects argument of type «float*», but argument 3 has type «std::string* {aka std::basic_string<char>*}» [-Wformat]
../Game.cpp:331:50: предупреждение: format «%f» expects argument of type «float*», but argument 4 has type «std::string* {aka std::basic_string<char>*}» [-Wformat]
../Game.cpp:331:50: предупреждение: format «%f» expects argument of type «float*», but argument 5 has type «std::string* {aka std::basic_string<char>*}» [-Wformat]

raycast
() автор топика
Ответ на: комментарий от raycast

format «%f» expects argument of type «float*», but argument 3 has type «std::string* {aka std::basic_string<char>*}»

Мало того, что ты ман не прочитал, так ты вообще читать не умеешь?

geekless ★★
()
Ответ на: комментарий от geekless

stringstream( «1.1 2.2 3.3») >> x >> y >> z;

а то что он написал на любом ЯП можно соорудить

wota ★★
()
Ответ на: комментарий от raycast

^при замене на %s вместо %f, тоже самое

raycast
() автор топика
Ответ на: комментарий от kiverattes

А ещё надо писать 2 == i, а не i == 2 - это ещё на первом курсе сиплюсплюсоведческого факультета любого аграрно-промышленного института проходят.

Щито это за бред? Так на несколько наносекунд быстрее, да?

HerrWeigel ★★★★
()
#include <stdio.h>

#include <stdlib.h>
#include <ctype.h>

int main() {
    const char *text = "1.0 45.0 20.0";
    char *p;
    do {                                                                             
        double val = strtod(text, &p);                                               
        printf("(%g)\n", val);                                                       
    } while (isspace(*(text = p)));                                                  
    return 0;                                                                        
}

валидация за тобой ;)

arsi ★★★★★
()
Ответ на: комментарий от HerrWeigel

Так на несколько наносекунд быстрее, да?

так пишут люди, не осилившие чтение варнингов, чтоб вдруг не написать:

if( i = 2 )

wota ★★
()
Ответ на: комментарий от HerrWeigel

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

При записи 2 = i будет ошибка при компиляции.

«Быстрее» тут ни при чём.

DeVliegendeHollander ★★
()
Ответ на: комментарий от wota

так пишут люди, не осилившие чтение варнингов, чтоб вдруг не написать:

if( i = 2 )

А, понятно. Полный провал.

HerrWeigel ★★★★
()
Ответ на: комментарий от HerrWeigel

Но меня такие приёмчики только смешат. Куда человек лезет, если не в силах освоить синтаксис простейшего условного выражения? Пусть в офис-менеджеры идёт. :)

DeVliegendeHollander ★★
()
Ответ на: комментарий от DeVliegendeHollander

Но меня такие приёмчики только смешат. Куда человек лезет, если не в силах освоить синтаксис простейшего условного выражения? Пусть в офис-менеджеры идёт. :)

Ну я и говорю: беда.

HerrWeigel ★★★★
()
Ответ на: комментарий от wota

> котэ считает, что валидация и неправильный алгоритм - разные вещи

белка считает, что котэ, считающий отсутствие проверки результата разбора неправильным *алгоритмом*, не внушает доверия ;)

arsi ★★★★★
()
Ответ на: комментарий от arsi

белка считает, что котэ, считающий отсутствие проверки результата разбора неправильным *алгоритмом*, не внушает доверия ;)

белка просто не понимает, что «проверки результата разбора» не сделает код рабочим

wota ★★
()
Ответ на: комментарий от wota

> белка просто не понимает, что «проверки результата разбора» не сделает код рабочим

объясни белке :)

arsi ★★★★★
()
Ответ на: комментарий от arsi

объясни белке :)

очень просто - если полагать, что правильный текст должен быть 1:1 как у ТС, то твой алгоритм будет пропускать \n, например, что будет ошибкой, т.к. это могут уже быть другие данные на следующей строке, если не быть такими педантами, то следует допустить пропуск whitespace вообще, а у тебя этого нет

wota ★★
()
Ответ на: комментарий от kiverattes

А ещё надо писать 2 == i, а не i == 2 - это ещё на первом курсе сиплюсплюсоведческого факультета любого аграрно-промышленного института проходят.

А это тема для срача, и вообще индивидуально и относительно. В некоторых конторах вообще Yoda conditions явно запрещают в документах по стилю кода.
Мне лично нравится

Harald ★★★★★
()
Ответ на: комментарий от minakov

1) Я не понял, откуда возник этот вопрос. Речь шла о форме записи условного выражения в конструкциях if и в циклах.

2) Я на С обычно парсингом текстов не занимаюсь. В С мне *scanf хватает (если говорить о задачах типа поставленной в ОП).

3) Вообще-то и для С есть библиотеки для работы с регэкспами. В конце концов можно и ими воспользоваться.

DeVliegendeHollander ★★
()
Ответ на: комментарий от wota

> если полагать, что правильный текст должен быть 1:1 как у ТС, то твой алгоритм будет пропускать \n

если текст будет 1:1 как у ТС, то в нём элементарно не будет \n :)

> если не быть такими педантами, то следует допустить пропуск whitespace вообще, а у тебя этого нет

4.2.

arsi ★★★★★
()
Ответ на: комментарий от arsi

если текст будет 1:1 как у ТС, то в нём элементарно не будет \n :)

объясню популярно - твой парсер _не должен_ пропускать \n, т.к. «правильный текст должен быть 1:1 как у ТС» != «программа работает в идеальном мире, все входные данные 100% корректные»

4.2.

сейчас 4.2 пишут уже без всякого повода..., вот тебе пример - данные из stdin или файла (конфиг, csv и пр. )

wota ★★
()
Ответ на: комментарий от wota

> объясню популярно - твой парсер _не должен_ пропускать \n, т.к. «правильный текст должен быть 1:1 как у ТС» != «программа работает в идеальном мире, все входные данные 100% корректные»

э... чё? о_О

> сейчас 4.2 пишут уже без всякого повода...

продолжай наблюдения.

> вот тебе пример - данные из stdin или файла (конфиг, csv и пр. )

какое отношение этот поток сознания имеет к твоему [ошибочному] утверждению, что в примере не пропускаются пробелы?

давай ты пойдёшь проспишься, а завтра продолжим, а то ты сейчас несёшь эпический бред.

arsi ★★★★★
()
Ответ на: комментарий от arsi

э... чё? о_О

видно даже популярно ты не понимаешь, извини, но я не знаю как еще объяснить, что == ' ' и isspace не идентичны друг другу, и в программе дадут разное поведение при разборе текста

имеет к твоему [ошибочному] утверждению, что в примере не пропускаются пробелы?

http://en.wikipedia.org/wiki/Whitespace_character

просветись немного, а потом еще раз подумай над фразой «пропуск whitespace вообще», если не додумаешься, то вот тебе пример:

" 1.1 \t 2.2\t3.3"

давай ты пойдёшь проспишься, а завтра продолжим, а то ты сейчас несёшь эпический бред.

просто ты очень тупишь, а я пытаюсь тебе объяснить так, чтоб ты понял, но не получается пока

wota ★★
()
Ответ на: комментарий от Harald

Если понимать, зачем это - нет срача. Сраться о том, нужна ли безопасность? Круто, давайте сраться о том, нужны ли пароли, замки и изолента во вселенной.

kiverattes ★☆
()
Ответ на: комментарий от wota

> ' ' и isspace не идентичны друг другу

к чему это?

> просветись немного, а потом еще раз подумай над фразой «пропуск whitespace вообще», если не додумаешься, то вот тебе пример:

> " 1.1 \t 2.2\t3.3"

к чему это?

> просто ты очень тупишь

у меня для тебя плохие новости ;)

arsi ★★★★★
()

у тебя дробная часть всегда 0?

Dron ★★★★★
()
Ответ на: комментарий от arsi

к чему это?
к чему это?
у меня для тебя плохие новости ;)

да, я уже понял, что тебе что-то объяснять бесполезно

wota ★★
()
Ответ на: комментарий от wota

> да, я уже понял, что тебе что-то объяснять бесполезно

не дорос ты ещё кому-нибудь что-нибудь объяснять ;) да и что ты можешь объяснить, если даже манов не осилил по функциям, к которым придираешься :)

arsi ★★★★★
()
Ответ на: комментарий от geekless

судя по количеству его постов за последние 3 дня, то автор вообще не думает.

frozenix ★★★
()
Ответ на: комментарий от arsi

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

wota ★★
()
Ответ на: комментарий от note173
std::stringstream stream(str);
flost x, y, z;
stream >> x >> y >> z;

if(stream.fail())
{
  // Неправильный формат строки
  std::cerr << "Err" << std::endl;
}
frozenix ★★★
()
Ответ на: комментарий от wota

Коте прав. Надо чтобы программа выдавала нужный результат, при любых входных данных. Для этого даже различные тесты пишут.

drdim
()
Ответ на: комментарий от drdim

> Надо чтобы программа выдавала нужный результат, при любых входных данных.

ты хоть понял, что сказал? :) нужный результат — 15, входные данные — %#@%^&!*, твои действия? :)

arsi ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.