文字配列 s に格納された文字列の 2 倍の長さの文字列をちょうど格納できるサイズの文字配列を動的に割り当て, そこに s 中の文字列を 2 回繰り返したものをコピーし, その文字配列の先頭要素へのポインタを返す関数を作成
ただし、strcpy と strcat を用いてはならない.
(例)
元の文字列 : abc
書き換えた文字列 : abcabc
下記が今かけているプログラムなのですが、
これだと文字列はそのまま表示されてしまいます。
改善点を教えていただけないでしょうか?
c言語
1#include<stdio.h> 2#include<stdlib.h> 3#include<string.h> 4 5char *strdouble(char s[]){ 6 7 char *d = NULL; 8 int i; 9 10 //sの長さ*2の文字配列を割り当てる 11 d = (char *)malloc(sizeof(char)*(strlen(s) + strlen(s))); 12 13 for(i = 0; s[i]!= '\0'; i++){ 14 15 d[i] = s[i]; 16 } 17 18 d[i] = '\0'; 19 20 return d; 21} 22
ちなみにmainプログラムは下記になります。
mainプログラムの修正はしてはいけないです。
c言語
1#include <stdio.h> 2#include <stdlib.h> 3#define SLEN 126 4#define SFMT "%126s" 5 6char *strdouble(char s[]); 7 8int main(void) 9{ 10 char s[SLEN+1]; 11 char *s2 = NULL; 12 13 for (;;) { 14 fprintf(stderr, "s = "); 15 if (scanf(SFMT,s)==EOF) { break; } 16 s2 = strdouble(s); 17 printf("%s\n",s2); 18 free(s2); 19 s2 = NULL; 20 } 21 22 return 0; 23}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/11/16 07:30
2019/11/16 07:30
2019/11/16 07:31
2019/11/16 07:54
2019/11/16 08:24
2019/11/16 09:39
2019/11/16 09:54
2019/11/16 23:27
回答4件
0
C
1char *strdouble(const char *s) 2{ 3 char *d = malloc(strlen(s) * 2 + 1); 4 if (d) sprintf(d, "%s%s", s, s); 5 return d; 6}
投稿2019/11/17 04:32
総合スコア8224
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
先の回答者であるLouiS0616さんのご指摘に加えて、目には見えていませんが、大事なことをひとつ忘れています。
C
1d = (char *)malloc(sizeof(char)*(strlen(s) + strlen(s)));
の部分で、末端に\0
文字を入れる分が足りていません。
(誤認により削除)更に細かい点を指摘すると、 ですので、sizeof(char)*(strlen(s)
でchar
型のバイト数を意識している割には、+ strlen(s)
の方では考慮されていません。
C
1d = (char *)malloc(sizeof(char)*(strlen(s) + strlen(s)) + sizeof(char)); 2 3またはいっそ、 4 5d = (char *)malloc((strlen(s) * 2) + 1);
と言ったところでしょうか。
投稿2019/11/16 07:42
編集2019/11/16 08:02総合スコア9254
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/11/16 07:46
2019/11/16 07:50
2019/11/16 07:55
2019/11/16 08:04
2019/11/16 08:07
0
ベストアンサー
C
for(i = 0; s[i]!= '\0'; i++){
d[i] = s[i];
}
一周分しかコピーしていないように見えます。
iの値を保持したまま、この処理を二回繰り返すように書き換えれば良いです。
またmallocを使う際は、領域が確保できているか確認するようにすると良いでしょう。
####返り値
関数 calloc() と malloc() は、割り当てられたメモリーへのポインターを返す。 割り当てられたメモリーは、あらゆる組み込み型に対応できるようにアラインメントされる。 エラーの場合、これらの関数は NULL を返す。
引用元: Man page of MALLOC
コードの貼り方について
teratailには、コードを見やすく表示する機能があります。
質問編集画面を開き、コードを選択した状態で<code>ボタンを押して下さい。
投稿2019/11/16 07:23
編集2019/11/16 07:28総合スコア35668
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/11/16 07:29
2019/11/16 07:33
2019/11/16 07:34 編集
2019/11/16 07:37
2019/11/16 07:44
2019/11/16 07:44
2019/11/16 07:50
2019/11/16 07:51
2019/11/16 07:56
2019/11/16 07:56
2019/11/16 08:01
2019/11/16 08:06
2019/11/16 08:14
2019/11/16 08:20
2019/11/16 08:36 編集
2019/11/16 08:38
2019/11/16 10:24 編集
2019/11/18 08:12
2019/11/18 12:32
2019/11/19 02:01
2019/11/19 03:00 編集
2019/11/19 03:09
2019/11/19 03:40 編集
2019/11/19 07:19
2019/11/19 07:29
2019/11/19 08:48
2019/11/19 08:49
2019/11/19 08:57
2019/11/19 23:40
2019/11/20 01:37
2019/11/20 02:19
2019/11/20 02:23
2019/11/20 06:46
2019/11/20 06:52
2019/11/20 06:56 編集
2019/11/20 06:56
2019/11/20 07:01
2019/11/20 07:14
2019/11/20 07:54
0
考えられるだけの改善点をあげてみました。
C
1// #includeと<の間はスペースを入れる 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5#include <stdint.h> 6 7// assert用 8// テスト時はこのままにし、本番ではコメントアウトを外す 9// #defien NDEBUG 10#include <assert.h> 11 12// 本来はヘッダ部分を分離して、それ読み込むが、 13// 今回はmainの方に直接書いてあるため、個々に書く。 14// mainと同じファイルに書く場合はこの部分は不要 15#define SLEN 126 16 17/** 18 * 受け取った文字列を二回表示にして返す。 19 * 引数は`SLEN`文字以下のnull終端文字列で無ければならない。 20 * そうで無い場合の動作は未定義とする。(何が起こるかは不明) 21 * この関数呼び出し時は、プログラム実行時は十分なメモリが存在し、 22 * malloc等の処理が失敗しない状態で無ければならない。 23 * メモリが不十分で、malloc等が失敗する場合の動作は未定義とする。 24 * これらの条件をつけた経緯はrubato6809さんのコメントを参考にすること。 25 */ 26 27// ループ変数を除き一文字のみの変数名や引き数名は避ける。 28char *strdouble(char str[]) { // ) {の間はスペースを入れる。 29 // ローカル変数は必要になったときに宣言する。 30 // 関数の先頭でまとめて宣言しない。 31 32 // strlen()は重い処理のため、呼び出しは一回のみにするように変数に入れる。 33 // strlen()の戻り値はsize_t型。 34 size_t len = strlen(str); 35 36 // 確保するメモリはlenの2倍に1足した数だが、その値がSIZE_MAXを越える場合、 37 // その計算がオーバーフロー起こす可能性がある。 38 // 受け取る引数の文字列の長さに制限が無い場合は、 39 // あらかじめSIZE_MAXを越えないかを確認しておく 40 // しかし今回は、SLENによってサイズの最大サイズが固定であるため、 41 // SLENによって条件を満たさない場合があるかの確認をテスト時のみ行う。 42 // NDEBUGが有効の場合は下記はコンパイル時に除外される。 43 assert(SERN <= (SIZE_MAX - 1) / 2) 44 45 // strの長さ(len)の2倍に1足した大きさの文字配列を割り当てる 46 // null終端文字列は終端null文字分のために、文字列の長さに+1だけ大きさが必要。 47 // 変数名はわかりやすい名前を付ける。 48 // 宣言と同時に代入する。関数の最初で宣言はしない。 49 // sizeof(char)は例外なく必ず1である。charの場合は書かない。 50 char *double_str = (char *)malloc(len * 2 + 1); 51 52 // メモリが十分に確保されていることが保証できなければ、 53 // mallocしたら必ず戻り値がNULLでないかを確認する必要がある。 54 // しかし、rubato6809さん曰く「まずエラーになりません。」となっている。 55 // SLENのサイズが小さくても、空きメモリが極めて少ない状態でプログラムを 56 // 実行した等の特殊な状況においては、失敗する恐れがあるが、 57 // 今回は、そのような場合は動作未定義として、チェックはしないこととする。 58 59 // for文等でちまちまと代入せずにmemcpy()を使う。 60 // 実装にもよるがmemcpy()はある程度のバイト列ごとにまとめてコピーするため、 61 // 長い文字列では、1文字ずつコピーするよりも数倍の速度差が出る可能性がある。 62 // destとsrcがオーバーラップすることは無いため、memmove()にする必要は無い。 63 memcpy(double_str, str, len); 64 65 // lenだけズレた位置にもう一度コピーする。 66 // 終端null文字も含めるために、lenに+1した分をコピーする。 67 memcpy(double_str + len, str, len + 1); 68 69 // あとはdouble_strを返すだけ、お疲れ様でした。 70 return double_str; 71}
投稿2019/11/16 10:19
編集2019/11/17 06:03総合スコア21737
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/11/16 23:18
2019/11/17 02:51
2019/11/17 03:05
2019/11/17 04:48 編集
2019/11/17 06:16 編集
2019/11/17 06:56 編集
2019/11/17 07:14
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。