プロが教える店舗&オフィスのセキュリティ対策術

fscanfで格納された変数がおかしいです。
ダブルポインタで定義した変数にfscanfでファイルから文字列データを読み込んでいるのですが
表示がおかしな事になっています。

読み込んだファイルの内容は、

aiueo
kakikueko
sasisuseso
tatituteto

です。
表示された結果が
kakikueko
sasisuseso
tatituteto
kakisasitatituteto
sasitatituteto
tatituteto
自分では解決しずらいのでここで質問をさせて頂くことになりました。
C/C++で記述してあるのですが、以下にソースを載せておきますのでご指摘ください。
/*

double pointa

*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 256

char** size;

// TEST
void test(void)
{
for(int l = 0; l < 3; l++) {
printf("\n%s", &size[l]);
}
}

int main()
{
FILE* fp;
int c = -1;
char moji[MAXSIZE];

if((fp = fopen("test.txt","rb")) == NULL) {
printf("error");
exit(1);
}

while(fscanf(fp,"%s",moji) != EOF) c++;

size = (char**)malloc(sizeof(char) * MAXSIZE * c);
// 初めに戻す
fseek(fp, 0, SEEK_SET);
// 最初の文だけ取り出す
fscanf(fp,"%s",moji);
// 一文を格納する
for(int l = 0; fscanf(fp, "%s", &size[l]) != EOF; l++) {
printf("\n%s", &size[l]);
}

printf("\n");
test();
fclose(fp);

getchar();
free(size);
return 0;
}
test関数内で表示するとおかしな結果がでるのですが何故かわかりません。
よろしくお願いします。

A 回答 (8件)

どうもめちゃくちゃ書きすぎてました & 最後まで動かしてなかった



まず #4 にしたがった修正するなら char ** では無くて char * としてください

どうしてもchar** にしたいのであれば
>size = (char**)malloc(sizeof(char) * MAXSIZE * c);
の部分を
size = (char**)malloc(sizeof(char *) * MAXSIZE * c);
とする必要があります
ただしこの場合実際に格納しているのはファイルの読み取りデータであって
確保した変数名と型が一致してないのでとっても分かりずらいプログラムになります

今度一応ちゃんとプログラム通したから合ってるはず・あっててくれ
    • good
    • 0
この回答へのお礼

>まず #4 にしたがった修正するなら char ** では無くて char * としてください
コンパイルしたら無事にできました。
普通のポインタでのやり方でも問題なくできそうですね。

>どうしてもchar** にしたいのであれば
こっちの方も無事にできました。
ダブルポインタにたいしてもっと勉強しておこうと思います。
何より無事に解決できました。

お礼日時:2010/01/30 14:31

どうでもいいけど、



誤:見ずらい、分かりずらい
正:見づらい、分かりづらい

見たり分かったりするのが「つらい」のです。
見たり分かったりするのが「すらい」のではありません。

# 変換の際に警告が出ないのかな?
    • good
    • 0
この回答へのお礼

つらい○ すらい×ですね。^^;
誤字脱字には気をつけておきます。

お礼日時:2010/01/30 14:12

Microsoft VSコンパイラで同様のエラーメッセージが確認できました。


error C2440: '=' : 'char *' から 'char (*)[256]' に変換できません。

そうなら、行番号も分かっているので、機械的に
(char*)malloc();
から
(char(*)[MAXSIZE])malloc();

gcc -std=C99 ではWエラーでしたので、一発正解にならなくてすみません。
にしても、結局Microsoftのエラーメッセージは親切ですね。
    • good
    • 0
この回答へのお礼

なるほど。
char (*)[MAXSIZE]で char *size[MAXSIZE]に対応することができるんですね。
冷静に考えれば、 配列へのポインタ型ですから当然ですよね。
回答ありがとうございます。

お礼日時:2010/01/30 14:21

こんちには、初投稿なのでインデントのしかたが分からなくて見ずらいかも知りません、ご勘弁を。


ポインタの配列つまりダブルポインタと、2次元配列の区別を勉強しするといいです。
コメントの//側を採用しても同じ動作です、理由は私も詳しくは知りませんが、&は付けなくて大丈夫です。
/*

double pointa

*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 256

//char** size;
char (*size)[MAXSIZE];

// TEST
void test(void)
{
for(int l = 0; l < 3; l++) {
printf("\n%s", &size[l]);
}
//printf("\n%x %x", &size[1], &size[1], size[1]);
//for(int l = 0; l < 3; l++) {
//printf("\n%s", size[l]);
//}
}

int main()
{
FILE* fp;
int c = -1;
char moji[MAXSIZE];

if((fp = fopen("test.txt","rb")) == NULL) {
printf("error");
exit(1);
}

while(fscanf(fp,"%s",moji) != EOF) c++;

size = (char*)malloc(sizeof(char) * MAXSIZE * c);
// 初めに戻す
fseek(fp, 0, SEEK_SET);
// 最初の文だけ取り出す
fscanf(fp,"%s",moji);
// 一文を格納する
for(int l = 0; fscanf(fp, "%s", &size[l]) != EOF; l++) {
printf("\n%s", &size[l]);
}
//for(int l = 0; fscanf(fp, "%s", size[l]) != EOF; l++) {
//printf("\n%s", size[l]);
//}

printf("\n");
test();
fclose(fp);

getchar();
free(size);
return 0;
}
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
ポインタの配列で上記のソースのようにしたのですが、
error C2440: '=' : 'char *' から 'char (*)[256]' に変換できません。
というエラーがでてきます。
ポインタ配列での取得の仕方がおかしいみたいなんです。

お礼日時:2010/01/30 11:19

追加書き込みしまくってるついで


修正箇所は以下のようになります
size[l] を size[l * MAXSIZE]  に変えれば動きます
(char **で定義する必要無いって話もあるかもしれません)
    • good
    • 0
この回答へのお礼

  回答ありがとうございます。
ダブルポインタの理解力が足りないみたいですね。
size[l * MAXSIZE]に直したらところ表示は正常になりましたが
freeで解放しようとすると失敗するみたいです。
詳しくは分からないので調べてみようと思います。

お礼日時:2010/01/30 11:09

#1#2 ぼけまくってます 再訂正



sizeはダプルポインタの型定義してるだけで
size[0]/size[1]・・・・
に256バイトのバッファ先頭アドレスはいってるわけではありません

>for(int l = 0; fscanf(fp, "%s", &size[l]) != EOF; l++) {
これでは全体で確保したバッファのポインタポンのアドレスを
インクリメントしたバッファアドレスを渡してるだけです
読み込みしながらの表示では見た目上問題ありませんが
最後のtest関数では表示がおかしくなります
    • good
    • 0

#1訂正  ちゃんと見てなかった


2回目のtest関数では文字の終端がNULL(0)になってないので
そのように表示されます
読み込み直後はたまたま0が入ってるだけ
本来意識的にクリアするなどの方法を取らないと
潜在的なバグになります
    • good
    • 0

>size = (char**)malloc(sizeof(char) * MAXSIZE * c);


行数カウントする際に c をインクリメント
しかも -1 で初期化しているので実行数と取得した行数が食い違います

>// 最初の文だけ取り出す
>fscanf(fp,"%s",moji);
ここで既にファイルポインタが移動するので次の読み込みは
kakikueko
が読み込まれます

>// 一文を格納する
>for(int l = 0; fscanf(fp, "%s", &size[l]) != EOF; l++) {
>printf("\n%s", &size[l]);

>test();
上ではやってることは結果として同じ
(結果として読み込みファイルの2行目から最後までを2回表示してるだけ)
実行結果がおかしいわけではありません
    • good
    • 0

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


このQ&Aを見た人がよく見るQ&A