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

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

ただいまの
回答率

91.35%

  • C

    2528questions

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

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

解決済

回答 3

投稿 2017/12/04 10:34 ・編集 2017/12/06 07:02

  • 評価
  • クリップ 0
  • VIEW 218

sanchu52

score 58

ダウンロードしたプログラムでエラーが出て実行できない。
元々エラーの出る質問プログラムでした。
修正しながらうまくいきましたというコメントがありましたが、
私はうまくいきませんでしたので
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:終了
メニューを選択してください:

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • PineMatsu

    2017/12/04 17:00

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

    キャンセル

  • sanchu52

    2017/12/05 05:40

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

    キャンセル

  • 退会済みユーザー

    2017/12/06 17:02

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 3

+3

原因を指摘するより「デバッグをすること」をお勧めしたいです(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 10:46

編集 2017/12/06 09:24

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/06 06:48

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

    キャンセル

  • 2017/12/06 13:42

    丁寧な説明ありがとうございます。やってみます。

    キャンセル

  • 2017/12/06 17:02

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

    キャンセル

+1

  • csvに空白が混じっています
  • int selectが初期化されずに非0で初期化されることを期待しています
  • 何を格納してるんでしょうか?
    pが使われていません(切り出しに失敗云々全部削除してコメントアウトを戻すと動作する)
  • ソートは…なんというか意味不明 酷すぎて言葉が出ない。自力で実装した方がいい

投稿 2017/12/05 09:28

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/06 06:50

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

    キャンセル

  • 2017/12/06 14:07

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

    キャンセル

checkベストアンサー

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 09:14

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/06 16:48

    なんでコレがベストアンサーなのよ...

    キャンセル

  • 2017/12/06 16:59

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

    キャンセル

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

ただいまの回答率

91.35%

関連した質問

同じタグがついた質問を見る

  • C

    2528questions

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