![見出し画像](https://assets.st-note.com/production/uploads/images/93349725/rectangle_large_type_2_641b0f47df201097afcf052bc8d300fd.jpeg?width=1200)
回答してみました ~ C言語教室 第7回 - 動的なメモリ割り当て ~
こちらの課題を回答してみました。
早速。
回答
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* salloc(char* str)
{
size_t l = strlen(str);
char* _s = malloc(l+1);
if (_s != NULL)
{
strncpy(_s, str, l);
_s[l] = '\0';
}
return _s;
}
void sfree(char* _s)
{
if (_s != NULL)
{
free(_s);
}
}
ちょこっと解説
文字列関連の標準関数を使ってしまった。
「strlen」の結果をチェックしようか(0より大きいかどうか)と思ったけど、「+1」して「malloc」するので、まぁいいかと。文字列が空だったら、空の文字列のポインタを返すだけだし。あまり簡単に NULL を返すのもどうかと思うし。
「NULL」と「\0」使い分けがあってるのかどうか。
「sfree」は課題にはないのですが、私はこのように対になる関数を作ることが多いです。今回は特に、いちいち「NULL」チェックをしたくなかったし。「salloc」の仕様が変わっても概ね「salloc」「sfree」内で対応できるでしょうし。
テストプログラム
int main()
{
{
char* s = "abc";
char* _s;
_s = salloc(s);
printf("0x%016lx %s\n", (unsigned long)s, s);
printf("0x%016lx %s\n", (unsigned long)_s, _s);
printf("\n");
sfree(_s);
}
{
char* s = "";
char* _s;
_s = salloc(s);
printf("0x%016lx %s\n", (unsigned long)s, s);
printf("0x%016lx %s\n", (unsigned long)_s, _s);
printf("\n");
sfree(_s);
}
{
char a = 0;
char* s = &a;
char* _s;
_s = salloc(s);
printf("0x%016lx %s\n", (unsigned long)s, s);
printf("0x%016lx %s\n", (unsigned long)_s, _s);
printf("\n");
sfree(_s);
}
{
char a[5] = {1, 2, 3, 0x34, 5};
char* s = a;
char* _s;
_s = salloc(s);
printf("0x%016lx %s\n", (unsigned long)s, s);
printf("0x%016lx %s\n", (unsigned long)_s, _s);
printf("\n");
sfree(_s);
}
return 0;
}
テスト結果
~/c $ ./a.out
0x000000634aaf3631 abc
0xb40000772bd7d230 abc
0x000000634aaf3630
0xb40000772bd7d230
0x0000007fc73e92d7
0xb40000772bd7d230
0x0000007fc73e92b8 4
0xb40000772bd7d230 4
~/c $
徹底的にテストしたとは言い難いけど。
めっちゃ長い文字列とか、「malloc」に失敗するようなケースは挙げられていません。
「malloc」で失敗するのは難しいだろうから、テスト用の「malloc」でやるしかないのかも。
最後のケースはちょいいじめてみた。
補足
せっかくコメントいただいたので補足。
「strncpy」のコピー範囲
「strncpy」は NULL がコピーされないんですね。
だから、「_s[l] = '\0';」が必要です。
初めての方は間違えやすいかも?
「free」は NULL を保証
関数「free」では NULL が保証されているのだそうです。ですから関数「sfree」では NULL チェックは不要ですね。
ご指摘ありがとうございました。
この記事が気に入ったらサポートをしてみませんか?