为什么星号三角形不能大于 23?

  • 本文关键字:不能 大于 三角形 c
  • 更新时间 :
  • 英文 :


我目前正在学习C编程,并通过一个简单的练习。

请参阅此代码:

#include<stdio.h>
#include<stdlib.h>
char* nstars(int n);
int main(void)
{
int sn;
printf("Number of stars: ");
scanf("%d", &sn);
for(int i = 1; i <= sn; i++)
{
printf("n%s", nstars(i));
}
return 0;
}
char* nstars(int n)
{
char* starstr = (char*) calloc(n, sizeof(char));
for(int nt=0; nt < n; nt++)
{
starstr[nt] = '*';
}
return starstr;
}

上面的代码将打印如下内容

sn=4
*
**
***
****

代码工作正常,直到sn高于 23。它开始打印出奇怪的字符。

为什么会这样?我该如何解决?

您没有正确终止starstr字符串 - 直到您达到大小 23,恰好starstr的最后一个元素之后紧跟着一个 0 值字节,所以看起来它到目前为止工作正常。

n 个字符的字符串需要存储在至少n+1 个元素宽的数组中,以考虑终止符,因此您需要像这样调整calloc调用:

char *starstr = calloc( n + 1, sizeof *starstr );

一些注意事项 - 首先,从 C891开始,calloc上的强制转换是不必要的,如果您使用的是 C89 编译器2,则可以抑制有用的诊断。 其次,您可以在目标上使用sizeof来获取正确的类型大小 -表达式*starstr的类型为char,因此sizeof *starstr等效于sizeof (char)。 根据定义,sizeof (char)是 1,因此严格来说,您可以用文字1替换所有这些字符,但是这样,如果您决定使用像wchar_t这样的"宽"字符类型,则不必更改calloc调用本身。

最后,正如所写的那样,这段代码有一个相当讨厌的内存泄漏 - 每次调用nstars时都会分配一个新数组,但完成后不会解除分配它。

坦率地说,您不需要为每行分配一个新数组 - 以最终大小分配一次数组(+1 以考虑终止符(,然后在末尾添加新的星号:

int main( void )
{
...
char *starstr = calloc( n + 1, sizeof *starstr );
/**
* ALWAYS check the result of a malloc, calloc, or realloc call.
*/
if ( !starstr )
{
fprintf( stderr, "Could not allocate memory for string - exitingn" );
exit( 0 );
}
for ( int i = 0; i < n; i++ )    // Each time through the loop, add an
{                                // asterisk to the end of starstr,
starstr[i] = '*';              // then print starstr.  
printf( "%sn", starstr );
}
free( starstr );
...
}

由于calloc将分配的内存清零,因此在添加新星号后无需显式写入字符串终止符。 如果你改用malloc,你需要写

starstr[i] = '*';
starstr[i+1] = 0;
printf( "%sn", starstr );


  1. 这在C++中是必需的,但是如果你C++写作,你不应该使用malloccallocrealloc,除非你真的需要弄脏你的手。
  2. C89 允许隐式int声明,因此,如果您忘记包含stdlib.h,或者没有在作用域中calloc声明,编译器将假定它返回了一个int,并在您尝试将结果分配给指针时发出诊断。 但是,如果将结果强制转换为指针,则编译器不会发出诊断,并且可能会出现运行时错误。 C99 及更高版本不再允许隐式int声明,因此这个特定问题不再是问题,但最好还是不要使用强制转换。 它使代码更易于阅读和维护。

只需为calloc输入n + 1

还有:不要忘记free

char *必须以"\0"结尾,因此您需要分配大小 + 1

#include<stdio.h>
#include<stdlib.h>
char* nstars(int n);
int main(void)
{
int sn;
printf("Number of stars: ");
scanf("%d", &sn);
for(int i = 1; i <= sn; i++)
{
char *str = nstars(i);
printf("n%s", str);
free(str);
}
return 0;
}
char* nstars(int n)
{
char* starstr = (char*) calloc(n + 1, sizeof(char));
for(int nt=0; nt < n; nt++)
{
starstr[nt] = '*';
}
return starstr;
}

最新更新