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

时间:2018-10-08 13:43:34

标签: 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为止,代码才能正常工作。它将开始打印出奇怪的字符。

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

2 个答案:

答案 0 :(得分:2)

只需将n + 1替换为calloc

还有:不要忘记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;
}

答案 1 :(得分:2)

您没有正确终止using字符串-直到达到大小23为止,恰好发生是紧随{{1 }},直到现在为止看起来一切正常。

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

starstr

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

最后,按照编写的代码,此代码将发生相当多的内存泄漏-每次调用wchar_t时都在分配一个新数组,但完成后并不会取消分配它。

坦率地说,您不必为每行分配一个新数组-以最终大小(为结束符分配为+1)分配一次一次,然后向其中添加一个新星号结束:

calloc

由于nstars将分配的内存清零,因此在添加新的星号后,无需显式编写字符串终止符。如果您改用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 - exiting\n" ); 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( "%s\n", starstr ); } free( starstr ); ... } ,则需要编写

calloc


  1. 在C ++中是必需的,但是如果您在编写C ++,则除非真正使用 ,否则不应使用mallocstarstr[i] = '*'; starstr[i+1] = 0; printf( "%s\n", starstr ); malloc需要弄脏你的手。
  2. C89允许隐式calloc声明,因此,如果您忘记包含realloc或在范围内没有int的声明,则编译器会假定它返回stdlib.h,如果您尝试将结果分配给指针,则会发出诊断信息。但是,如果将结果强制转换为指针,则编译器不会发出诊断信息,并且可能会遇到运行时错误。 C99和更高版本不再允许隐式calloc声明,因此此特定问题不再是问题,但最好还是放弃。它使代码更易于阅读和维护。