前提・実現したいこと
C言語を使っています。
データを線形リストで登録し、その後削除したい情報をキーとして入力し、削除するというプログラムにしたいです。
しかし、ターミナル上で control + D で 削除する対象の key を入力できるようになるはずがその動作を無視して終わってしまいます。
23行目が怪しいと思っているのですが、自分の力では解決できません。よろしくおねがいします。
発生している問題・エラーメッセージ
CLang 1111-2222 Java 3333-4444 Python 6666-7777 Python 6666-7777 Java 3333-4444 CLang 1111-2222 ←これを入力後、contlol + D Key Name ←飛ばされる Python 6666-7777 Java 3333-4444 CLang 1111-2222
該当のソースコード
C言語
1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5struct tfield{ 6 char name[20]; 7 char tel[20]; 8 struct tfield *pointer; 9}*head; 10 11struct tfield *talloc(void); 12void genlist(void); 13void displist(void); 14void del(char *); 15 16int main(void) 17{ 18 char key[20]; 19 20 genlist(); 21 displist(); 22 23 while(printf("Key Name \n"),(scanf("%s",key))!=EOF){ 24 del(key); 25 } 26 27 displist(); 28 return 0; 29} 30 31void del(char *key) 32{ 33 struct tfield *p,*old; 34 35 p=old=head; 36 while(p!=NULL){ 37 if(strcmp(key,p->name)==0){ 38 if(p==head) 39 head=p->pointer; 40 else 41 old->pointer=p->pointer; 42 return; 43 } 44 old=p; 45 p=p->pointer; 46 } 47 printf("キーデータが見つかりません\n"); 48} 49 50 51void genlist(void) 52{ 53 struct tfield *p; 54 55 head=NULL; 56 while(p=talloc(),scanf("%s %s",p->name,p->tel)!=EOF){ 57 p->pointer=head; 58 head=p; 59 } 60} 61 62void displist(void) 63{ 64 struct tfield *p; 65 p=head; 66 while(p!=NULL){ 67 printf("%15s%15s\n",p->name,p->tel); 68 p=p->pointer; 69 } 70} 71struct tfield *talloc(void) 72{ 73 return (struct tfield *)malloc(sizeof(struct tfield)); 74}
試したこと
23行目 判定を != → == にすると無限ループ。
ターミナルの問題のような気がします。
stty -a の出力を見せてください。
ターミナル上でcontrol+Dの入力はEOF(End of file)を示すことになるので、scanfがEOF(-1)を返す仕様です。ですので
> ターミナル上で control + D で 削除する対象の key を入力できるようになるはず
と言うこと自体が成り立ちません。
成り立つかどうかは処理系によるかもです。
なので処理系によっては動くかもしれないけど適切ではないかもですね。
Cygwinでは動いちゃいました。
@itagagakiさん
ご指摘ありがとうございます。
> 成り立つかどうかは処理系によるかもです。
確かにそうですね。WindowsコマンドプロンプトではCTRL+Zですし。
@itagagaki さん
% stty -a
speed 9600 baud; 24 rows; 80 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
-extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
-ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
stop = ^S; susp = ^Z; time = 0; werase = ^W;
となりました。
eof = ^D ですね。
そこは問題ないですね。
他の方がおっしゃっているように、お使いの処理系では、一度EOFを送ったら、その後scanfしてもEOFしか返らないシステムなのっぽいですね。
なので、EOFで終わりにするのではなく、何か特別なワードで終わりにするのがよさそうですね。
みなさんありがとうございます。自分の中ではほとんど解決したと思っています。初めて質問してみたのですが、返信がとても早くてびっくりするとともに、ありがたく思いました。次回がありましたらよろしくおねがいします。
回答3件
あなたの回答
tips
プレビュー