質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

2567閲覧

ダウンロードしたプログラムでエラーが出て実行できない。

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2017/12/04 01:34

編集2017/12/05 22:02

ダウンロードしたプログラムでエラーが出て実行できない。
元々エラーの出る質問プログラムでした。
修正しながらうまくいきましたというコメントがありましたが、
私はうまくいきませんでしたので
main関数は修正して実行しています。コンパイラはMinGwです。
実行結果を下のほうに掲載してあります。
"address.csv"をメニュー4dumpで参照すると文字化けしています。
numberの切り出しに失敗しました。とあるので、これが影響していそうなのですが
コードの直し方がわかりません。よろしくお願いします。

"address.csv"以下です。
yamasita,fuse,090-7777,mail-6
hosi,nagoya,5436,f-mail
kato,kanagawa,080-8888,mail1-2
naka,kamikosaka,080-4444,mail1-1
nasi,oosaka,6789,h-mail
sato,tokyo ,090-3333,mail1-4
suzuki,saitama,090-2222,mail1-5

コード // http://dixq.net/forum/viewtopic.php?t=9744&p=78652 #include<stdio.h> #include<stdlib.h> #include<string.h> #define N 256 struct address{ //アドレス帳のデータ char name[32]; char addre[128]; char number[12]; char mail[64]; struct address* next; //次の要素へのポインタ }; /*プロトタイプ宣言*/ void data_show(struct address* head); void data_add(struct address* head); void data_delete(struct address* head); void data_sort(struct address* head); void data_write(struct address* head); int main(void){ struct address* head=NULL,*p; FILE* fp; static char name[N], addre[N], number[N], mail[N]; //int c; fp = fopen("address.csv","r"); if(fp==NULL){ printf("file not open\n"); exit(1); } char ch[512]; while(fscanf(fp,"%s",ch)!=EOF){ p = (struct address*)malloc(sizeof(struct address)); char* token=","; char* s; s = strtok(ch, token); if ( s != NULL ) { strcpy(name, s); } else { printf( "nameの切り出しに失敗しました。\n"); break; } s = strtok(NULL, token); if ( s != NULL ) { strcpy(addre, s); } else { printf( "addreの切り出しに失敗しました。\n"); break; } s = strtok(NULL, token); if ( s != NULL ) { strcpy(number, s); } else { printf( "numberの切り出しに失敗しました。\n"); break; } s = strtok(NULL, token); if ( s != NULL ) { strcpy(mail, s); } else { printf( "mailの切り出しに失敗しました。\n"); break; } //strcpy(p->name ,strtok(ch,token)); //strcpy(p->addre ,strtok(NULL,token)); //strcpy(p->number ,strtok(NULL,token)); //strcpy(p->mail ,strtok(NULL,token)); p->next = head; head = p; } p = head; printf("\n"); fclose(fp); int select; while(select != 0){ printf("1:ソ\ート 2:削除 3:追加 4:参照 0:終了\nメニューを選択してください:"); scanf("%d",&select); switch(select){ case 1: data_sort(head); break; case 2: data_delete(head); break; case 3: data_add(head); break; case 4: data_show(head); break; case 0: printf("終了します\n"); break; default: printf("もう一度選択してください\n"); break; } } return 0; } //データの追加する関数 void data_add(struct address* head){ struct address* p, *q, *new; char new_name[32]; char new_addre[128]; char new_number[12]; char new_mail[64]; printf("追加する要素を入力してください"); printf("名前:"); scanf("%s",new_name); printf("住所:"); scanf("%s",new_addre); printf("電話番号:"); scanf("%s",new_number); printf("メールアドレス:"); scanf("%s",new_mail); p = head->next; q = head; while(p != NULL){ q = p; p = p->next; } new = (struct address*)malloc(sizeof(struct address)); strcpy(new->name,new_name); strcpy(new->addre,new_addre); strcpy(new->number,new_number); strcpy(new->mail,new_mail); new->next = p; q->next = new; q = head; data_write(q); } void data_delete(struct address* head){ char name[32]; struct address* p, *before; printf("アドレスを削除します\n名前を入力してください:"); scanf("%s", name); p = head; int flag = 0; while(p != NULL && strcmp(p->name,name)!=0){ before = p; p = p->next; flag = 1; printf("a\n"); } printf("%s\n",p->name); if(flag==0 && strcmp(p->name,name) == 0){ head = p->next; p = head; printf("アドレスを削除しました\n"); data_write(p); } else if(p == NULL){ printf("アドレスに登録されていません\n"); }else{ before->next = p->next; p = head; printf("アドレスを削除しました\n\n"); data_write(p); } } //データを参照する関数 void data_show(struct address* head){ struct address* p = head; while(p){ printf("%s,%s,%s,%s\n",p->name,p->addre,p->number,p->mail); p = p->next; } printf("\n"); } //データソート関数 void data_sort(struct address* head){ struct address* p,*before,*after; p = head; after = head->next; if(strcmp(p->name,after->name) > 0){ p = after; p->next = head; p->next->next = after->next; } before = p; p = p->next; after = p->next; while(before){ before = p; p = p->next; after = p->next; } printf("ソ\ートしました\n"); } //ファイルに書き込む関数 void data_write(struct address* p){ FILE* fp2; //struct address* tmp; fp2 = fopen("new_address.csv","w"); if(fp2==NULL){ printf("file not open\n"); exit(1); } while(p){ fprintf(fp2,"%s,%s,%s,%s\n",p->name,p->addre,p->number,p->mail); p = p->next; } fclose(fp2); } /* 実行結果 naka@naka ~/kadai $ gdb a.exe ......省略しています。エラー箇所   while(fscanf(fp,"%s",ch)!=EOF){ (gdb) 40 p = (struct address*)malloc(sizeof(struct address)); (gdb) 42 char* token=","; (gdb) 45 s = strtok(ch, token); (gdb) 46 if ( s != NULL ) { (gdb) 47 strcpy(name, s); (gdb) 53 s = strtok(NULL, token); (gdb) 54 if ( s != NULL ) { (gdb) 55 strcpy(addre, s); (gdb) 61 s = strtok(NULL, token); (gdb) 62 if ( s != NULL ) { (gdb) 63 strcpy(number, s); (gdb) 69 s = strtok(NULL, token); (gdb) 70 if ( s != NULL ) { (gdb) 71 strcpy(mail, s); (gdb) 81 p->next = head; (gdb) 82 head = p; (gdb) 39 while(fscanf(fp,"%s",ch)!=EOF){ (gdb) 40 p = (struct address*)malloc(sizeof(struct address)); (gdb) 42 char* token=","; (gdb) 45 s = strtok(ch, token); (gdb) 46 if ( s != NULL ) { (gdb) 47 strcpy(name, s); (gdb) 53 s = strtok(NULL, token); (gdb) 54 if ( s != NULL ) { (gdb) 55 strcpy(addre, s); (gdb) 61 s = strtok(NULL, token); (gdb) 62 if ( s != NULL ) { (gdb) 65 printf( "numberフリoオノクsオワオスB\n"); (gdb) numberの切り出しに失敗しました。 66 break; (gdb) 85 p = head; (gdb) 86 printf("\n"); (gdb) 88 fclose(fp); (gdb) 91 while(select != 0){ (gdb) 92 printf("1:\[g 2: 3:ヌチ 4:Qニ 0:Iケ\nj[Iオトュセウ「F"); (gdb) 1:ソート 2:削除 3:追加 4:参照 0:終了 メニューを選択してください:93 scanf("%d",&select); (gdb) クAツ・ツ0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[]^_`abcdefghijklmnopqrstuvwxyz{|}~€ 。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚ 1,hijklmnopqrstuvwxyz[]^_`abcdefghijklmnopqrstuvwxyz{|}~€ 。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚ 1,ネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚ 1,ヤユヨラリルレロワン゙゚ 1 クAツ・ツ,,ミムメモヤユヨラリルレロワン゙゚ ,ワン゙゚  クAツ・ツ・・・  ,  ,, クAツ・ツ,C:\MinGW\msys\1.0\home\nakamura\kadai*,・・・・・・・・・・・・x*ツ・ン〔・,・・・・・・x*ツ・ン〔・ クAツ・ツ,tail,, 1:ソート 2:削除 3:追加 4:参照 0:終了 メニューを選択してください: 。 1:ソート 2:削除 3:追加 4:参照 0:終了 メニューを選択してください:4 クAツ・ツ0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[]^_`abcdefghijklmnopqrstuvwxyz{|}~€ 。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚ 1,hijklmnopqrstuvwxyz[]^_`abcdefghijklmnopqrstuvwxyz{|}~€ 。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚ 1,ネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚ 1,ヤユヨラリルレロワン゙゚ 1 クAツ・ツ,,ミムメモヤユヨラリルレロワン゙゚ ,ワン゙゚  クAツ・ツ・・・  ,  ,, クAツ・ツ,C:\MinGW\msys\1.0\home\nakamura\kadai*,・・・・・・・・・・・・x*ツ・ン〔・,・・・・・・x*ツ・ン〔・ クAツ・ツ,tail,, 1:ソート 2:削除 3:追加 4:参照 0:終了 メニューを選択してください: */

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nob.

2017/12/04 01:47

本来なら、どういう動きをするプログラムで、質問者さんご自身はどこまでの動きを確認したか、それを書いてください。「ソースコードを提示するので考えて下さい」では、あんまりです。
yumetodo

2017/12/04 02:16

ついにでcsvの文字コードと実行環境についても追記してください
PineMatsu

2017/12/04 08:00

示されているURLは質問サイトですよね。そこの質問者もうまく動かないので質問されて色々と修正しているようですが、このteratailでの質問はそれらの修正は掛けられた状態なのですか?
退会済みユーザー

退会済みユーザー

2017/12/04 20:40

URLの質問サイトで取得したプログラムで修正に従って修正して実行したのですが、上手くいかなくて、似たようなプログラムを参考にして、自自分修正して実行しています。コメント欄が折り返しができないのですが、おしえていただけますか。お願いいたします。
guest

回答3

0

原因を指摘するより「デバッグをすること」をお勧めしたいです(nobさんと同じことを言っています)。デバッグプリントで変数の内容を調べればプログラムがどう動いているかだんだんわかってくるはずと思います。それを殆どしていないのがわからない原因ではないでしょうか。

最初に覚えるべき基本的テクニックの一つは「変数の中身がどうなっているかをデバッガーやデバッグプリントで確認する」ことだと思います。その結果で変数の中身が期待通りかどうか判断し、期待どおりでなければさらに「それはなぜか」を別の変数の中身やプログラムがどのルートを通過したかなどを調べる・・・というふうに次々に原因を絞り込むことができます。

IDEを使うと一々デバッグプリントを入れなくてもステップ実行しながら変数の中身をみていくだけでもかなりのことが分かります。が、しかし大量の実行ステップがあるようなコードだと一ステップずつデバッガーでコードの動きや変数の中身を確認するのは苦行です。ブレークポイントを設定したとしても何度も実行されるループの内側などだとやはり苦行です。

そうした場合、やはり「デバッグプリントによる調査」のが必要になるでしょう。デバッグプリントを入れすぎると結果が大量に出すぎてこれまたわからなくなることもあります。そういう場合はさらに「デバッグプリントを出すタイミングを工夫する」といったことも必要かも知れません。

要するにプログラムを書いたり動かすには何かしら考えて・工夫しないと作業は進まないということを申し上げたいです。

コードを眺めただけで原因がわかる確率を上げるにはそれに応じた経験が必要です。コードを眺める必要がないとはいっていません。眺めることは必要ですがそれだけで解決できるは限らないということです。ソースを見てもわからなければ次にすべきはプログラムのデバッグです。デバッグにも経験は必要ですが、それがうまく行えないなら質問するより先にデバッグの経験を積むべきと思います。


追記:回答コメントを拝見すると、質問者さんはやはりデバッグをどうすべきか戸惑っている印象でした。それを解説したようなサイトをあまり見ないので少しデバッグのtipsめいたものをコメントしてみます。

###何を考えるべきか
ライブラリーの仕様やCの言語仕様などに充分な確信がない状態の段階ではソースを眺めるだけで原因を特定するのはまず無理です。なぜならバグが起こっている典型的な状況は「プログラマーのこう動くはずだという思い込み」に起因しているからです。「間違ったことを思い込んでいる」のですからそれに自分で気づけないのは当然です。

デバッグを学ぶ際には「自分がそうだと思っていること」を疑うことが肝心です。

例1: fscanfで読み込んだ結果はこうなるはず=>本当にそうか疑う
例2: strtokで1行に4つの要素を切り出せるはず=>本当にそうか疑う

###何を確認するか

疑うことができたならそれが実際にどうなっているかを確認します。デバッグプリントの利点は「こうなっているはず」という推測を「実際にそうなっている」という事実に変えられることです。

例1は実際にfscanfの結果をデバッグプリントすればはっきるするでしょう。場合によっては「行末の見えない空白文字」などに翻弄されることがあるでしょうから
printf("%s\n", buffer);ではなく、
printf("'%s'\n", buffer);とするなどの工夫も有効です。こうしたこともデバッグtipsの一つです。(だれでもデバッグに苦労した経験から、こうした工夫は自然に思いつくものです)

例2は「1つ目、2つ目、・・・の切り出し結果を全てデバッグプリントする」とヒントが得られるでしょう。4つトークンがあるはずという予測で例えば2つ目の切り出し結果が「あ!行末まで2つ目のトークンとして読み込まれてる!」といった具合に予想とは違っている事実がわかるからです。

こうして「こうなるはず」という点を一つ一つ確認するくせをつけてください。知識が充分でないうちは確認することも多く大変面倒なのですがその訓練さえ積めば、コードの内容により確信を持つことができるようになり自然にデバッグプリントの量も減り、最後にはまったくデバッグせずとも書いたコードが一発で動くようになっていきます。それは保証します。


こういうふうにデバッグをしても、「なぜそうなるかわからない」というこtもあるでしょう。その場合にこそ「こうデバッグした結果、こういう事実がわかった。でもなぜかわからない」と質問しましょう。今の状態の質問よりはずっとアドバイスが得られやすくなるでしょう。

投稿2017/12/05 01:46

編集2017/12/06 00:24
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/12/05 21:48

はい、デバッグは少しずつ勉強しています。おっしゃるようにgdbを実行して,プリントアウトして変数を調べて、検討しています。最初の質問にはデバッグのエラー箇所の結果を載せていたのですが、 このサイトは初心者のマークを付けて質問させていただいています。貴重な意見をありがとうございます。 質問を丸投げしているつもりはないのですが、結果的にそうなんですね。 色々行った結果わからなくて質問しているつもりですが、よくそう言われます。へこみますね。 がんばります。
退会済みユーザー

退会済みユーザー

2017/12/06 04:42

丁寧な説明ありがとうございます。やってみます。
退会済みユーザー

退会済みユーザー

2017/12/06 08:02

住所録のプログラムを検索してダウンロードしたものですが、勉強には不向きでした。 ありがとうございました。
guest

0

  • csvに空白が混じっています
  • int selectが初期化されずに非0で初期化されることを期待しています
  • 何を格納してるんでしょうか?

pが使われていません(切り出しに失敗云々全部削除してコメントアウトを戻すと動作する)

  • ソートは…なんというか意味不明 酷すぎて言葉が出ない。自力で実装した方がいい

投稿2017/12/05 00:28

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/12/05 21:50

へんじありがとございます。今日はお仕事なので後でチェックしてみます。
退会済みユーザー

退会済みユーザー

2017/12/06 05:07

ソートはデータを追加したときの整列です。
guest

0

ベストアンサー

"address.csv"をメニュー4dumpで参照すると文字化けしています。

そもそも切り出した文字列を pの中に格納してないよね。だったら化けてアタリマエ。

numberの切り出しに失敗しました。とあるので、これが影響していそうなのですが
コードの直し方がわかりません。よろしくお願いします。

sato,tokyo ,090-3333,mail1-4 は空白を含んでいます。だから、

while(fscanf(fp,"%s",ch)!=EOF)

このfscanfで読み出されるのは "sato,tokyo" 、尻切れなのでその後に続くはずの numberが切り出せない。

投稿2017/12/06 00:14

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2017/12/06 07:48

なんでコレがベストアンサーなのよ...
退会済みユーザー

退会済みユーザー

2017/12/06 07:59

ありがとうございます。numberの切り出しに失敗しました。は消えたのでこの質問は終わりにしたいと思います。このプログラムは私が勉強するには不備が多すぎて、コンパイル、実行まではいくのですが、上手く動かすことができませんでした。途中 3追加ができたり、1ソートが出来たりしていましたが、いじり過ぎて 4参照、0終了だけができる状態です。住所録のプログラムを勉強するには不都合でしたが、これとほとんど同じでちゃんと動くプログラムで勉強したいと思います。 そのときはまたお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問