我为这个问题尝试了很多解决方案,但都没有正常工作!
我想将char **数组的值复制到char *。
类型的变量中char *line;
char **tokens = malloc(....);
所以,我尝试了以下内容:
for(i=0; i < sizeof(tokens); i++)
strncpy(line, tokens[i], strlen(line));
或者
for(i=0; i < sizeof(tokens); i++)
strncat(line, tokens[i]);
或者
for(i=0; i < sizeof(tokens); i++)
memcpy(line, tokens[i], strlen(line));
我的理解是令牌[i]将是char *类型,但是如果我得到错误,我无法理解。
Segmentation fault (core dumped)
如果这些方法不起作用,我该如何进行复制?
任何提示?
char *removesubString(char *path, char **args){
char *dir;
int COUNT;
COUNT = 100;
char **dirs = malloc(sizeof(char*)*COUNT);
int i, position;
for (i = 2; i < sizeof(args); i++) {
if(args[i] == NULL){
break;
}
dir = strtok(path, PATH_DELIM);
position = 0;
while (dir != NULL) {
if(strcmp(dir, args[i]) == 0){
dir = strtok(NULL, PATH_DELIM);
continue;
}
dirs[position] = dir;
position++;
dir = strtok(NULL, PATH_DELIM);
}//end of while
dirs[position] = NULL;
}//end of for
char *line;
line = "";
for (i = 0; i < position; i++) {
strncpy(line, dirs[i], strlen(dirs[i]));
}
return line;
}
答案 0 :(得分:0)
弹出关于代码的第一个问题是你的界限是错的:
char *line;
char **tokens = malloc(TOKENS_ARRAY_SIZE);
当你这样做时:
for(i=0; i < sizeof(tokens); i++) {
…
}
它不会返回已分配内存的大小,而是返回tokens
指针本身的已分配内存。来自sizeof manpage:
返回
类型的对象表示的大小(以字节为单位)
当您在静态矩阵上执行sizeof
时,它将返回矩阵的大小,因为这是为其分配的内存量。但是对于动态分配的矩阵,它只返回指针的大小,即如果你这样做:
char array_static[42];
char* array_dyn = malloc(sizeof(char)*42);
printf("sizeof(array_static) = %d\n", sizeof(array_static));
printf("sizeof(array_dyn) = %d\n", sizeof(array_dyn));
它将返回:
sizeof(array_static) = 42
sizeof(array_dyn) = 8
因此,如果动态数组中的项目数小于数组指针的返回大小,则会溢出,并且您将获得段错误。
因此,处理您的情况的正确方法是将动态数组的长度保留在另一个变量中,在设置分配的内存大小时更新它,然后将该值用于迭代。
int tokens_length = 42;
char *line;
char **tokens = malloc(sizeof(char*)*tokens_length);
for(i=0; i < sizeof(tokens_length); i++) {
…
}
所以在你的情况下,你应该这样做:
// keep somewhere the number of directories that you *can* allocate
int nb_dirs = 100;
char **dirs = malloc(sizeof(char*) * nb_dirs);
…
// keep a pointer on how many directories you've added
int position = 0;
while (dir != NULL) {
…
position++;
// fail loudly if you're adding more directories than you've allocated
// or you might use realloc() to extend the array's length
if (position >= nb_dirs) {
printf("ERROR! Too many directories!");
// RETURN WITH ERROR!
}
…
}
// here you iterate over all the directories you've added
for(i = 0; i <= position; i++){
// here you can do stuff with dirs, and copy only the length of the dirs element
strncpy(<TARGET>, dirs[i], strlen(dirs[i]);
}
然后还有另一个你应该考虑的问题:在你的循环中,你正在修改path
,作为参数给出,你在strcpy()
dirs进入:
strncpy(path, dirs[i], <LENGTH>);
但这没有多大意义,无论你想做什么都不是你写的。
这里,考虑到正确设置了size参数,您将把dirs
数组的每个项复制到同一个变量中。所以你最终总是路径指针引用的dirs
数组的最后一个值。
但问题是你只有路径指针,但是你知道它在给函数时的分配方式知之甚少。它是如何分配的,以及分配了多少内存?什么“有用”的大小(虽然可以用strlen()
猜测一个?)
哦,最后,一旦你完成它们,不要忘记free()
你的分配。不要泄漏记忆,这很粗鲁! ☺
编辑:
好吧,这是我能看到的错误的东西,以及一些关于它的评论:char *removesubString(char *path, char **args){
char *dir;
int COUNT = 100;
char **dirs = malloc(sizeof(char*)*COUNT);
int i, position;
/* for both XXX marks below:
*
* below, sizeof(args) will return the size of the pointer
* not the number of items it contains. You *NEED* to pass
* a "int argc" as parameter to your function, that gives
* the numbers of items in the array.
* Think about why you have argc in the main() function construct:
* int main(int argc, const char** argv)
* _OR_ if the args array of strings is _ALWAYS_ terminated
* by a NULL item, then you should do: */
// int i = 0;
// while(args[i] != NULL) {
// /* do stuff */
// ++i;
// }
for (i = 2; i < sizeof(args) /* XXX */; i++) {
if(args[i] == NULL){ /* XXX */
break;
}
dir = strtok(path, PATH_DELIM);
position = 0;
while (dir != NULL) {
if(strcmp(dir, args[i]) == 0){
dir = strtok(NULL, PATH_DELIM);
continue;
}
/* because within the function you have no guarantee
* on the number of tokens within path, if you have
* more than 100 tokens, you will overflow the dirs array.
* a good idea would be to test whether position is bigger
* than or equal to COUNT, and if it is use realloc to
* extend dirs */
dirs[position] = dir;
position++;
dir = strtok(NULL, PATH_DELIM);
/* you could avoid having twice the former line
* and instead make your loop body being: */
// while (dir != NULL) {
// if(strcmp(dir, args[i]) != 0){
// /* TODO: check position vs COUNT and realloc dirs if necessary */
// dirs[position] = dir;
// ++position;
// }
// dir = strtok(NULL, PATH_DELIM);
// }
}
dirs[position] = NULL;
}
char *line;
line = ""; /* ← here you allocate line with a string of length 1 */
for (i = 0; i < position; i++) {
// so here, you'll write up to the number of characters
// within dirs[i], into a string of length one.
strncpy(line, dirs[i], strlen(dirs[i]));
}
/* And even if it was working you'd be assigning the line
* variable to a new value at each iteration, ending up doing
* something equivalent to the following line, but with "position"
* numbers of iterations: */
// strncpy(line, dirs[position-1], strlen(dirs[position-1]));
/* Don't forget to free the instances you've allocated dynamically
* before leaving the function: */
// free(dirs);
/* And finally there's another issue here, you're returning
* a variable that has been statically allocated above, so that
* when you'll try to use the pointed instance in the calling
* context, that variable won't exist anymore. */
return line;
}
HTH