ページ 11

質問です!

Posted: 2007年2月23日(金) 14:21
by ももた
このソースを見て頂きたいのですが(作成途中のものです)

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

typedef struct busho{ /*構造体bushoの型枠の宣言*/
char b_name[41]; /*char型の配列b_name 要素数41*/
struct busho *next; /*次のbushoの構造体を指すポインタ変数next*/
struct shain *sentou; /*shainの構造体shainを指すポインタ変数sentou*/
}busho;

typedef struct shain{ /*構造体shainの型枠の宣言*/
char s_name[30]; /*char型の配列s_name 要素数30*/
char tel[12]; /*char型の配列tel 要素数12*/
char sex[1]; /*char型の配列sex 要素数1*/
struct shain *next; /*次のshainの構造体を指すポインタ変数next*/
}shain;


int main(void)
{
busho dmy; /*構造体busho型の変数dmyの宣言*/
busho *start = &dmy; /*構造体dmyのアドレスをstartに格納*/
busho *wkdata; /*データ設定用のポインタ変数wkdataの宣言*/
busho *wp; /*作業用のポインタwpの宣言*/
char b_name[20] = " "; /*char型の配列b_nameの宣言 要素数20*/
char buf[10]; /*char型の配列bufの宣言 要素数1*/

/*struct song *wkdata2;
struct song *wp2;
char s_name[15] = " ", buf2[10];
char tel[12];
char sex[1];
struct busho *tmp;
struct shain *tmp2;
*/

int num, i; /*int型の変数num,iの宣言(num:選択時の数字格納用),i:ループカウンタ*/
int len;


start->next = NULL; /*最初はデータがないのでNULLに設定*/

while(1)
{
printf("\n");
printf("[1][2][9]のどれかを選んでください!\n"); /*選択処理*/
printf("[1]:部署名登録\n");
printf("[2]:社員登録\n");
printf("[9]:システム終了\n");

printf("\n");
printf("[選択番号]:");
gets(buf);
num=atoi(buf);

switch(num){ /*部署名の追加処理*/
case 1:
while(1){
printf("[部署名(全角20文字)]:"); /*部署名をキーボード入力*/
gets(b_name);
len=strlen(b_name);
if(strcmp(b_name, " ")== 0){
break;
}
if(len>40){
printf("文字数オーバーです\n");
len=0;
continue;
}
else{
break;
}
}
wkdata=(struct busho *)malloc(sizeof(struct busho));
if(wkdata==NULL){
printf("メモリを確保する事ができません。\n");
return 1;
}

/*確保した構造体に部署名を設定する*/

strcpy(wkdata->b_name, b_name);

for(wp=start,i=0; wp->next != NULL; wp=wp->next,i++);

if(i==5){
printf("これ以上追加できません!!\n");
break;
}

if(wp->next == NULL){
wp->next = wkdata;
wkdata->next = NULL;
}







/*チェインの構造体の内容を表示*/
printf("**** 部署名リスト ****\n");
printf("\n");
for(wp=start->next,i=1; wp != NULL; wp = wp-> next, i++){
printf("[部署名%d]:%s\n", i, wp->b_name);
}
printf("\n");
break;

case 2:
if(start->next==NULL){
continue;
}
printf("[部署選択]:");
gets(buf);
num=atoi(buf);


printf("\n");
while(1){



}



case 9:
printf("[システム終了します!]\n");
return 0;
}
}
}

このソースで部署名を記入する時に全角、半角関わらず20桁以上打ち込むと再入力にできるのですが、次に正しいものを打ち込むとなぜか、画面がばぐってしまいます。何故だから分かる方おられましたら教えて頂きたいです>_<
よろしくお願いします。

Re:質問です!

Posted: 2007年2月23日(金) 15:00
by Yuki
>for(wp=start,i=0; wp->next != NULL; wp=wp->next,i++);
とありますが、1件目入力時startはNULLですよね?
wp->nextの参照は大丈夫ですか?

バグとは関係ありませんが、
>wkdata=(struct busho *)malloc(sizeof(struct busho));
の部分は
wkdata=(busho *)malloc(sizeof(busho));
で良いと思います。

ソースを載せるときは、インデントをして、<pre>タグでくくってもらえると
見やすいのでありがたいです。(<>は半角でお願いします。)


printf( "ここまでは通った。%d行目\n", __LINE__ );
といったようなデバックログを追加しておくと、どこに問題があるのかが
見つけやすくなります。

Re:質問です!

Posted: 2007年2月23日(金) 15:10
by ももた
そうです!最初はNULLにしてます!また、1件目の入力時に文字数をオーバーさせて、再入力時に正確なものを打ち込むとバグします。他の場合は大丈夫でした^^; なぜかまだ分からないです・・・。

Re:質問です!

Posted: 2007年2月23日(金) 15:13
by Justy
 早い話が、gets内でスタックを破壊しています。

 全角20文字といいながら、対象の変数に
20文字を十分格納できるサイズがないのに格納してしまい、
その結果スタックを壊し、その他のローカル変数が壊れて
しまったのではないでしょうか。

Re:質問です!

Posted: 2007年2月23日(金) 15:17
by ももた
そうなんですか^^; Justyさん!それならどうすればいいのでしょうか?

Re:質問です!

Posted: 2007年2月23日(金) 15:30
by Justy
 とりあえず、b_nameの配列サイズを大きく(256以上)すれば当座はしのげるかと。

 ちゃんと対応するのであれば、b_nameの配列を 42以上に。
 gets(b_name) はやめて scanf("%41s", b_name) に。
 で、len>40だったら rewind(stdin) を実行するようにする。
 これで「この問題」の部分は大丈夫です。

Re:質問です!

Posted: 2007年2月23日(金) 15:56
by ももた
問題は解決しました!ありがとうございました! また、先ほど出てきたrewind(stdin)が何かわからずサイトを調べてるんですが、イイサイトないですね^^;

Re:質問です!

Posted: 2007年2月23日(金) 16:47
by ももた
すみません。。。やはり無理でした・・・1回目に全角で文字を30文字以上打つと登録されてしまうんですが^^;

Re:質問です!

Posted: 2007年2月23日(金) 16:56
by Yuki
ムリだったソースを載せてください。

Re:質問です!

Posted: 2007年2月23日(金) 16:58
by ももた
/************************************
* *
* 社員名簿作成プログラム *
* *
*************************************/




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

typedef struct busho{ /*構造体bushoの型枠の宣言*/
char b_name[42]; /*char型の配列b_name 要素数41*/
struct busho *next; /*次のbushoの構造体を指すポインタ変数next*/
struct shain *sentou; /*shainの構造体shainを指すポインタ変数sentou*/
}busho;

typedef struct shain{ /*構造体shainの型枠の宣言*/
char s_name[30]; /*char型の配列s_name 要素数30*/
char tel[12]; /*char型の配列tel 要素数12*/
char sex[1]; /*char型の配列sex 要素数1*/
struct shain *next; /*次のshainの構造体を指すポインタ変数next*/
}shain;


int main(void)
{
busho dmy; /*構造体busho型の変数dmyの宣言*/
busho *start = &dmy; /*構造体dmyのアドレスをstartに格納*/
busho *wkdata; /*データ設定用のポインタ変数wkdataの宣言*/
busho *wp; /*作業用のポインタwpの宣言*/
char b_name[20] = " "; /*char型の配列b_nameの宣言 要素数20*/
char buf[10]; /*char型の配列bufの宣言 要素数1*/



/*struct song *wkdata2;
struct song *wp2;
char s_name[15] = " ", buf2[10];
char tel[12];
char sex[1];
struct busho *tmp;
struct shain *tmp2;
*/

int num, i; /*int型の変数num,iの宣言(num:選択時の数字格納用),i:ループカウンタ*/
int len;
char buf3[1];

start->next = NULL; /*最初はデータがないのでNULLに設定*/

while(1)
{
printf("\n");
printf("[1][2][9]のどれかを選んでください!\n"); /*選択処理*/
printf("[1]:部署名登録\n");
printf("[2]:社員登録\n");
printf("[9]:システム終了\n");

printf("\n");
printf("[選択番号]:");
gets(buf);
num=atoi(buf);

switch(num){ /*部署名の追加処理*/
case 1:
while(1){
printf("[部署名(全角20文字)]:"); /*部署名をキーボード入力*/
/*gets(b_name);*/

scanf("%41s", b_name);
gets(buf3);
len=strlen(b_name);



if(strcmp(b_name, " ")== 0){
break;
}
if(len>40){
printf("文字数オーバーです\n");
rewind(stdin);
continue;

}
else{
break;
}
}
wkdata=(busho *)malloc(sizeof(busho));
if(wkdata==NULL){
printf("メモリを確保する事ができません。\n");
return 1;
}

/*確保した構造体に部署名を設定する*/

strcpy(wkdata->b_name, b_name);

for(wp=start,i=0; wp->next != NULL; wp=wp->next,i++);

if(i==5){
printf("これ以上追加できません!!\n");
break;
}

if(wp->next == NULL){
wp->next = wkdata;
wkdata->next = NULL;
}


printf("**** 部署名リスト ****\n"); /*チェインの構造体の内容を表示*/
printf("\n");
for(wp=start->next,i=1; wp != NULL; wp = wp-> next, i++){
printf("[部署名%d]:%s\n", i, wp->b_name);
}

printf("\n");
break;




case 2:
if(start->next==NULL){
continue;
}



case 9:
printf("[システム終了します!]\n");
return 0;
}
}
}

Re:質問です!

Posted: 2007年2月23日(金) 17:03
by Justy
 いやもうなんというか。

 要素数が 20しかありませんよ、b_name。

Re:質問です!

Posted: 2007年2月23日(金) 17:29
by box
文字列長などに対しては #define を使ってみてはいかがでしょうか。
同じ性格を持っている文字列の長さが異なっているのは不自然です。

Re:質問です!

Posted: 2007年2月23日(金) 23:21
by ももた
すみません!また教えて頂きたいです。
性別の部分の表示にバグがあるんですが・・理由がわかりません。教えてください>_<
[ソースコード]
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct busho{
char b_name[41];
struct busho *next;
struct shain *sentou;
};

struct shain{
char s_name[30];
char tel[12];
char sex[1];
struct shain *next;
};


int main(void)
{
struct busho dmy;
struct busho *start = &dmy;
struct busho *wkdata;
struct busho *wp;
char b_name[41] = " ";
char buf[41];

struct shain *wkdata2;
struct shain *wp2;



int num,i;
char b_name_cmp[41];

start->next = NULL;

while(1)
{
printf("\n");
printf("①②⑨のどれかを選んでください!\n");
printf("[1]:部署名登録\n");
printf("[2]:社員登録\n");
printf("[9]:システム終了\n");

printf("\n");
printf("[番号入力]:");
gets(buf);
num=atoi(buf);


switch(num){
case 1:

printf("[部署名]:");
gets(b_name);
if(strcmp(b_name, "")== 0){
break;
}

wkdata=(struct busho *)malloc(sizeof(struct busho));
if(wkdata==NULL){
printf("メモリを確保できません\n");
return 1;
}

/**/

strcpy(wkdata->b_name, b_name);

for(wp=start,i=0; wp->next != NULL;wp=wp->next,i++);

if(4<i){
printf("これ以上追加できません\n");
break;
}

if(wp->next == NULL){
wp->next = wkdata;
wkdata->next = NULL;
}




wkdata2=(struct shain *)malloc(sizeof(struct shain));
wkdata->sentou=wkdata2;
wkdata2->next=NULL;



printf("****[部署名リスト]****\n");
for(wp=start->next,i=1; wp != NULL; wp = wp-> next, i++){
printf("[部署名%d]:%s\n", i, wp->b_name);
}
printf("\n");
break;


case 2:
while(1){
wp=start;
if(wp->next == NULL){
printf("部署名が登録されていません\n");
break;
}

printf("[部署名]:");
gets(b_name_cmp);
if(strcmp(b_name_cmp, "")== 0){
break;
}

for(wp=start->next ; wp != NULL ; wp=wp->next){
if(strcmp(wp->b_name,b_name_cmp) == 0){
break;
}
}
if(wp==NULL){
continue;
}

wp2=wp->sentou;

wkdata2=(struct shain *)malloc(sizeof(struct shain));
if(wkdata2==NULL){
printf("メモリを確保する事ができません\n");
return 1;
}

while(1){
printf("[社員名]:");
gets(buf);
strcpy(wkdata2->s_name, buf);
if(strcmp(wkdata2->s_name,"")== 0){
continue;
}
else{break;}
}

while(1){
printf("[TE[/url]:");
gets(buf);
if(strcmp(buf,"")==0){
continue;
}
if(strlen(buf)>12){
continue;
}


for(i=0; 47<(int)buf && (int)buf<58 ; i++);
if(i==strlen(buf)){
break;
}
else if((int)buf<48 || 57<(int)buf){
continue;
}
}
strcpy(wkdata2->tel,buf);

while(1){
printf("[性別](男=1,女=0): ");
gets(buf);

if(strcmp(buf,"1")==0){
strcpy(wkdata2->sex,"男");
}
else if(strcmp(buf,"0")==0){
strcpy(wkdata2->sex,"女");
}
else{
printf("入力エラーです!(0か1を押してください!)\n");
continue;
}
break;
}
printf("\n");


for(wp2=wp->sentou; wp2->next != NULL; wp2=wp2->next);



if(wp2->next == NULL){
wkdata2->next = NULL;
wp2->next = wkdata2;

}

for(wp2=wp->sentou,i=1 ; wp2->next != NULL ; wp2=wp2->next,i++){
printf("[%d]部署名:%s\n", i,wp->b_name);
printf("名前:%s\n", wp2->next->s_name);
printf("TEL:%s\n", wp2->next->tel);
printf("性別:%s\n\n", wp2->next->sex);

if(i>10){
printf("これ以上追加できません!(CRを押してください)\n\n");
break;
}
}
}
break;
case 9:
printf("[システムを終了します]\n");
return 0;
}
}
}

Re:質問です!

Posted: 2007年2月23日(金) 23:31
by box
> 性別の部分の表示にバグがあるんですが・・理由がわかりません。教えてください>_<

"男"または"女"という、終端の'\0'を含めて
3バイトの領域の格納先が1バイトしかないのは、
まずいでしょうね。

ソースの貼り付けの際、前後をなかなか<pre>と</pre>タグ(不等号は半角)で
はさんでいただけないのは残念なことです。

Re:質問です!

Posted: 2007年2月23日(金) 23:31
by バグ
"男"や"女"は2バイト文字なのに、メンバに割り当てられているのは1バイトしかありませんね。文字列の終端を示す'0'を含めて最低でも3バイトは確保しておかないと危険ですよ。
それにたしか、原則として1個の配列は認められてなかったように思います(;^_^A

Re:質問です!

Posted: 2007年2月23日(金) 23:34
by ももた
すみません。よくわからないです>_< どの部分をどのように変更すればいいのでしょうか^^; よくわからなくてすみません。。。

Re:質問です!

Posted: 2007年2月23日(金) 23:36
by ももた
あっ!わかりました!sex[1]→sex[3]に変えるとゴミの表示がなくなりました^^;

Re:質問です!

Posted: 2007年2月24日(土) 00:33
by ももた
すみません。また質問です!部署名(全角20文字)、社員名(全角15文字)という条件があるんですが、全角21文字,全角16文字以上は繰り返し再入力にしたいんですが、どのように書けばいいのでしょうか? 全然できないのでどなたか教えてください>_<

Re:質問です!

Posted: 2007年2月24日(土) 00:44
by box
全然できない、と判断されるまでに、
ご自分の頭でどのくらいの時間お考えになりましたか?
また、書籍やネット上の情報をどの程度お調べになりましたか?

もしも、ほとんど考えたり調べたりしないで、脊髄反射的に「わからん!掲示板だ!」という
お考えをお持ちだとすると、ちょっといかがなものかと思います。

Re:質問です!

Posted: 2007年2月24日(土) 01:02
by ももた
そうですね^^; 3,4時間位色々ためしたり、また利用できる関数はないかと調べてるんですが、できなかったので。。。何も考えないですぐに質問みたいな事はしないです。

Re:質問です!

Posted: 2007年2月24日(土) 01:13
by box
ということは、先ほどの性別の件などと
同時にお考えになっていたようですね。
投稿時刻から推測して。

一つの問題が片づいてから次に取りかかる方が、
トータルでは効率的だと思います。

Re:質問です!

Posted: 2007年2月24日(土) 01:20
by ももた
性別の問題はなんとか解決したんですが、文字数部分にかなり苦戦をしてますよ>_<
色々サイトでヒントになりそうな部分はないかと調べてるんですが、まだまだ初心者なのでわからないことだらけですね^^;

Re:質問です!

Posted: 2007年2月26日(月) 10:46
by asd
>全角21文字,全角16文字以上は繰り返し再入力にしたいんですが

1.入力を受け付ける
2.入力された文字のサイズを調べる
3.サイズが全角21文字(半角42文字)、全角16文字(半角32文字)以上だったら1.から繰り替えす

こういう処理が必要だと言うことはお分かりになりましたでしょうか?
やりたいことに対して出来るだけ部分部分の処理に分解していくと作りやすいですよ。
上の処理はそれぞれ該当する関数があるかと思いますし^^