プロが教えるわが家の防犯対策術!

C言語習得中の文系学生です。現在、データ構造(リンクリスト、ツリー構造)を勉強中です。
勉強用にプログラムを組んでるのですが、構造体メンバに文字列を代入し出力する関数で予想とは違う結果が出てしまいました。思いつく限りの方法は試しましたが、状況は変わりませんでした。

先に、予想した実行結果と実際の実行結果を載せます。

char型配列data[32]に入力文字列を代入し出力した時
・予想した結果
入力: abcdefgh
出力: abcdefgh

・実際の結果
入力: abcdefgh
出力: abc

次にコードと実行結果を載せます。
上記の通り、与えられた文字をそのまま出力するだけのプログラムです。
質問投稿用にメンバの量は1つにしました。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>

#define MAX_DATA 32

struct memb{

char s[MAX_DATA];
}k;

void input_c(char *data){

data = (char *)malloc( sizeof(char)*32 );
printf("Size is %d\n",malloc_usable_size(data));

puts(">>> ");
fgets(data,sizeof(data),stdin);
sscanf(data,"%s",data);

  printf("DATA is %s\n",data);
}

int main(void){


input_c(k.s);
printf("Inputted Data : %s\n",k.s);

return 0;
}

--------------------------------------------
実行結果
Size is 36
>>>
abcdefgh
DATA is abc
Inputted Data :


以上です。
こういう状態になってしまう原因がどこにあるのか、何がそうさせているのかについて、
どうかご教授のほど宜しくお願い致します。

A 回答 (4件)

>xを0で初期化


>xをパラメータとしてinput関数に渡す
>5を入力
>ここでスタックには0がプッシュされたままで5がプッシュされる

実際に動かしてみた方がわかると思いますが……。

スタックがどうとかはこの場合関係ないです。
ローカル変数の値がどうなるか?です。

質問に掲示されたヤツだと…ポインタ使うのでそれぞれ下記のようにしてみてはどうですかね?

input_c(k.s);
の前に
printf("k.s Address 0x%p\n", k.s);
でk.sのアドレスを表示してみる。

data = (char *)malloc( sizeof(char)*32 );
の前後で
printf("data Address 0x%p\n", data);
でdataの指す先がどう変化するか確認する。

sizeof()がおかしいのは既に指摘されてます。
# 配列のポインタを引数にして関数コールしてもコールされた側ではその配列のサイズを知る手段がありません。
# 引数でサイズも渡す。というのがよくある方法です。

>sscanf(data,"%s",data);

取り出し元と書き出し先が同一領域で問題ないのか?
については確認が必要かも知れません。
まぁ、仮に大丈夫だったとしても上記の処理では意味がありませんが。(ホワイトスペースで読み取りが終わる…かな?)

ちなみに…input_c()の中でメモリリーク起きてます。
# malloc()で取得したヒープはいつ解放はてます?
# 答え:プロセスが終了した時にOSが回収する。
#    じゃあ、プロセスが終了しない場合はどうなるでしょうかね。
    • good
    • 0

sizeof(data)がおかしい。



dataはmallocしたバッファへのポインタであってバッファそのものではないからsizeof(data)はバッファ長ではなくポインタのサイズ。

このシステムでは32ビットだったので4が返ってきたのだろう。

よってfgets(data,sizeof(data),stdin);では
'a','b','c',0x00が入る。
    • good
    • 0
この回答へのお礼

>dataはmallocしたバッファへのポインタであってバッファそのものではないからsizeof(data)はバッファ長ではなくポインタのサイズ。

全くその通りです・・・ありがとうございました!!

お礼日時:2013/06/19 01:44

すみません, #1 の最後の行はゴミなので無視してください.



ちなみに「質問のプログラムではポインタを渡しているので #1 のプログラムとは違う」という指摘は却下.

この回答への補足

わかりそうでわかりませんが・・・

5を入力した時の実行結果





xを0で初期化
パラメータとして渡す5
スタックには0がプッシュされたままで5がプッシュされる
input関数で5を出力
main関数で5を出力
(ここまででスタックから5がポップされる)
最後に残った0がポップされ出力される

ということでしょうか・・・
これが正しいとした上での質問ですが、これはprintf関数によるものですか?
スタックだのヒープだのよくわからないんです…
もしご存知であれば参考書やホームページ等を教えていただけますか?

補足日時:2013/06/19 00:47
    • good
    • 0
この回答へのお礼

一部打ち間違えたまま投稿してしまいました
すみません
訂正します

xを0で初期化
xをパラメータとしてinput関数に渡す
5を入力
ここでスタックには0がプッシュされたままで5がプッシュされる
input関数で5を出力
main関数で5を出力
(ここまででスタックから5がポップされる)
最後に残った0がポップされ出力される

以上訂正です。

お礼日時:2013/06/19 01:05

#include <stdio.h>



void input(int x)
{
scanf("%d", &x);
printf("%d\n", x);
}

int main()
{
int x = 0;
input(x);
printf("%d\n", x);
return 0;
}
というプログラムは, どう動くでしょうか?
printf("
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!