开发者

Splitting a char* at its many '\0' chars

开发者 https://www.devze.com 2023-03-12 16:10 出处:网络
The following is in C++. I have a string that contains the environment variables I need to split it at the declaration of each variable & store it in a string:

The following is in C++. I have a string that contains the environment variables I need to split it at the declaration of each variable & store it in a string:

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

So I am using cstring functions to split the string at the occurence of the null terminator char '\0' but it's just going into an infinite loop. Why?

SOLUTION Found: look at code comments:

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 )
 开发者_StackOverflow中文版  {
       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;       
}


You can do this a bit more simply and without relying on the C Standard Library functions:

#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;
    }
}

The std::string constructor used here takes characters from the pointed-to array until it reaches a \0. We then move to the next string, which begins one character past the end of the previous string. It stops when it reaches an "empty" string (the double null terminator that ends the sequence).


I would have expected this to exit immediately, but actually the man page says:

The terminating null character is considered to be part of the string; therefore if c is '\0', the functions locate the terminating '\0'.

Of course, the result of pos = strchr(environVar, '\0'); is that *pos == '\0' and strlen(pos) == 0. So you always copy exactly zero characters. Not useful.

You also set environVar = pos;, without skipping over the NUL character. So the next call to strchr returns environVar and no more progress is ever made.


You've also forgotten to initialize buffer, you're passing a wild pointer to strncpy which will corrupt a random part of memory. This bug will probably rear its ugly head as soon as you fix the fact that the length parameter is always zero.


This line is wrong.

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

pos is positioned at the first null, and has a length of zero. You probably want strlen(environVar).

This line is probably causing the infinite loop:

environVar = pos;

Since pos is positioned at \0, it is going to return that same pointer. Try pos + 1.


#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;
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消