Multistring в памяти
От: Serg-o-65535 Россия  
Дата: 08.11.06 20:52
Оценка:
Уважаемые господа, помогите новичку решить тревиальную задачу
Поиск по форумам/Google дал мне много ответов, но они либо не совсем то, что нужно, либо еще больше запутали.
Я плавно мигрирую с Delphi на С++, и многие вещи для меня пока не очевидны, хотя Герберт Шилдт уже снитнся

Вопрос такой:
У меня есть в памяти целиком содержимое текстового файла (классиеский мультитринг).
На начало этого блока есть укзатель вида void *p. Известна длина этого блока в байтах.
Задача- в цикле перебрать все строки этого блока.
Сейчас я иду циклом по всему боку, плюсуя в токен очередной символ, пока не дойду до '\0', и тогда это очередная строка.

Но сдаётся мне что это извращение Наверняка какой-нибудь sscanf это умеет быстрее и надёжнее.
Подскажите, пожалуйста, в какую сторону копть.

Заранее спасибо.
С уважением, Троицкий Сергей.
Re: Multistring в памяти
От: Аноним  
Дата: 08.11.06 21:42
Оценка:
Здравствуйте, Serg-o-65535, Вы писали:

SO6>Уважаемые господа, помогите новичку решить тревиальную задачу

SO6>Поиск по форумам/Google дал мне много ответов, но они либо не совсем то, что нужно, либо еще больше запутали.
SO6>Я плавно мигрирую с Delphi на С++, и многие вещи для меня пока не очевидны, хотя Герберт Шилдт уже снитнся

SO6>Вопрос такой:

SO6>У меня есть в памяти целиком содержимое текстового файла (классиеский мультитринг).
SO6>На начало этого блока есть укзатель вида void *p. Известна длина этого блока в байтах.
SO6>Задача- в цикле перебрать все строки этого блока.
SO6>Сейчас я иду циклом по всему боку, плюсуя в токен очередной символ, пока не дойду до '\0', и тогда это очередная строка.

SO6>Но сдаётся мне что это извращение Наверняка какой-нибудь sscanf это умеет быстрее и надёжнее.

SO6>Подскажите, пожалуйста, в какую сторону копть.

SO6>Заранее спасибо.

SO6>С уважением, Троицкий Сергей.

Можно, например, так

#include <string>
#include <vector>
#include <sstream>

using namespace std;

void *p = "Hello,\n world!";    // Исходные данные
int text_length = 15;

vector<string> lines;   // Этот вектор будет содержать строки, встретившиеся в тексте

// Для разбиения используем строковые потоки
string text(static_cast<char *>(p),text_length), line;
istringstream line_splitter(text);

while(getline(line_splitter,line)) // Читаем очередную строку и сохраняем её в векторе
{
    lines.push_back(line);
}
Re: Multistring в памяти
От: dr.Chaos Россия Украшения HandMade
Дата: 09.11.06 08:43
Оценка: -1
Здравствуйте, Serg-o-65535, Вы писали:

SO6>Уважаемые господа, помогите новичку решить тревиальную задачу

SO6>Поиск по форумам/Google дал мне много ответов, но они либо не совсем то, что нужно, либо еще больше запутали.
SO6>Я плавно мигрирую с Delphi на С++, и многие вещи для меня пока не очевидны, хотя Герберт Шилдт уже снитнся

SO6>Вопрос такой:

SO6>У меня есть в памяти целиком содержимое текстового файла (классиеский мультитринг).
SO6>На начало этого блока есть укзатель вида void *p. Известна длина этого блока в байтах.
SO6>Задача- в цикле перебрать все строки этого блока.
SO6>Сейчас я иду циклом по всему боку, плюсуя в токен очередной символ, пока не дойду до '\0', и тогда это очередная строка.

SO6>Но сдаётся мне что это извращение Наверняка какой-нибудь sscanf это умеет быстрее и надёжнее.

SO6>Подскажите, пожалуйста, в какую сторону копть.

SO6>Заранее спасибо.

SO6>С уважением, Троицкий Сергей.

Перебрать с какой целью:
Посчитать количество?
Обработать каждую, не изменяя?
Получить массив строк?

В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL.

Удачи.
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re: Multistring в памяти
От: Кодт Россия  
Дата: 09.11.06 09:18
Оценка:
Здравствуйте, Serg-o-65535, Вы писали:

SO6>Вопрос такой:

SO6>У меня есть в памяти целиком содержимое текстового файла (классиеский мультитринг).

Ну не совсем классический.
1) В мультистринге разделители — NUL, а в тексте — LF либо CR/LF
2) Элементы мультистринга — непустые строки, конец мультистринга — пустая строка (т.е. <last_string> NUL NUL); а в тексте пустые строки (LF LF) могут встречаться

(NUL — обозначение нулевого символа в ASCII, не путать с NULL — нулевым указателем в С/С++).

SO6>На начало этого блока есть укзатель вида void *p. Известна длина этого блока в байтах.


Лучше уж char* или, если это UTF-16/UCS-2, то WCHAR*.

SO6>Задача- в цикле перебрать все строки этого блока.

SO6>Сейчас я иду циклом по всему боку, плюсуя в токен очередной символ, пока не дойду до '\0', и тогда это очередная строка.

Поиск LF — это strchr(str, '\n')
Поиск NUL — это strlen(str)

SO6>Но сдаётся мне что это извращение Наверняка какой-нибудь sscanf это умеет быстрее и надёжнее.


sscanf это сделает заведомо медленнее и извращённее.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: Multistring в памяти
От: Serg-o-65535 Россия  
Дата: 09.11.06 09:49
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Ну не совсем классический.

К>1) В мультистринге разделители — NUL, а в тексте — LF либо CR/LF
К>2) Элементы мультистринга — непустые строки, конец мультистринга — пустая строка (т.е. <last_string> NUL NUL); а в тексте пустые строки (LF LF) могут встречаться

Спасибо за уточнение, совсем упустил из виду.
В моём случае был именно мультистринг — пустых строк нет, только последняя, разделители '\n'

К> Лучше уж char* или, если это UTF-16/UCS-2, то WCHAR*.

Ко мне этот указатель приходит именно в виде void* из чужой функции, но ему я делаю char *begin = (char*)p;

К>sscanf это сделает заведомо медленнее и извращённее.

Спасибо большое за информацию, особенно касающуюся поиска \n — это тоже вскоре понадобится.

А конкретно мою задачу с вашей помошью решил так:

char *begin = (char*)p; // указатель на начло блока данных,
char *end = begin +size; // указатель на конец блока данных,
while(begin != end) {
strcpy(token, begin); // в token очередная строка
begin += strlen(begin) + 1;
} // while

Большое спасибо!
С уваженеим, Троицкий Сергей.
Re[2]: Multistring в памяти
От: Serg-o-65535 Россия  
Дата: 09.11.06 09:53
Оценка:
Re[2]: Multistring в памяти
От: Serg-o-65535
Дата: 09.11.06 12:49

Здравствуйте, Кодт, Вы писали:

К>Ну не совсем классический.

К>1) В мультистринге разделители — NUL, а в тексте — LF либо CR/LF
К>2) Элементы мультистринга — непустые строки, конец мультистринга — пустая строка (т.е. <last_string> NUL NUL); а в тексте пустые строки (LF LF) могут встречаться

Спасибо за уточнение, совсем упустил из виду.
В моём случае был именно мультистринг — пустых строк нет, только последняя, разделители нули
(по ошибке написал сначала '\n')

К> Лучше уж char* или, если это UTF-16/UCS-2, то WCHAR*.

Ко мне этот указатель приходит именно в виде void* из чужой функции, но ему я делаю char *begin = (char*)p;

К>sscanf это сделает заведомо медленнее и извращённее.

Спасибо большое за информацию, особенно касающуюся поиска \n — это тоже вскоре понадобится.

А конкретно мою задачу с вашей помошью решил так:

char *begin = (char*)p; // указатель на начло блока данных,
char *end = begin +size; // указатель на конец блока данных,
while(begin != end) {
strcpy(token, begin); // в token очередная строка
begin += strlen(begin) + 1;
} // while

Большое спасибо!
С уваженеим, Троицкий Сергей.
Re[2]: Multistring в памяти
От: Serg-o-65535 Россия  
Дата: 09.11.06 09:56
Оценка:
Здравствуйте, dr.Chaos, Вы писали:

DC>Перебрать с какой целью:

DC>Посчитать количество?
DC>Обработать каждую, не изменяя?
DC>Получить массив строк?

Только обработать каждую, не изменяя.

DC>В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL.

DC>Удачи.
Большое спасибо, проблема успешно решена именно в этой стороне

С уваженеим, Троицкий Сергей.
Re[2]: Multistring в памяти
От: Serg-o-65535 Россия  
Дата: 09.11.06 09:59
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Можно, например, так

Спасибо за такой вариант.
Задачу решил арифметикой указателей + стандартными функциями C, но ваш способ дал пищу для размышлений — очень пригодится для другйо задачи, тоже очень полезная информация.


С уваженеим, Троицкий Сергей.
Re[2]: Multistring в памяти
От: rm822 Россия  
Дата: 09.11.06 15:51
Оценка:
Здравствуйте, dr.Chaos, Вы писали:

DC>В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL.


Вот как раз strtok —
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Multistring в памяти
От: dr.Chaos Россия Украшения HandMade
Дата: 09.11.06 15:58
Оценка:
Здравствуйте, rm822, Вы писали:

R>Здравствуйте, dr.Chaos, Вы писали:


DC>>В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL.


R>Вот как раз strtok —


Чем тебе strtok не угодил? .
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[4]: Multistring в памяти
От: rm822 Россия  
Дата: 09.11.06 16:24
Оценка:
Здравствуйте, dr.Chaos, Вы писали:

DC>Здравствуйте, rm822, Вы писали:


R>>Здравствуйте, dr.Chaos, Вы писали:


DC>>>В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL.


R>>Вот как раз strtok —


DC>Чем тебе strtok не угодил? .


Тем что глобальные переменные пользует.
Как следствие не потокобезопасен и неудобен (например нельзя бить 2 строки одновременно для сравнения по некоему специфическому критерию)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Multistring в памяти
От: dr.Chaos Россия Украшения HandMade
Дата: 09.11.06 16:37
Оценка: :)
Здравствуйте, rm822, Вы писали:

R>Здравствуйте, dr.Chaos, Вы писали:


DC>>Здравствуйте, rm822, Вы писали:


R>>>Здравствуйте, dr.Chaos, Вы писали:


DC>>>>В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL.


R>>>Вот как раз strtok —


DC>>Чем тебе strtok не угодил? .


R>Тем что глобальные переменные пользует.

R>Как следствие не потокобезопасен и неудобен (например нельзя бить 2 строки одновременно для сравнения по некоему специфическому критерию)

Ммм, а ты вообще видел, что я в посте спросил для чего нужно? .
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[6]: Multistring в памяти
От: rm822 Россия  
Дата: 09.11.06 16:54
Оценка:
DC>Ммм, а ты вообще видел, что я в посте спросил для чего нужно? .
А вот это не суть. Не надо учить плохому а то потом кто-то будет проблемы таких кулибиных-любителей strtok разгребать
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: Multistring в памяти
От: dr.Chaos Россия Украшения HandMade
Дата: 09.11.06 17:04
Оценка:
Здравствуйте, rm822, Вы писали:

DC>>Ммм, а ты вообще видел, что я в посте спросил для чего нужно? .

R>А вот это не суть. Не надо учить плохому а то потом кто-то будет проблемы таких кулибиных-любителей strtok разгребать

А где собственно учил плохому? Я показал альтернативы, я не говорил: "Пользуйся strtok — остальное зло". Кстати про многопоточность и strtok не знал . Тем не менее он применим во многих ситуациях, например только ради разбора небольшой строки, включать sstream не хочеться.
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[5]: Multistring в памяти
От: capgreen  
Дата: 09.11.06 18:50
Оценка:
DC>>Чем тебе strtok не угодил? .

R>Тем что глобальные переменные пользует.

R>Как следствие не потокобезопасен и неудобен (например нельзя бить 2 строки одновременно для сравнения по некоему специфическому критерию)

Это завист от реализации.
Наример если посмотреть в исходники CRT из \Vc7\crt\src то можно увидеть реализация этой функции для многопоточной модели имеет некоторую специфику
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Multistring в памяти
От: Roman Odaisky Украина  
Дата: 09.11.06 21:45
Оценка:
Здравствуйте, Serg-o-65535, Вы писали:

SO6>А конкретно мою задачу с вашей помошью решил так:


SO6>char *begin = (char*)p; // указатель на начло блока данных,
SO6>char *end = begin +size; // указатель на конец блока данных,
SO6>while(begin != end) {
SO6>strcpy(token, begin); // в token очередная строка
SO6>begin += strlen(begin) + 1;
SO6>} // while

Алгоритм Шлемиэля? Ты 2 раза проходишь строку: один раз при strcpy, один раз при strlen. Хотя я затрудняюсь придумать приличный способ сделать без велосипедов и то, и другое сразу...
До последнего не верил в пирамиду Лебедева.
Re[4]: Multistring в памяти
От: Serg-o-65535 Россия  
Дата: 09.11.06 23:15
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Алгоритм Шлемиэля? Ты 2 раза проходишь строку: один раз при strcpy, один раз при strlen. Хотя я затрудняюсь придумать приличный способ сделать без велосипедов и то, и другое сразу...


Я понимаю это strcpy(token, begin); привёл просто для примера того, куда девается строка .
В реальном алгоритме у меня никакх strcpy нет. Я использую сразу begin

Спасибо за уточнение.
Re[5]: Multistring в памяти
От: kan Великобритания  
Дата: 10.11.06 09:57
Оценка:
rm822 wrote:

> DC>Чем тебе strtok не угодил? .

> Тем что глобальные переменные пользует.
> Как следствие не потокобезопасен
В MultiThread Runtime он хранится в Thread Local Variable:
#ifdef _MT
         _ptiddata ptd = _getptd();
#else  /* _MT */
         static char *nextoken;
#endif  /* _MT */
...
#ifdef _MT
                 str = ptd->_token;
#else  /* _MT */
                 str = nextoken;
#endif  /* _MT */

(с) MSVS 7.1

> и неудобен (например нельзя бить 2

Самая гадость — он модифицирует разбиваемую строку.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Multistring в памяти
От: NickolasCPP Россия  
Дата: 10.11.06 13:50
Оценка:
Здравствуйте, Serg-o-65535, Вы писали:

...

Вообщем есть потоки( т.е. <<) такие штуки которые стали в C++ одно время очень популярными, но используя их ты лишь сократишь код, неизвестно какими алгоритмами, которые существенно уменьшат быстродействие твоей программы , поэтому рекомендую все таки оставить так как есть!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.