Arrays 在C中使用字符/字符串指针会产生奇怪的输出

Arrays 在C中使用字符/字符串指针会产生奇怪的输出,arrays,c,string,pointers,char,Arrays,C,String,Pointers,Char,我正在尝试生成以下输出: 0.1 0.12 0.123 0.1234 ... 0.123456789 我的代码使用字符串/字符数组和一些我不熟悉的指针数据类型 代码取自以帮助入门,但我得到以下乱七八糟的输出 代码如下: #include <stdlib.h> #include <string.h> #include <stdio.h> int main() { char *str = "0."; char d

我正在尝试生成以下输出:

0.1

0.12

0.123

0.1234

...

0.123456789
我的代码使用字符串/字符数组和一些我不熟悉的指针数据类型

代码取自以帮助入门,但我得到以下乱七八糟的输出

代码如下:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main()
{
    char *str = "0.";
    char digit = '0';

    size_t len = strlen(str);

    int i = 1;


    while(i<10)
    {
        printf("i: %d\n",i);
    
        char *temp = malloc(len + 1 + 1);
    
        len = strlen(temp);
    
        digit = i + '0';
    
        temp[len] = digit;
    
        char string[len];
    
        strcpy(string,temp);
    
        free(temp);
    
        printf("%s\n\n",string);
    
        i = i +1;
    }
}
#包括
#包括
#包括
int main()
{
char*str=“0。”;
字符数字='0';
尺寸长度=strlen(str);
int i=1;

正如@ismick所提到的(i,
temp
指向未初始化的内存,因此可以包含任何内容。更安全的方法是使用
calloc
,特别是对于
0
终止的字符串,如C

使用
sprintf
比使用
strcpy
要简单得多

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main()
{
    char *str = "0.";

    size_t len = 2;

    for (int i = 1; i < 10; i++) {
        printf("i = %d\n", i);                                                                            
        len = len + 2;

        char *temp = calloc(len, sizeof(char));
        sprintf(temp, "%s%d", str, i); 
        if (i > 1) free(str); // string literal when i=1
        str = temp;
        printf("%s\n\n", str);
    }
    free(str);
}
#包括
#包括
#包括
int main()
{
char*str=“0。”;
尺寸长度=2;
对于(int i=1;i<10;i++){
printf(“i=%d\n”,i);
len=len+2;
char*temp=calloc(len,sizeof(char));
sprintf(温度,“%s%d”,str,i);
if(i>1)free(str);//当i=1时的字符串文字
str=温度;
printf(“%s\n\n”,str);
}
自由基(str);
}
这里有一些新东西:
for(inti=1;i<10;i++)
for(inti=1;i<10;i=i+1)
是一个方便的常用构造快捷方式

int i = 1;

while (i < 10) {
  ....
  i = i + 1;
}
inti=1;
而(i<10){
....
i=i+1;
}
我们使用
calloc
获取指向用
0
初始化的内存块的指针;第二个
sizeof(char)
参数告诉我们获取适合
len
-many
char
的块

我们使用
sprintf(temp,“%s%d”,str,i);
来轻松地将
str的上一个值复制到这个新的内存块中,再加上下一个数字,例如
0。
~>
0.1
0.12
~>
0.123

最后,我们将
str=temp;
设置为指向
str
temp
的开头,这样我们就不会丢失刚才使用
sprintf
创建的复制/连接字符串

编辑:添加有关代码的注释

编辑2:修复了注释中指出的双
免费

正如@ismick提到的,
temp
指向未初始化的内存,因此可以包含任何内容。更安全的方法是使用
calloc
,特别是对于
0
终止的字符串,如C

使用
sprintf
比使用
strcpy
要简单得多

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main()
{
    char *str = "0.";

    size_t len = 2;

    for (int i = 1; i < 10; i++) {
        printf("i = %d\n", i);                                                                            
        len = len + 2;

        char *temp = calloc(len, sizeof(char));
        sprintf(temp, "%s%d", str, i); 
        if (i > 1) free(str); // string literal when i=1
        str = temp;
        printf("%s\n\n", str);
    }
    free(str);
}
#包括
#包括
#包括
int main()
{
char*str=“0。”;
尺寸长度=2;
对于(int i=1;i<10;i++){
printf(“i=%d\n”,i);
len=len+2;
char*temp=calloc(len,sizeof(char));
sprintf(温度,“%s%d”,str,i);
if(i>1)free(str);//当i=1时的字符串文字
str=温度;
printf(“%s\n\n”,str);
}
自由基(str);
}
这里有一些新东西:
for(inti=1;i<10;i++)
for(inti=1;i<10;i=i+1)
是一个方便的常用构造快捷方式

int i = 1;

while (i < 10) {
  ....
  i = i + 1;
}
inti=1;
而(i<10){
....
i=i+1;
}
我们使用
calloc
获取指向用
0
初始化的内存块的指针;第二个
sizeof(char)
参数告诉我们获取适合
len
-many
char
的块

我们使用
sprintf(temp,“%s%d”,str,i);
来轻松地将
str的上一个值复制到这个新的内存块中,再加上下一个数字,例如
0。
~>
0.1
0.12
~>
0.123

最后,我们将
str=temp;
设置为指向
str
temp
的开头,这样我们就不会丢失刚才使用
sprintf
创建的复制/连接字符串

编辑:添加有关代码的注释

编辑2:修复了评论中指出的双
免费

正如@isrnick已经指出的,问题是您分配了内存,但在调用
strlen
之前没有对其进行初始化

一般来说,在内存分割堆时重复分配/释放内存不是一个好主意。最好在开始时分配一次,然后重用内存,最后释放内存

更好、更整洁的解决方案是将其保留在堆栈上:


正如@isrnick已经指出的,问题在于您分配内存,但在调用
strlen
之前不初始化它

一般来说,在内存分割堆时重复分配/释放内存不是一个好主意。最好在开始时分配一次,然后重用内存,最后释放内存

更好、更整洁的解决方案是将其保留在堆栈上:


temp
指向
malloc
分配的内存,但内存中未存储字符串,因此
strlen(temp)
将产生一些随机值…
temp
指向
malloc
分配的内存,但内存中未存储字符串,因此
strlen(temp)
将导致一些随机值…遗憾的是,我忘记了在for循环的最后一行执行
空闲(temp)
,然后执行
空闲(str)
在main的末尾!这会崩溃,你会释放str两次。当str仍然指向free'd
temp
时,你也会使用
str
,因此它会产生有趣的输出。你是对的!我先编译了它,但没有任何空闲,它会产生预期的输出。然后我不小心尝试在手机上修复它。谢谢。很遗憾,我忘了e> free(temp)
在for循环的最后一行,然后
free(str)
在main的末尾!这会崩溃,您会释放str两次。当str仍然指向free的
temp
时,您也会使用
str
,因此它是专业的