変数の勝手な同期

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
tomo

変数の勝手な同期

#1

投稿記事 by tomo » 6年前

[1] 変数stack,tokの操作をすると構造体の変数の値が変わってしまう
 [1.1] データファイルの解析を行おうとしています。
 [1.2] printfを用いて調べたところ、char型の変数stackとtokをいじると構造体の変数の値が変ってしまうと判明
アドレスを調べてみたが、メモリの確保はしっかりできているようで変わる理由がわかりません

コード:

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

struct model{
	char* Symbol; 
	char* Code;
};
char *fname="test(3).txt";//引数の仮データ
int size=1000;
int N=3;
//int main(char *fname,int size,int N){ //Javaから動かすつもりです
int main(){
	FILE *fpd;
	errno_t error;
	int i,line=0;
	struct model *data;
	char *stack;
	char *tok,*nexttoken;
	data = (struct model *)malloc(sizeof(struct model)*(N+1));
	for(i=0; i<=N; i++){
		printf("data[%d]=%d\n",i,&data[i]);
		data[i].Symbol = (char *)malloc(sizeof(char)*(N+1));
		data[i].Symbol=NULL;
		printf("  Symbol=%d\n",&data[i].Symbol);
		data[i].Code = (char *)malloc(sizeof(char)*(N+1));
		data[i].Code =NULL;
		printf("  Code=%d\n\n",&data[i].Code);
	}

	tok = (char *)malloc(sizeof(char)*N);
	printf("token=%d\n",&tok);
	stack = (char *)malloc(sizeof(char)*N);
	printf("stack=%d\n",&stack);

	if(error = fopen_s(&fpd,fname,"r")!=0)exit(0);
	printf("読み込んだ!\n");

	while(fgets(stack,size,fpd)!=NULL){
		printf("line:%d\n",line);
		printf("stack:%s\nSymbol:%s\nCode:%s\n\n",stack,data[0].Symbol,data[0].Code);
		
		if(line>0 && line<3){
			i=0;
			printf("stack=%d\ntok=%d\nSymbol=%d\n\n",&stack,&tok,&data[0].Symbol);
			tok = strtok_s(stack, ",",&nexttoken);//1つ目の要素
			//if(line==2)printf("--data[0].Symbol=%s\n",data[0].Symbol);

			while( tok != NULL){
				if(line==1){
					data[i].Symbol=tok;
					printf("data[%d].Symbol=%s\n",i,data[i].Symbol);
				}else if(line==2){
					data[i].Code=tok;
					printf("data[%d].Code=%s\n",i,data[i].Code);
				}
				tok = strtok_s(NULL, ",",&nexttoken);// 2つ目以降
				i++;
			}
		}
		line++;
		//if(line==2)printf("--data[0].Symbol=%s\n",data[0].Symbol);
	}
	for(i=0; i<=2*N+1; i++){
		if(i<=N) printf("data[%d].Symbol=%s\n",i,data[i].Symbol);
		else printf("data[%d].Code=%s\n",i-(N+1),data[i-(N+1)].Code);
		if(i==N)printf("\n");
	}
	printf("\nN=%d\nEND\n",N);
	fclose(fpd);
	return 0;
}
↓test(3).txtの内容↓
30,30
1,01,001,111
0,10,110,000
0101101001011011010101010000110110010

 [1.3] エラーなどはありません。
構造体の変数を操作していないのに変わってしまうので困っています。
その原因と解決方法を教えてください。

[2] 環境  
 [2.1] Windows
 [2.2] Microsoft Visual stadio

[3] その他
 C言語はそこそこ理解していると思います。

tomo

Re: 変数の勝手な同期

#2

投稿記事 by tomo » 6年前

codeタグを使ったのですが改行されてないですね・・・
ごめんなさい。

tomo

Re: 変数の勝手な同期

#3

投稿記事 by tomo » 6年前

どうしても改行されないので・・・・

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

struct model{
char* Symbol;//情報源記号(例:B,WB,WW)
char* Code; //情報源符号 情報源記号を短く表現した符号
};
//char Lh[4]={'0','11','100','101'};
char *fname="test(3)";//引数仮データ
int size=1000;
int N=3;
//int main(char *fname,int size,int N){
int main(){
FILE *fpd;
//FILE *fpd,*fp;
errno_t error;
int i,line=0;//行数を示すのにも用いる
struct model *data;
char *stack;
char *tok,*nexttoken;

data = (struct model *)malloc(sizeof(struct model)*(N+1));//N+1個の情報を扱う
for(i=0; i<=N; i++){
printf("data[%d]=%d\n",i,&data);
data.Symbol = (char *)malloc(sizeof(char)*(N+1));
data.Symbol=NULL;
printf(" Symbol=%d\n",&data.Symbol);
data.Code = (char *)malloc(sizeof(char)*(N+1));
data.Code =NULL;
printf(" Code=%d\n\n",&data.Code);
}

tok = (char *)malloc(sizeof(char)*N);
printf("token=%d\n",&tok);
stack = (char *)malloc(sizeof(char)*N);
printf("stack=%d\n",&stack);

if(error = fopen_s(&fpd,fname,"r")!=0)exit(0);
printf("読み込んだ!\n");

while(fgets(stack,size,fpd)!=NULL){
printf("line:%d\n",line);
printf("stack:%s\nSymbol:%s\nCode:%s\n\n",stack,data[0].Symbol,data[0].Code);

if(line>0 && line<3){
i=0;
printf("stack=%d\ntok=%d\nSymbol=%d\n\n",&stack,&tok,&data[0].Symbol);
tok = strtok_s(stack, ",",&nexttoken);//1つ目の要素
//if(line==2)printf("--data[0].Symbol=%s\n",data[0].Symbol);

while( tok != NULL){
if(line==1){
data.Symbol=tok;
printf("data[%d].Symbol=%s\n",i,data.Symbol);
}else if(line==2){
data.Code=tok;
printf("data[%d].Code=%s\n",i,data[i].Code);
}
tok = strtok_s(NULL, ",",&nexttoken);// 2つ目以降
i++;
}
}
line++;
//if(line==2)printf("--data[0].Symbol=%s\n",data[0].Symbol);
}
printf("なんか解析データになってる(・ω・`)\n");
for(i=0; i<=2*N+1; i++){
if(i<=N) printf("data[%d].Symbol=%s\n",i,data[i].Symbol);
else printf("data[%d].Code=%s\n",i-(N+1),data[i-(N+1)].Code);
if(i==N)printf("\n");
}
printf("\nN=%d\nEND\n",N);
//fp=fopen("data.txt","w");
/*while(n=fgetc(fpd)!=EOF){
stack+=n;
if(stack==Lh[0]){
fprintf(fpw,"%s","WWW");
stack=NULL;
}else if(stack==Lh[1]){
fprintf(fpw,"%s","B");
stack=NULL;
}else if(stack==Lh[2]){
fprintf(fpw,"%s","WB");
stack=NULL;
}else if(stack==Lh[3]){
fprintf(fpw,"%s","WWB");
stack=NULL;
}

}*/
fclose(fpd);
//fclose(fp);
return 0;
}

アバター
usao
記事: 1569
登録日時: 6年前

Re: 変数の勝手な同期

#4

投稿記事 by usao » 6年前

コード:

int size=1000;
int N=3;
...
stack = (char *)malloc(sizeof(char)*N);
...
while(fgets(stack,size,fpd)!=NULL){
↑バッファサイズを超えて読み込んでいませんか?

[追記]
あと,tokを使うあたりがダメなように見えます.そのあたりでは
ポインタの代入 で 文字列のコピー を表そうとしているように見受けます.

#コードが改行されて見えないのはどうやらIEのバージョンがどうの,という話らしいです.
 私にはコードがちゃんと改行されて見えていますよ.

アバター
a5ua
記事: 199
登録日時: 9年前

Re: 変数の勝手な同期

#5

投稿記事 by a5ua » 6年前

問題点はたくさんありますが、いっぺんに指摘しても混乱すると思うので、まずはひとつ
文字列のコピーには、strcpyを使いましょう。

コード:

            while( tok != NULL){
                if(line==1){
                    data[i].Symbol=tok; // 文字列のコピーではない。tokが指す文字列を変更すれば、data[i].Symbolも変更される
                    printf("data[%d].Symbol=%s\n",i,data[i].Symbol);
                }else if(line==2){
                    data[i].Code=tok; // 文字列のコピーではない。tokが指す文字列を変更すれば、data[i].Codeも変更される
                    printf("data[%d].Code=%s\n",i,data[i].Code);
                }
                tok = strtok_s(NULL, ",",&nexttoken);// 2つ目以降
                i++;
            }

tomo

Re: 変数の勝手な同期

#6

投稿記事 by tomo » 6年前

strcpyと動的メモリ割り当ての数を変更しました。このような感じでしょうか?
一行目読み込み中に止まってしまうので、調べ中です。
※FireFoxにしてみたところ、codeタグで改行されてました^^;ありがとうございます

コード:

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

struct model{
	char* Symbol;//情報源記号(例:B,WB,WW)
	char* Code; //情報源符号 情報源記号を短く表現した符号
};
//char Lh[4]={'0','11','100','101'};
char *fname="test(3)";//引数仮データ
int size=1000;
int N=3;
//int main(char *fname,int size,int N){
int main(){
	FILE *fpd;
	//FILE *fpd,*fp;
	errno_t error;
	int i,line=0;//行数を示すのにも用いる
	struct model *data;
	char *stack;
	char *tok,*nexttoken;

	data = (struct model *)malloc(sizeof(struct model)*(N+1));//N+1個の情報を扱う
	for(i=0; i<=N; i++){
		printf("data[%d]=%d\n",i,&data[i]);
		data[i].Symbol = (char *)malloc(sizeof(char)*(N+1));
		data[i].Symbol=NULL;
		printf("  Symbol=%d\n",&data[i].Symbol);
		data[i].Code = (char *)malloc(sizeof(char)*(N+1));
		data[i].Code =NULL;
		printf("  Code=%d\n\n",&data[i].Code);
	}

	tok = (char *)malloc(sizeof(char)*N);
	printf("token=%d\n",&tok);
	stack = (char *)malloc(sizeof(char)*size);
	printf("stack=%d\n",&stack);

	if(error = fopen_s(&fpd,fname,"r")!=0)exit(0);
	printf("読み込んだ!\n");

	while(fgets(stack,size,fpd)!=NULL){
		printf("line:%d\n",line);
		
		if(line>0 && line<3){
			i=0;
			tok = strtok_s(stack, ",",&nexttoken);//1つ目の要素

			while( tok != NULL){
				if(line==1){
					strcpy(data[i].Symbol,tok);
					printf("data[%d].Symbol=%s\n",i,data[i].Symbol);
				}else if(line==2){
					strcpy(data[i].Code,tok);
					printf("data[%d].Code=%s\n",i,data[i].Code);
				}
				tok = strtok_s(NULL, ",",&nexttoken);// 2つ目以降
				i++;
			}
		}
		line++;
	}
	for(i=0; i<=2*N+1; i++){
		if(i<=N) printf("data[%d].Symbol=%s\n",i,data[i].Symbol);
		else printf("data[%d].Code=%s\n",i-(N+1),data[i-(N+1)].Code);
		if(i==N)printf("\n");
	}
	printf("\nN=%d\nEND\n",N);
	//fp=fopen("data.txt","w");
	/*while(n=fgetc(fpd)!=EOF){
		stack+=n;
		if(stack==Lh[0]){
			fprintf(fpw,"%s","WWW");
			stack=NULL;
		}else if(stack==Lh[1]){
			fprintf(fpw,"%s","B");
			stack=NULL;
		}else if(stack==Lh[2]){
			fprintf(fpw,"%s","WB");
			stack=NULL;
		}else if(stack==Lh[3]){
			fprintf(fpw,"%s","WWB");
			stack=NULL;
		}

	}*/
	fclose(fpd);
	//fclose(fp);
	return 0;
}

tomo

Re: 変数の勝手な同期

#7

投稿記事 by tomo » 6年前

strncpyなら解決できるかと思いやってみたのですが、
止まらないので理由のしっかり解析します・・・。

コード:

while( tok != NULL){
	if(line==1){
		strncpy(data[i].Symbol,tok,strlen(tok));
		printf("data[%d].Symbol=%s\n",i,data[i].Symbol);
	}else if(line==2){
		strncpy(data[i].Code,tok,strlen(tok));
		printf("data[%d].Code=%s\n",i,data[i].Code);
	}
	tok = strtok_s(NULL, ",",&nexttoken);// 2つ目以降
	i++;
}

アバター
a5ua
記事: 199
登録日時: 9年前

Re: 変数の勝手な同期

#8

投稿記事 by a5ua » 6年前

コード:

    for(i=0; i<=N; i++){
        printf("data[%d]=%d\n",i,&data[i]);
        data[i].Symbol = (char *)malloc(sizeof(char)*(N+1));
        data[i].Symbol=NULL;
        printf("  Symbol=%d\n",&data[i].Symbol);
        data[i].Code = (char *)malloc(sizeof(char)*(N+1));
        data[i].Code =NULL;
        printf("  Code=%d\n\n",&data[i].Code);
    }
malloc()で得たポインタをNULLに上書きしてしまっているので、
以降の、strcpy(data.Symbol,tok);でNULLアクセスとなっています。

したがって
data.Symbol=NULL;
data.Code =NULL;
は不要です。

non
記事: 1097
登録日時: 9年前

Re: 変数の勝手な同期

#9

投稿記事 by non » 6年前

26行目

コード:

        data[i].Symbol = (char *)malloc(sizeof(char)*(N+1));
        data[i].Symbol=NULL;
メモリを動的確保した後、NULLを入れるのは何をしたいのでしょうか?

アドレスを表示するには %d でなく %p にしましょう。

「追記」
かぶっちゃいました。
non

tomo

Re: 変数の勝手な同期

#10

投稿記事 by tomo » 6年前

思考錯誤している際に、初期化していないのが悪いのかと思いNULLを入れてました・・・。
strcpy(data.Symbol,"")のようにすれば当っているのでしょうか
%pについては知りませんでした。今後プログラムで*のアドレスを表示させるときに使います。


コード:

data = (struct model *)malloc(sizeof(struct model)*(N+1));//N+1個の情報を扱う
for(i=0; i<=N; i++){
	data[i].Symbol = (char *)malloc(sizeof(char)*(N+1));
	data[i].Code = (char *)malloc(sizeof(char)*(N+1));
}

tomo

Re: 変数の勝手な同期

#11

投稿記事 by tomo » 6年前

皆さまのお力を借り、想像していた結果が得られるようになりました。
同時に変数の扱い方を正確に把握していない等、自分の未熟な点がわかり勉強になりました。
本当にありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る