我有一个与extern char **environ
有关的问题。我正在尝试制作一个计算环境列表大小的C程序,将其复制到一系列字符串(一系列字符阵列(,然后用气泡排序按字母顺序排列。它将根据格式值以name=value
或value=name
订单打印。
我尝试使用strncpy
将字符串从环境中获取到我的新数组,但是字符串值空了。我怀疑我正在尝试以无法使用的方式使用环境,因此我正在寻求帮助。我试图在线寻找帮助,但是这个特定的程序非常有限。我无法使用system()
,但是我在网上找到的唯一帮助告诉我要制作一个程序来进行此系统调用。(这确实不是帮助(。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern char **environ;
int main(int argc, char *argv[])
{
char **env = environ;
int i = 0;
int j = 0;
printf("Hello world!n");
int listSZ = 0;
char temp[1024];
while(env[listSZ])
{
listSZ++;
}
printf("DEBUG: LIST SIZE = %dn", listSZ);
char **list = malloc(listSZ * sizeof(char**));
char **sorted = malloc(listSZ * sizeof(char**));
for(i = 0; i < listSZ; i++)
{
list[i] = malloc(sizeof(env[i]) * sizeof(char)); // set the 2D Array strings to size 80, for good measure
sorted[i] = malloc(sizeof(env[i]) * sizeof(char));
}
while(env[i])
{
strncpy(list[i], env[i], sizeof(env[i]));
i++;
} // copy is empty???
for(i = 0; i < listSZ - 1; i++)
{
for(j = 0; j < sizeof(list[i]); j++)
{
if(list[i][j] > list[i+1][j])
{
strcpy(temp, list[i]);
strcpy(list[i], list[i+1]);
strcpy(list[i+1], temp);
j = sizeof(list[i]); // end loop, we resolved this specific entry
}
// else continue
}
}
这是我的代码,非常感谢帮助。为什么这很难找到话题?缺乏必要吗?
编辑:粘贴错误的代码,这是同一主题上的一个单独的.c文件,但是我在另一个文件上开始新鲜。
UNIX环境,环境是主要的第三个参数。
尝试以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[], char **envp)
{
while (*envp) {
printf("%sn", *envp);
*envp++;
}
}
您的代码有多个问题,包括:
- 为
list
和sorted
分配"错误"的大小(您乘以sizeof(char **)
,但应乘以sizeof(char *)
,因为您要分配char *
的数组。此错误实际上不会伤害您。这次使用sizeof(*list)
避免避免使用CC_11问题。 - 为
list
和sorted
中的元素分配错误的大小。您需要使用strlen(env[i]) + 1
的大小,请记住以允许终止字符串的null。 - 您不检查内存分配。
- 您的字符串复制循环使用
strncpy()
,不应该(实际上,您应该很少使用strncpy()
(,尤其是因为它仅复制每个环境的4或8个字节(取决于您是否在32--上位或64位系统(,并且不能确保它们终止终止字符串(只是使用strncpy()
的而不是而不是的原因之一。 - 您的"排序"代码的外循环还可以;您的内部循环是100%的伪造周围。
- 您分配但不使用
sorted
。 - 您不打印排序的环境以证明其已排序。
- 您的代码缺少最终的
}
。
这是一些使用标准C库qsort()
函数进行分类的简单代码,并模拟POSIX strdup()
以dup_str()
的名称 - 如果您可以使用POSIX,则可以使用strdup()
。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char **environ;
/* Can also be spelled strdup() and provided by the system */
static char *dup_str(const char *str)
{
size_t len = strlen(str) + 1;
char *dup = malloc(len);
if (dup != NULL)
memmove(dup, str, len);
return dup;
}
static int cmp_str(const void *v1, const void *v2)
{
const char *s1 = *(const char **)v1;
const char *s2 = *(const char **)v2;
return strcmp(s1, s2);
}
int main(void)
{
char **env = environ;
int listSZ;
for (listSZ = 0; env[listSZ] != NULL; listSZ++)
;
printf("DEBUG: Number of environment variables = %dn", listSZ);
char **list = malloc(listSZ * sizeof(*list));
if (list == NULL)
{
fprintf(stderr, "Memory allocation failed!n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < listSZ; i++)
{
if ((list[i] = dup_str(env[i])) == NULL)
{
fprintf(stderr, "Memory allocation failed!n");
exit(EXIT_FAILURE);
}
}
qsort(list, listSZ, sizeof(list[0]), cmp_str);
for (int i = 0; i < listSZ; i++)
printf("%2d: %sn", i, list[i]);
return 0;
}
其他人指出,您可以使用原型int main(int argc, char **argv, char **envp)
通过main()
的第三个参数来了解环境。请注意,Microsoft明确支持这一点。它们是正确的,但是即使在main()
以外的功能中,您也可以通过environ
在环境中获得环境。在 not 中定义的全局变量中,变量environ
是唯一的,因此您必须自己编写声明。
请注意,内存分配是检查错误,并且在标准错误(而不是标准输出(上报告的错误。
显然,如果您喜欢写作和调试排序算法,则可以避免使用qsort()
。请注意,字符串比较需要使用strcmp()
进行,但是当您对qsort()
进行排序时,由于参数类型是错误的。
对我来说,输出的一部分是:
DEBUG: Number of environment variables = 51
0: Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.tQHOVHUgys/Render
1: BASH_ENV=/Users/jleffler/.bashrc
2: CDPATH=:/Users/jleffler:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work:/Users/jleffler/soq/src
3: CLICOLOR=1
4: DBDATE=Y4MD-
…
47: VISUAL=vim
48: XPC_FLAGS=0x0
49: XPC_SERVICE_NAME=0
50: _=./pe17
如果要对值进行排序而不是名称,则必须做一些艰苦的工作。您需要定义要查看的输出。有多种处理方法。
要获取环境变量,您需要像这样声明main
:
int main(int argc, char **argv, char **env);
第三个参数是环境变量的NULL
终止列表。请参阅:
#include <stdio.h>
int main(int argc, char **argv, char **environ)
{
for(size_t i = 0; env[i]; ++i)
puts(environ[i]);
return 0;
}
输出的是:
LD_LIBRARY_PATH=/home/shaoran/opt/node-v6.9.4-linux-x64/lib:
LS_COLORS=rs=0:di=01;34:ln=01;36:m
...
还请注意,代码中的sizeof(environ[i])
不会使您长度字符串,它可以使您有指针的大小,所以
strncpy(list[i], environ[i], sizeof(environ[i]));
是错误的。同样, strncpy
的全部要点是限制>基于目标,不在源上,否则,如果源大于目的地,则仍将溢出缓冲区。正确的电话将是
strncpy(list[i], environ[i], 80);
list[i][79] = 0;
裸露strncpy
可能不会编写' '
终止字节目的地还不够大,因此您必须确保终止细绳。另请注意,对于存储ENV变量而言,79个字符可能太短。例如,我的LS_COLORS
变量是巨大的,至少1500个字符。您可能想基于strlen(environ[i])+1
进行list[i] = malloc
呼叫。
另一件事:您的交换
strcpy(temp, list[i]);
strcpy(list[i], list[i+1]);
strcpy(list[i+1], temp);
j = sizeof(list[i]);
仅当所有list[i]
指向相同大小的内存时才有效。由于list[i]
是指示器,因此更便宜的交换方式是改用指针:
char *tmp = list[i];
list[i] = list[i+1];
list[i+1] = tmp;
这更有效,是O(1(操作,您不必担心是否内存空间的大小不相同。
我没有得到的是,您打算用j = sizeof(list[i])
?不仅sizeof(list[i])
返回指针的大小(这将是恒定的对于所有list[i]
(,为什么您会在运行变量j
中混乱堵塞?如果要离开循环,请执行break
。而且您正在寻找 strlen(list[i])
:这将为您提供字符串的长度。