在我的指针数组中添加字符串时,它被最后一个覆盖。谁能告诉我,我的错误在哪里?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main (){
int ile = 3;
const char * slowa[ile];
for(int j = 0; j < ile; j++){
char string[30];
gets(string);
slowa[j] = string;
printf ("%s dodalem pierwsza\n",string);
}
for (int i = 0; i < ile; i++) {
printf ("%s numer %d\n",slowa[i],i);
}
return 0;
}
答案 0 :(得分:2)
答案在以下两行代码中:
char string[30];
...
slowa[j] = string;
分配将slowa[j]
设置为相同缓冲区的地址,而不进行复制。因此,放在缓冲区中的最后一件事将被slowa[]
数组的所有元素引用,直到j-1
的位置。
要解决此问题,请在slowa
中存储值之前进行复制。您可以使用非标准strdup
,或使用malloc
+ strcpy
:
char string[30];
gets(string);
slowa[j] = malloc(strlen(string)+1);
strcpy(slowa[j], string);
在这两种情况下,您都需要在已为其分配值的free
数组的所有元素上调用slowa[]
,以避免内存泄漏。
答案 1 :(得分:2)
你总是指向字符数组,这是一个堆栈变量,它只在函数范围内本地分配,可能每个字符串声明都与你循环中前一次迭代的地址相同。你可以代替使用字符数组分配内存每个循环迭代或使用数组然后使用ie strdup为你的新字符串分配内存,如
slowa[j] = strdup(string) :
答案 2 :(得分:0)
正如其他人所说,你需要创建字符串的副本,否则你将字符串设置为相同的地址,因此它们只是相互覆盖。
此外,我认为使用fgets
而不是gets
是一种更安全的方法。这是因为gets
非常容易buffer overflow,而使用fgets
,您可以轻松检查缓冲区溢出。
这是我前一段时间编写的一些代码,类似于你想要实现的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PTRS 3
#define STRLEN 30
int
string_cmp(const void *a, const void *b) {
const char *str1 = *(const char**)a;
const char *str2 = *(const char**)b;
return strcmp(str1, str2);
}
int
main(void) {
char *strings[PTRS];
char string[STRLEN];
int str;
size_t len, i = 0;
while (i < PTRS) {
printf("Enter a string: ");
if (fgets(string, STRLEN, stdin) == NULL) {
fprintf(stderr, "%s\n", "Error reading string");
exit(EXIT_FAILURE);
}
len = strlen(string);
if (string[len-1] == '\n') {
string[len-1] = '\0';
} else {
break;
}
strings[i] = malloc(strlen(string)+1);
if (strings[i] == NULL) {
fprintf(stderr, "%s\n", "Cannot malloc string");
exit(EXIT_FAILURE);
}
strcpy(strings[i], string);
i++;
}
qsort(strings, i, sizeof(*strings), string_cmp);
printf("\nSuccessfully read strings(in sorted order):\n");
for (str = 0; str < i; str++) {
printf("strings[%d] = %s\n", str, strings[str]);
free(strings[str]);
strings[str] = NULL;
}
return 0;
}