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