在 C 中,您还需要处理您使用的内存。因此,如果您想要一个“---”字符串,您还需要为该字符串分配空间。一旦分配了空间,您将用给定的字符填充它。
之后,您必须释放该区域。
所以:
char *charmul(char c, int n)
{
int i;
char *buffer; // Buffer to allocate
buffer = malloc(n+1); // To store N characters we need N bytes plus a zero
for (i = 0; i < n; i++)
buffer[i] = c;
buffer[n] = 0;
return buffer;
}
然后我们需要添加错误检查:
char *charmul(char c, int n)
{
int i;
char *buffer; // Buffer to allocate
buffer = malloc(n+1); // To store N characters we need N bytes plus a zero
if (NULL == buffer)
return NULL;
for (i = 0; i < n; i++)
buffer[i] = c;
buffer[n] = 0;
return buffer;
}
您的来源将变为:
#include <stdio.h>
// charmul here
int main (void)
{
int height=0;
int n=0;
char symbol='#';
printf("Height: ");
scanf("%d",&height);
n=height+1;
while (n>=2)
{
char *s;
s = charmul(symbol, n);
printf("%s\n", s);
free(s); s = NULL;
n=n-1;
}
return 0;
}
另一种实现将寻求减少malloc
' 的数量,以提高性能。为此,您还需要向函数传递一个指向前一个缓冲区的指针,如果更短,则可以回收而无需进一步malloc
的 ,如果更长,将被free
'd 并重新分配(或者可以使用realloc
)。然后,您将free()
只执行最后一个未回收的值:
char *charmul_recycle(char c, int n, char *prevbuf)
{
int i;
if (prevbuf && (n > strlen(*prevbuf)))
{
free(prevbuf); prevbuf = NULL;
}
if ((NULL == prevbuf)
{
prevbuf = malloc(n+1); // To store N characters we need N bytes plus a zero
if (NULL == prevbuf)
return NULL;
}
for (i = 0; i < n; i++)
prevbuf[i] = c;
prevbuf[n] = 0;
return prevbuf;
}
char *buffer = NULL;
while(n > 2)
{
buffer = charmul_recycle(symbol, n, buffer);
if (NULL == buffer)
{
fprintf(stderr, "out of memory\n");
abort();
}
printf("%s\n", buffer);
n--;
}
当然,整个事情可以通过单个直接分配和逐步缩短字符串(通过设置s[n]
为零)来完成,但是我们不会使用“生成多个字符”功能:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void)
{
char *string;
int height=0;
int n=0;
char symbol='#';
printf("Height: ");
scanf("%d",&height);
n=height+1;
string = malloc(n); // allocate just enough memory (n is height+1)
memset(string, symbol, n); // fill string with symbols
while (--n) // with n ever decreasing...
{
string[n] = 0; // Truncate string after n characters
printf("%s\n", string); // output string
}
free(string); // string = NULL; // finally free the string
return 0;
}
更新(感谢 Jonathan Leffler):上面,有一个潜在的危险“过度优化”。在每次使用 之前string
,string
正确地以零结尾(“ string[n] = 0;
”)。但是,我已经分配了一个字符串变量并用东西填充它,并且没有立即零终止它,这仍然是事实。在上面的代码中,一切都很完美。这仍然是不好的编码实践,因为如果代码被重用并删除了循环,并且字符串用于其他目的(在这种情况下不太可能,但仍然......),未终止的string
可能会成为一个微妙的错误。
最快的解决方法是在分配后终止:
string = malloc(n); // allocate just enough memory (n is height+1)
memset(string, symbol, n-1); // fill string with symbols
string[n-1] = 0; // zero-terminate string
我现在偏离了原始主题,但这意味着在这种情况下,字符串正确地以零结尾两次。为避免这种情况,可以将代码重写为“剪切和粘贴安全”版本,还可以更清楚地显示额外的零作为 n 的添加:
n=height; // Number of characters
string = malloc(n+1); // Allocate memory for characters plus zero
memset(string, symbol, n); // Store the characters
string[n] = 0; // Store the zero
while (n) // While there are characters
{
printf("%s\n", string); // Print the string
string[--n] = 0; // Reduce it to one character less than before
}
该循环现在接受任何具有有意义的有效字符串n
,如果将其删除,则该字符串将保持可用状态。