dポイントプレゼントキャンペーン実施中!

fscanfで文字列を読み込み、strtokでカンマ区切りにするという関数を作りたいのですが、
reallocすると先頭から徐々にデータが文字化けしていきます。

まず最初に4つ分のchar*を取ります。
もし、5つ目が見つかったらさらに4つ増やし、9つ目が見つかったらさらに。。。というようになっております。
n個目の判定はcntがn-1で真になり、reallocが成功したら個数を増やすようになってます。

5つ目が見つかった時点では出力に問題は無いのですが、6個目から侵食が始まっていきます。
原因がどうしても自分では分からなかったので、誰かお願い致します。

words.txtの内容(末尾改行なし)
iii,jjj,kkkkkkkkk,l,m,n,ooooo,pppppppp,a,s,d,f,g

main.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"C:\borland\bcc55\Include\malloc.h"

int readlinefile(FILE *fp,char **words){
int cnt=0,len;
char *line=(char *)malloc(256);
char *tmp;
if(line==NULL) return 0;
if(fscanf(fp,"%s",line)!=EOF){
if((tmp=(char *)realloc(line,sizeof(char)*(strlen(line)+1)))==NULL){//できるだけメモリを節約してみる
return 0;
}else{
line=tmp;
}
len=strlen(line);
printf("line:%d:%d:%s\n",len,_msize(line),line);
if(len>1){//ファイル終端の改行を排除
int i;
char *tok=strtok(line,",");//カンマで区切ったアドレスを得る
while(tok){
if(cnt==0)printf("tok:1st:%x\n",tok);
if(cnt>3&&cnt%4==0){//サイズが足りなくなった時
char **tmp2;
if((tmp2=(char **)realloc(words,sizeof(char *)*(4+4*(cnt%4))))==NULL){
printf("words realloc ERROR\n");
break;
}else{
printf("realloc\n");
words=tmp2;//reallocを適用
}
}
words[cnt]=tok;

if(cnt){
printf("line(func)");
for(i=0;i<len+1;i++){
printf("%c",words[0][i]);
}
printf("\n");
}

tok=strtok(NULL,",");

printf("words[%d]:%x:%s\n",cnt,words[cnt],words[cnt]);

printf("\n");
printf("tok:%d回目:%x\n",cnt+1,tok);

cnt++;
}
return cnt;//正常終了した
}else{
free(line);
}
}
return 0;
}

int main(){
FILE *fp=fopen("words.txt","r");
if(fp){
int cnt=1;
while(cnt){
int i;
char **words=(char **)malloc(sizeof(char *)*4);
words[0]=NULL;
cnt=readlinefile(fp,words);
printf("mainに戻りました\n");
if(cnt)printf("words:%d\n",cnt);
for(i=0;i<cnt;i++){
printf("words[%d]:%x:%s\n",i,words[i],words[i]);
}
free(words[0]);
words[0]=NULL;
printf("\n");
free(words);
}
}else{
printf("file open ERROR\n");
}
return 0;
}

実行結果
なぜかコピペできないので実行するか斧でダウンロードお願いします。
http://www1.axfc.net/u/3352789.txt

全てまとめたもの
http://www1.axfc.net/u/3352796.zip

A 回答 (3件)

>if(cnt>3&&cnt%4==0){//サイズが足りなくなった時


>char **tmp2;
>if((tmp2=(char **)realloc(*words,sizeof(char *)*(4+4*(cnt%4))))==NULL){

ifの条件とrealloc()するサイズをよくみましょう。

また直接関係する事ではありませんがポインタ値を"%x"で出力させるのは間違ってます(sizeof(int) == sizeof(void *)の環境では動きはしますが)。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
cnt>3で初めての時は4=cntのときにcnt%4==0で5個目で、
cnt>3で2回目の時は8=cntの時にcnt%4==0で9個目で、
…でここは合ってますか?

sizeofの後の定数は元のサイズで、4*(cnt%4)は…ゼロ!?




動きました!ありがとうございます!!
本当にありがとうございます。全然気づきませんでした。


アドレスの出力の方ですが、まさしくポインタの値は整数と同じビット数だと思ってました。
これからは%pの方に直します。

お礼日時:2014/11/03 02:25

分割したトークンの実体を格納している領域はどこですか?

    • good
    • 0

readlinefileは、realloc()したwordsをどうやってmain()に返してるんでしょうか。

この回答への補足

ご回答ありがとうございます。
返して無いですね。reallocで返ってきたアドレスが同じだったみたいです。
修正版上げました。ー>http://www1.axfc.net/u/3352861.c
いい忘れましたが、ソースファイルで字下げの無いところは削除しても問題ありません。

補足日時:2014/11/02 23:01
    • good
    • 0

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