Здравствуйте, 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.
Удачи.
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Здравствуйте, rm822, Вы писали:
R>Здравствуйте, dr.Chaos, Вы писали:
DC>>Здравствуйте, rm822, Вы писали:
R>>>Здравствуйте, dr.Chaos, Вы писали:
DC>>>>В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL.
R>>>Вот как раз strtok —
DC>>Чем тебе strtok не угодил? .
R>Тем что глобальные переменные пользует. R>Как следствие не потокобезопасен и неудобен (например нельзя бить 2 строки одновременно для сравнения по некоему специфическому критерию)
Ммм, а ты вообще видел, что я в посте спросил для чего нужно? .
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Уважаемые господа, помогите новичку решить тревиальную задачу
Поиск по форумам/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);
}
Здравствуйте, 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 это сделает заведомо медленнее и извращённее.
Здравствуйте, Кодт, Вы писали:
К>Ну не совсем классический. К>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 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
Здравствуйте, dr.Chaos, Вы писали:
DC>Перебрать с какой целью: DC>Посчитать количество? DC>Обработать каждую, не изменяя? DC>Получить массив строк?
Только обработать каждую, не изменяя.
DC>В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL. DC>Удачи.
Большое спасибо, проблема успешно решена именно в этой стороне
Здравствуйте, Аноним, Вы писали: А>Можно, например, так
Спасибо за такой вариант.
Задачу решил арифметикой указателей + стандартными функциями C, но ваш способ дал пищу для размышлений — очень пригодится для другйо задачи, тоже очень полезная информация.
Здравствуйте, rm822, Вы писали:
R>Здравствуйте, dr.Chaos, Вы писали:
DC>>В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL.
R>Вот как раз strtok —
Чем тебе strtok не угодил? .
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Здравствуйте, dr.Chaos, Вы писали:
DC>Здравствуйте, rm822, Вы писали:
R>>Здравствуйте, dr.Chaos, Вы писали:
DC>>>В любом случае копай в сторону strtok (stdio.h или string.h) или в сторону getline из STL.
R>>Вот как раз strtok —
DC>Чем тебе strtok не угодил? .
Тем что глобальные переменные пользует.
Как следствие не потокобезопасен и неудобен (например нельзя бить 2 строки одновременно для сравнения по некоему специфическому критерию)
DC>Ммм, а ты вообще видел, что я в посте спросил для чего нужно? .
А вот это не суть. Не надо учить плохому а то потом кто-то будет проблемы таких кулибиных-любителей strtok разгребать
Здравствуйте, rm822, Вы писали:
DC>>Ммм, а ты вообще видел, что я в посте спросил для чего нужно? . R>А вот это не суть. Не надо учить плохому а то потом кто-то будет проблемы таких кулибиных-любителей strtok разгребать
А где собственно учил плохому? Я показал альтернативы, я не говорил: "Пользуйся strtok — остальное зло". Кстати про многопоточность и strtok не знал . Тем не менее он применим во многих ситуациях, например только ради разбора небольшой строки, включать sstream не хочеться.
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
DC>>Чем тебе strtok не угодил? .
R>Тем что глобальные переменные пользует. R>Как следствие не потокобезопасен и неудобен (например нельзя бить 2 строки одновременно для сравнения по некоему специфическому критерию)
Это завист от реализации.
Наример если посмотреть в исходники CRT из \Vc7\crt\src то можно увидеть реализация этой функции для многопоточной модели имеет некоторую специфику
Здравствуйте, 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. Хотя я затрудняюсь придумать приличный способ сделать без велосипедов и то, и другое сразу...
Здравствуйте, Roman Odaisky, Вы писали:
RO>Алгоритм Шлемиэля? Ты 2 раза проходишь строку: один раз при strcpy, один раз при strlen. Хотя я затрудняюсь придумать приличный способ сделать без велосипедов и то, и другое сразу...
Я понимаю это strcpy(token, begin); привёл просто для примера того, куда девается строка .
В реальном алгоритме у меня никакх strcpy нет. Я использую сразу begin
rm822 wrote:
> DC>Чем тебе strtok не угодил? . > Тем что глобальные переменные пользует. > Как следствие не потокобезопасен
В MultiThread Runtime он хранится в Thread Local Variable:
Вообщем есть потоки( т.е. <<) такие штуки которые стали в C++ одно время очень популярными, но используя их ты лишь сократишь код, неизвестно какими алгоритмами, которые существенно уменьшат быстродействие твоей программы , поэтому рекомендую все таки оставить так как есть!