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
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
元のトピックから遠く離れてしまいましたが、これは、この場合、文字列が2 回正しくゼロで終了していることを意味します。これを回避するには、コードを「カット アンド ペースト セーフ」バージョンに書き直すことができます。また、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
になり、それが削除された場合、文字列は使用可能な状態のままになります。