Разделение символа * на множество символов '\ 0' - PullRequest
1 голос
/ 13 июня 2011

Следующее в C ++.У меня есть строка, которая содержит переменные окружения, мне нужно разделить ее при объявлении каждой переменной и сохранить ее в строке:

char* envVars = "=::=::\0system=blah\0othervar=blah\0"

Поэтому я использую функции cstring для разделения строки в случаенулевой терминатор char '\ 0', но он просто входит в бесконечный цикл.Почему?

РЕШЕНИЕ Найдено: посмотрите на комментарии к коду:

vector <string> GetEvironmentVariables()
{
   vector <string> envVariables;
   char* environVar = GetEnvironmentStrings();
   char* pos        = strchr( environVar, '\0' );

   // As far as I know environVar =::=::\0environVar1=...\0environVar2=...\0" 
   // so the string has many NULL terminators  

   while ( pos != NULL )
   {
       char* buffer;
       strncpy( buffer, environVar, strlen(pos) );   // on the 1st iteration: buffer SHOULD = "=::=::\0", 2nd buffer SHOULD = "environVar=...\0"
       envVariables.push_back( string(buffer) );
       environVar = pos;                            // SOLUTUION: I need to move over the '\0' pos points to so: environVar = ++pos;
       pos        = strchr( environVar, '\0' );

       printf("Var: %s \n", envVariables.back().c_str() ); 
       printf("env: %s \n", environVar);
       system("PAUSE");
       // prints out this:
       // Var: cRek (same junk each iteration)
       // env: 
       // Press any key to continue....
   }

   FreeEnvironmentStrings( environVar ); 
   return envVariables;       
}

Ответы [ 4 ]

8 голосов
/ 13 июня 2011

Вы можете сделать это немного проще и не полагаясь на функции стандартной библиотеки C:

#include <string>
#include <vector>

int main()
{
    const char* environment = "x=x\0y=y\0z=z\0";

    std::vector<std::string> environment_strings;
    const char* current_string = environment;

    while (*current_string)
    {
        environment_strings.push_back(current_string);
        current_string += environment_strings.back().length() + 1;
    }
}

Используемый здесь конструктор std::string берет символы из массива, на который указывает указатель, пока не достигнет \0.Затем мы переходим к следующей строке, которая начинается на один символ за концом предыдущей строки.Он останавливается, когда достигает «пустой» строки (двойного нулевого терминатора, который завершает последовательность).

2 голосов
/ 13 июня 2011

Я ожидал, что это немедленно завершится, но на самом деле на странице руководства написано:

Завершающий нулевой символ считается частью строки;поэтому, если c равно '\0', функции находят завершающий '\0'.

Конечно, результатом pos = strchr(environVar, '\0'); является то, что *pos == '\0' и strlen(pos) == 0.Таким образом, вы всегда копируете ровно ноль символов.Не полезно.

Вы также устанавливаете environVar = pos;, не пропуская символ NUL.Поэтому следующий вызов strchr возвращает environVar, и больше никакого прогресса не происходит.


Вы также забыли инициализировать buffer, вы передаете дикий указательв strncpy, что приведет к повреждению случайной части памяти. Эта ошибка, вероятно, приведет к появлению уродливой головы, как только вы исправите тот факт, что параметр длины всегда равен нулю.

0 голосов
/ 13 июня 2011

Эта строка неверна.

strncpy( buffer, environVar, strlen(pos) );

pos находится в первом нуле и имеет длину ноль.Возможно, вам нужен strlen (environmentVar).

Эта строка, вероятно, вызывает бесконечный цикл:

environVar = pos;

Поскольку pos расположен в \ 0, он будет возвращать тот же указатель.Попробуйте поз + 1.

0 голосов
/ 13 июня 2011
#include <cstring>
#include <string>
#include <vector>

using namespace std;

int main ()
{
    vector<string> res;

    const char *s = "=::=::\0system=blah\0othervar=blah\0";
    const char *p = s;

    while (*s != '\0')
    {
        p = strchr (p, '\0');
        res.push_back (s);
        s = ++p;
    }
}
...