Переменные среды находятся в символе * как получить его в std::string

#c #winapi #cstring

#c #winapi #cstring

Вопрос:

Я извлекаю переменные окружения в win32 с помощью GetEnvironmentStrings() . Он возвращает char* .

Я хочу выполнить поиск в этой строке (указатель на символ) для конкретной переменной окружения (да, я знаю, что могу использовать GetEnvironmentVariable() , но я делаю это таким образом, потому что я также хочу напечатать все переменные окружения на консоли — я просто повозился).

Итак, я подумал, что я бы преобразовал char* в std:: string и использовал find для него (я знаю, что я также могу использовать функцию поиска c_string, но меня больше беспокоит попытка скопировать char* в std::string ). Но следующий код, похоже, не копирует все char* в std::string (это заставляет меня думать, что в есть char* символ, но на самом деле это не конец).

 char* a = GetEnvironmentStrings();
string b = string(a, sizeof(a));
printf( "%s", b.c_str() );  // prints =::= 
  

Есть ли способ скопировать a char* в std::string (я знаю, что могу использовать strcpy() для копирования a const char* в строку, но не char* ).

Комментарии:

1. Кто, черт возьми, пытается закрыть это как точный дубликат? Это совершенно другой вопрос!

2. @Xeo: Ну, нет, это не так… Используемая функция getenv / GetEnvironmentVariable отличается, но результат тот же… Все, что нужно сделать оператору, это заменить getenv вызов на GetEnvironmentVariable call.

3. @rubenvb: За исключением того, что GetEnvironmentStrings() возвращает сомнительный формат, с которым OP требует конкретной помощи. Вы не можете просто заменить getenv на GetEnvironmentStrings() .

4. Проблема не совсем та же. В конце концов, он не пытается узнать, как это сделать, он интересуется, почему это произошло именно так.

5. Упс, мои извинения, я недостаточно бодр, чтобы использовать свои голоса «закрыть».

Ответ №1:

Вы не хотите использовать sizeof() в этом контексте — вы можете просто передать значение в конструктор. char* тривиально становится const char* , и вы не хотите использовать strcpy или printf либо.

Это для обычных C-строк — однако GetEnvironmentStrings() возвращает немного странный формат, и вам, вероятно, потребуется вставить его вручную.

 const char* a = GetEnvironmentStrings();
int prev = 0;
std::vector<std::string> env_strings;
for(int i = 0; ; i  ) {
    if (a[i] == '') {
        env_strings.push_back(std::string(a   prev, a   i));
        prev = i;
        if (a[i   1] == '') {
            break;
        }
    }
}
for(int i = 0; i < env_strings.size(); i  ) {
    std::cout << env_strings[i] << "n";
}
  

Комментарии:

1. спасибо, я понимаю, так что это должно быть правдой, что char * переменных окружения заполнен символами . Я принимаю ваш подход, но я думаю, что вместо перебора каждого символа я буду использовать строковую функцию c strtok, чтобы разделить ее на символы

2. @Mack: Ты не можешь этого сделать. GetEnvironmentStrings возвращает память, которую вам не разрешено перезаписывать, и strtok она не потокобезопасна, и в любом случае это ужасно небезопасно. Используйте подход C .

3. @Mack: Не забывайте, strtok это ужасно неправильная вещь сама по себе. Это полномасштабный одноэлементный конечный автомат.

4. @Mack: О, и я не думаю, что возможно заставить strtok не останавливаться на первом и ждать двойного . Все библиотеки C-string будут ожидать в качестве завершителя — вот почему вам нужен пользовательский код синтаксического анализа.

5. Работает ли это, если переменных окружения нет: т.е. возвращается » 0″.

Ответ №2:

sizeof(a) в том, что у вас есть выше, будет возвращен размер char* , то есть указатель (обычно 32 или 64 бита). Вы искали там функцию strlen . И на самом деле это вообще не требуется:

 std::string b(a);
  

должно быть достаточно, чтобы получить первую пару переменных окружения.

Комментарии:

1. Проверьте документацию для GetEnvironmentStrings — этого будет недостаточно.

2. спасибо, но я пробовал это, и он все еще выводит = ::= это заставляет меня думать, что в конце каждой переменной окружения есть символ 0, поэтому я получаю это немного

3. @Mack, да, выше будет отображен только первый, извините, я забыл, что макет блока окружения.

Ответ №3:

Результат GetEnvironmentStrings() указывает на память, содержащую все строки среды. Аналогично решению Puppy, оно будет помещено в вектор string, где каждая строка содержит только одну переменную окружения ( "key=value" )

 std::vector<std::string> env_strings;
LPTCH a = GetEnvironmentStrings();
  

В качестве примера у нас будут определены 2 переменные окружения:

 "A=ABC"
"X=XYZ"
  

LPTCH a будет:

 A=ABCX=XYZ
  

Каждая переменная '' завершается, и, наконец, полная строка среды ( a ) будет завершаться дополнительной '' .

strlen вернет размер до первого вхождения символа завершения '' . Последняя строка всегда будет пустой.

 while ((std::size_t len = strlen(a)) > 0)
{
    env_strings.push_back(std::string(a, len));
    a  = len   1;
}
  

Многобайтовый символ

Для многобайтовых символов это также будет работать:

 LPTCH a = GetEnvironmentStrings();
std::vector<std::wstring> env_strings;

while ((std::size_t len = wcslen(a)) > 0)
{
    env_strings.push_back(std::wstring(a, len));
    a  = len   1;
}

FreeEnvironmentStrings(a);
  

Комментарии:

1. Вы можете использовать std::string_view , чтобы избежать выделения копирования строк только для их обработки (например, поиска определенной переменной). Но скопируйте то, что вам нужно сохранить, перед вызовом FreeEnvironmentStrings().

2. Обратите внимание, указатель, a возвращенный из GetEnvironmentStrings , был изменен перед передачей в FreeEnvironmentStrings

Ответ №4:

Вызывает ли следующее какие-либо проблемы?

 char* a = GetEnvironmentStrings();
string b;
b=a;
printf( "%s", b.c_str() );
  

Комментарии:

1. ну, я подробнее изучил std:: string, он выводит: =::=:: now

Ответ №5:

Когда вы говорите:

 string b = string(a, sizeof(a));
  

вы получаете размер a, который является указателем и, вероятно, равен 4. Таким образом, вы получите первые 4 символа. Я не уверен, что вы действительно пытаетесь сделать, но вы должны быть в состоянии просто сказать:

 string b( a );
  

Ответ №6:

 char* a = ...;
string str(a);
string b;
b = a;
  

Ответ №7:

Я предполагаю, что вы имеете в виду функцию Windows API GetEnvironmentStrings. Итак, протестируйте результат с помощью nullptr и выполните простое присвоение:

 char* env = ::GetEnvironmentStrings();
if (0 != env)
{
   std::string senv = env;
   // use senv to find variables
}
else
{
   // report problem or ignore
}