и как можно это обойти, если я не хочу каждый раз выделять и уничтожать память под char. Мне нужно разделять строку
достаточно быстро, поскольку это происходит в цикле много раз.
Здравствуйте, Mattias, Вы писали:
M>Хорошо. Тогда следующий вопрос, могу ли я создать char[] из char* не используя динамического выделения памяти.
Нет, конечно. Однако, без динамического выделения памяти вообще почти ничего полезного нельзя сделать — кроме, разве что, нескольких безопастностных уязвимостей.
M>Если нет , то мне кажется функция strtok — довольно бесполезная, я могу ее использовать только либо используя динамическое выделение , либо заранее зная строку для инициализации массива чаров.
Она не просто бесполезная, а вообще вредная. Потому что портит входную строку и, кроме того, имеет внутреннее состояние. То есть, нельзя одновременно разбивать несколько разных строк, хоть в разных потоках, хоть в одном.
Здравствуйте, Centaur, Вы писали:
C>Она не просто бесполезная, а вообще вредная. Потому что портит входную строку и, кроме того, имеет внутреннее состояние. То есть, нельзя одновременно разбивать несколько разных строк, хоть в разных потоках, хоть в одном.
В одном потокое действительно нельзя, но в разных вполне допустимо, т.к. внутреннее состояние она хранит в контексте потока.
Здравствуйте, Mattias, Вы писали: M>Это так, но у меня передается в функцию переменная char*.
учи С M>Кстати а почему это работает, разве не одно и то же?
в первом случаи ты обьявил указатель на строку, размещенную в сегменте для констант.
А в случаи char test[] обьявляешь массив, который будет создан на стеке и проинициализирован указанной строкой.
Здравствуйте, Mattias, Вы писали:
M>Здравствуйте, Nik_1, Вы писали:
N_>>Здравствуйте, Mattias, Вы писали: M>>>char test[] = "wert \t\t 32 2 wert";
M>Это так, но у меня передается в функцию переменная char*. Кстати а почему это работает, разве не одно и то же?
И все таки я не понял. Вот есть код:
char* test = ... ; // код который возвращает char*
далее я хочу разбить test на токены с помощью strtok.
Здравствуйте, Mattias, Вы писали:
M>Здравствуйте, Mattias, Вы писали:
M>>Здравствуйте, Nik_1, Вы писали:
N_>>>Здравствуйте, Mattias, Вы писали: M>>>>char test[] = "wert \t\t 32 2 wert";
M>>Это так, но у меня передается в функцию переменная char*. Кстати а почему это работает, разве не одно и то же?
M>И все таки я не понял. Вот есть код:
M>char* test = ... ; // код который возвращает char*
M>далее я хочу разбить test на токены с помощью strtok.
M>Как это сделать?
помни, что strtok меняет переданную строку, вставляя 0 символы в нужных местах
поэтому надо передавать строку, в которую можно писать
или же отказаться от использования strtok — не так уж мудрено написать код, который не будет менять исходную строку, все равно часто отдельные отрезки копируются куда-то, ...
Здравствуйте, ilnar, Вы писали:
I>Здравствуйте, Mattias, Вы писали:
M>>Здравствуйте, Mattias, Вы писали:
M>>>Здравствуйте, Nik_1, Вы писали:
N_>>>>Здравствуйте, Mattias, Вы писали: M>>>>>char test[] = "wert \t\t 32 2 wert";
M>>>Это так, но у меня передается в функцию переменная char*. Кстати а почему это работает, разве не одно и то же?
M>>И все таки я не понял. Вот есть код:
M>>char* test = ... ; // код который возвращает char*
M>>далее я хочу разбить test на токены с помощью strtok.
M>>Как это сделать?
I>помни, что strtok меняет переданную строку, вставляя 0 символы в нужных местах I>поэтому надо передавать строку, в которую можно писать I>или же отказаться от использования strtok — не так уж мудрено написать код, который не будет менять исходную строку, все равно часто отдельные отрезки копируются куда-то, ...
Хорошо. Тогда следующий вопрос, могу ли я создать char[] из char* не используя динамического выделения памяти.
Если нет , то мне кажется функция strtok — довольно бесполезная, я могу ее использовать только либо используя динамическое выделение , либо заранее зная строку для инициализации массива чаров.
Здравствуйте, Mattias, Вы писали:
N_>>>Здравствуйте, Mattias, Вы писали: M>>>>char test[] = "wert \t\t 32 2 wert";
M>>Это так, но у меня передается в функцию переменная char*. Кстати а почему это работает, разве не одно и то же?
M>И все таки я не понял. Вот есть код:
M>char* test = ... ; // код который возвращает char*
M>далее я хочу разбить test на токены с помощью strtok.
M>Как это сделать?
Тебе тут надавали кучу разных советов и, ИМХО, еще сильнее сбили тебя с толку. Все что тебе нужно на данном этапе — это понять разницу между массивом и указателем — это не одно и то же. Лучший способ разобраться в предмете — почитать учебник. если в двух словах, то массив — это последовательность однотипных объектов, расположенных в памяти друг за другом. Указатель — это переменная (или константа), в которой записан адрес какого-либо объекта. С помощью указателей можно ссылаться как на одиночные объекты, так и на элементы массивов. К указателям применимы операции сравнения, инкремента, декремента, сложения и вычитания (так называемая арифметика указателей). При этом автоматически считается, что указатель указывает на элемент массива, применение этих операций к указателю на одиночный объект приводит к неопределенному поведению программы. Массивы могут автоматически (неявно) преобразовываться в указатели, при этом образуется указатель, указывающий на первый элемент массива, после чего к указателю можно применять арифметические операции и тем самым осуществлять навигацию по элементам массива.
Как массивы так и указатели могут располагаться в разных областях памяти — статической, динамической, временной (в стеке), а также в области констант. В зависимости от костантности/неконстантности указателей и адресуемых ими объектов (элементов массива), а также от того в какой области памяти они расположены, набор допустимых операций может варьироваться. Рассмотрим твой исходный пример:
В этом примере определяется указатель test, указывающий на первый элемент массива символов. Причем указатель и массив расположены в разных областях памяти — указатель в стеке, а массив символов — в статической памяти, доступной только для чтения. В этом и заключается причина ошибки — посредством указателя ты пытаешься модифицировать данные в области памяти, доступной только для чтения. Исправить ошибку можно расположив массив в другой области памяти, например, на стеке:
Можно было бы вместо стека использовать и динамическую память, но в этом случае возникает вопрос об ответственности за освобождении этой памяти. Решения этого и других вопросов, которые неизбежно возникнут в процессе разработки, лучше начать с чтения книг. Короче говоря, учиться, учиться и учиться (с).
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, leshy84, Вы писали:
L>В одном потокое действительно нельзя, но в разных вполне допустимо, т.к. внутреннее состояние она хранит в контексте потока.
А в одном потоке — просто не удастся.
On the first call to strtok, the function skips leading delimiters and returns a pointer to the first token in strToken, terminating the token with a null character. More tokens can be broken out of the remainder of strToken by a series of calls to strtok. Each call to strtokmodifies strToken by inserting a null character after the token returned by that call. To read the next token from strToken, call strtok with a NULL value for the strToken argument. The NULL strToken argument causes strtok to search for the next token in the modified strToken. The strDelimit argument can take any value from one call to the next so that the set of delimiters may vary.
C>Она не просто бесполезная, а вообще вредная. Потому что портит входную строку и, кроме того, имеет внутреннее состояние. То есть, нельзя одновременно разбивать несколько разных строк, хоть в разных потоках, хоть в одном.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А в одном потоке — просто не удастся.
PD>передаешь ненулевой указатель — начнем парсинг. Передаешь NULL — продолжаем парсинг.
Ну и? Функция foo начинает токенизацию некоей строки и для каждого токена вызывает функцию bar. Функция bar в процессе своей работы токенизирует какую-то другую строку. При возврате из bar функция foo обнаруживает, что состояние токенизатора испорчено, и всё из-за того, что кто-то сделал функцией (или копрограммой?) то, что по сути должно быть алгоритмом или объектом.
Здравствуйте, Centaur, Вы писали:
C>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>А в одном потоке — просто не удастся.
PD>>передаешь ненулевой указатель — начнем парсинг. Передаешь NULL — продолжаем парсинг.
C>Ну и? Функция foo начинает токенизацию некоей строки и для каждого токена вызывает функцию bar. Функция bar в процессе своей работы токенизирует какую-то другую строку. При возврате из bar функция foo обнаруживает, что состояние токенизатора испорчено, и всё из-за того, что кто-то сделал функцией (или копрограммой?) то, что по сути должно быть алгоритмом или объектом.
Я и не спорю, что это не лучшим образом сделано. Я просто хотел сказать, что технически невозможно парсить в одном потоке одновременно 2 строки.