掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.24751

fgets
投稿者---ace(2005/12/12 18:28:19)


私は今あるプログラムを作っていてまだ途中なのですが
どうしても自作関数void create(void)のなかの
fgetsを使ってキーボードから名前を入力したいのですが
fgetsをスルーします。
原因がわかる方アドバイスお願いします。
#include <stdio.h>
#include <process.h>
#define limit 61
void create();
void display(int);
void update(int);
void kanri();
void crean();
char name[limit];
int  pro;
main()
{
    printf("C言語ソースファイル管理\n\n");
    printf("        <メニュー画面>\n\n");
    printf("    1. 新規ファイルの作成\n");
    printf("    2. 既存ファイルの内容表示\n");
    printf("    3. 既存ファイルの内容変更\n");
    printf("    4. 既存ファイルの管理\n\n");
    printf("    9. 処理終了\n\n");
    printf("    希望する処理番号を入力してください:");
    for( ;scanf("%d", &pro) ; )
    {
        if(1 <= pro && pro <= 4)
        {   
            crean();
            switch(pro)
            {
                case 1:
                    create();
                    break;
                case 2:
                    display(0);
                    break;
                case 3:
                    update(0);
                    break;
                default:
                    kanri();
                    break;
            }
            break;
        }
        else if(pro == 9)
        {
            crean();
            break;
        }
        else
        {
            printf("    処理番号が適切ではありません。\n");
            printf("    希望する処理番号を入力してください:");
        }
    }
}
void create(void)
{
    printf("C言語ソースファイル管理\n\n");
    printf("        <新規ファイル作成処理>\n\n");
    printf("    作成するファイル名を入力してください。\n");
    printf("    (メイン画面に戻るには、何も入力せずに改行キーを\n  押してください)\n\n");
    printf("    新規ファイル名:");
    fgets(name, limit, stdin);
    printf("%s", name);
}
void display(int a)
{
    
}
void update(int b)
{
    
}
void kanri()
{
    
}
void crean()
{
    system("cls");
}




この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:fgets 24752 REE 2005/12/12 18:56:10


No.24752

Re:fgets
投稿者---REE(2005/12/12 18:56:10)


>fgetsをスルーします。
>原因がわかる方アドバイスお願いします。

http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-4
の(2)が原因です。



この投稿にコメントする

削除パスワード

No.24753

Re:fgets
投稿者---ace(2005/12/12 19:46:02)


改行文字が残るのが原因なのですか?


この投稿にコメントする

削除パスワード

No.24754

Re:fgets
投稿者---REE(2005/12/12 20:51:26)


>改行文字が残るのが原因なのですか?

はい、fgetsは改行文字まで読むので、
その残った改行文字を読んで終了します。



この投稿にコメントする

削除パスワード

No.24755

Re:fgets
投稿者---ace(2005/12/12 20:56:53)


scanfでは書式指定のところで改行を読み捨てる方法がいくつか記載されていますがfgetsはどのようにして改行文字を読み捨てるとよいのですか?


この投稿にコメントする

削除パスワード

No.24757

Re:fgets
投稿者---iijima(2005/12/12 21:35:24)


ちょっと勘違いされているようです。

今回の問題は、scanfのところでリターンキーによって入力された改行文字
がバッファに残り、それがfgetsで読まれるので、(見た目は何もしないで)
すぐに次の処理に移ってしまうということです。
これは、scanfのところで改行文字を読み捨てるようにすれば解消します。
# REEさんもこのことを指摘されたのだと思います。

fgetsは改行文字を含む1行を読み込み、バッファに改行文字を残しません
から、ここで読み捨てを考える必要はありません。
ただし、fgetsで読み込んだ文字列の最後には改行文字'\n'まで入りますの
で、それがいらないという場合は終端文字'\0'に置き換えるといった処理
が別途必要になります。


この投稿にコメントする

削除パスワード

No.24758

Re:fgets
投稿者---RAPT(2005/12/12 23:39:27)


>ただし、fgetsで読み込んだ文字列の最後には改行文字'\n'まで入りますの
>で、それがいらないという場合は終端文字'\0'に置き換えるといった処理
>が別途必要になります。

厳密に言うなら、改行文字を読み込む前にバッファサイズに達した場合は、
改行文字まで読み込まれないので、バッファの最後の文字が、改行文字
だったら、これを置き換える、ってことになります。



この投稿にコメントする

削除パスワード

No.24759

Re:fgets
投稿者---ace(2005/12/13 00:11:09)


皆さんに意見を参考にプログラムを少し作ったのですが
,fgetsにすると新規ファイルを作成してくれません。
,scanfにすると作成してくれるのですが。
\nも読み捨てするようにしているのですが原因がわかりません。

#include <stdio.h>
#include <process.h>
#define limit 61
void create();
void display(int);
void update(int);
void kanri();
void crean();
FILE *fp;
char name[limit];
int  pro;
main()
{
    printf("C言語ソースファイル管理\n\n");
    printf("        <メニュー画面>\n\n");
    printf("    1. 新規ファイルの作成\n");
    printf("    2. 既存ファイルの内容表示\n");
    printf("    3. 既存ファイルの内容変更\n");
    printf("    4. 既存ファイルの管理\n\n");
    printf("    9. 処理終了\n\n");
    printf("    希望する処理番号を入力してください:");
    for( ;scanf("%d%*c", &pro) ; )
    {
        if(1 <= pro && pro <= 4)
        {   
            crean();
            switch(pro)
            {
                case 1:
                    create();
                    break;
                case 2:
                    display(0);
                    break;
                case 3:
                    update(0);
                    break;
                default:
                    kanri();
                    break;
            }
            break;
        }
        else if(pro == 9)
        {
            crean();
            break;
        }
        else
        {
            printf("    処理番号が適切ではありません。\n");
            printf("    希望する処理番号を入力してください:");
        }
    }
}
void create(void)
{
    char sorse[limit];
    printf("C言語ソースファイル管理\n\n");
    printf("        <新規ファイル作成処理>\n\n");
    printf("    作成するファイル名を入力してください。\n");
    printf("    (メイン画面に戻るには、何も入力せずに改行キーを\n  押してください)\n\n");
    printf("    新規ファイル名:");
    fgets(sorse, limit, stdin);
    if(*name == '\n')
    {
        crean();
        main();
    }
    else
    {
        fp = fopen(name,"r");
        if(fp == NULL)
        {
            crean();
            printf("    新たにファイルを作成しました。\n");
            printf("    ソースファイルへの入力を開始してください。\n");
            fp = fopen(name, "a");
            for( ; fgets(sorse, limit, stdin) != NULL; )
            {
                fputs(sorse, fp);
            }
        }
        else
        {
            fclose(fp);
            printf("\n  1. 内容を印字する\n");
            printf("    2. 内容を更新する\n");
            printf("    希望する処理番号を入力してください:");
            for( ;scanf("%d%*c", &pro) ; )
            {
                if(pro == 1 || pro == 2)
                {
                    crean();
                    switch(pro)
                    {
                        case 1:
                            display(1);
                            break;
                        case 2:
                            update(0);
                            break;
                    }
                    break;
                }
                else
                {
                    printf("    処理番号が適切ではありません。\n");
                    printf("    希望する処理番号を入力してください:");
                }
            }
        }
    }
}
void display(int a)
{

}
void update(int b)
{

}
void kanri()
{

}
void crean()
{
    system("cls");
}



この投稿にコメントする

削除パスワード

No.24761

Re:fgets
投稿者---まきじ(2005/12/13 00:29:07)


>,fgetsにすると新規ファイルを作成してくれません。

ファイル名 は sorse に格納されているのに fopen(name,・・・ となってますが?

>if(fp == NULL)
>printf(" 新たにファイルを作成しました。\n");

fp は NULL なのに「ファイル作成しました」で良いの?

# 因みに"ソース"の綴りは "source" です。
# "クリア" の綴りは "clear" です。


この投稿にコメントする

削除パスワード

No.24762

Re:fgets
投稿者---ace(2005/12/13 00:46:29)


>>,fgetsにすると新規ファイルを作成してくれません。
>
>ファイル名 は sorse に格納されているのに fopen(name,・・・ となってますが?
>
>>if(fp == NULL)
>>printf(" 新たにファイルを作成しました。\n");
>
>fp は NULL なのに「ファイル作成しました」で良いの?
>
># 因みに"ソース"の綴りは "source" です。
># "クリア" の綴りは "clear" です。
sorseをnameに変えてもだめでした。
if(fp == NULL)は入力したファイル存在するかどうかを確かめるために
fopen(name,"r")で開いて
存在しない(NULL)なら
fopen(name,"a")で開いて存在しないので
新たにファイルを作成する処理です。
わかりずらくてごめんなさい。


この投稿にコメントする

削除パスワード

No.24764

Re:fgets
投稿者---まきじ(2005/12/13 00:57:28)


>sorseをnameに変えてもだめでした。

fopen() のモードが "r" だからです。

>fopen(name,"a")

の戻り値が NULL だったらどうするのですか?


この投稿にコメントする

削除パスワード

No.24771

Re:fgets
投稿者---wiz(2005/12/13 02:58:20)


>fopen() のモードが "r" だからです。

多分勘違いされていると思うのですが

>fp = fopen(name,"r");
>if(fp == NULL)
ここでファイルが存在した場合にオープンして失敗したら
存在しないってことにしてから
>printf(" 新たにファイルを作成しました。\n");
>printf(" ソースファイルへの入力を開始してください。\n");
>fp = fopen(name, "a");
ここで存在しなかったので新しくファイルを作成するってことでしょう。
メッセージの後に処理しているのでわかりにくいですが。。。




この投稿にコメントする

削除パスワード

No.24773

Re:fgets
投稿者---まきじ(2005/12/13 03:27:47)


>>fopen() のモードが "r" だからです。
>多分勘違いされていると思うのですが

あ、本当ですね・・勘違いしてました。
存在確認なら "r" で良いですね。
そもそも、新規ファイルなのに存在確認が必要なの?

で「作成しました」を表示するタイミングがおかしい。
fopen(name,"a") が NULL でない時に表示するのでは?

>if(*name == '\n')

は name[0] の方が判りやすいかと。
char name[limit]; と宣言してるし・・


あと main() を呼び出すより do{  }while(); とかの方が良いのでは?


この投稿にコメントする

削除パスワード

No.24778

Re:fgets
投稿者---wiz(2005/12/13 11:04:33)


fgets(name, limit, stdin);
ここに'\n'を終端文字'\0'に置き換える処理を入れてください
fp = fopen(name,"r");

#ファイル名に改行コードがはいってるのが原因・・・?
#fopenのパラメータになにか制限があるのかな。。。

for( ; fgets(sorse, limit, stdin) != NULL; )
この条件ではfgetsが成功している間ループするので
終了させるのが難しいかも


この投稿にコメントする

削除パスワード

No.24779

Re:fgets
投稿者---まきじ(2005/12/13 12:17:45)


>for( ; fgets(sorse, limit, stdin) != NULL; )
>この条件ではfgetsが成功している間ループするので
>終了させるのが難しいかも

Ctrl + Z あるいは Ctrl + D で終了できます。


この投稿にコメントする

削除パスワード

No.24809

Re:fgets
投稿者---ace(2005/12/14 20:28:12)


まじきさんプログラムがわかりにくくてすみません。
wizのいうとおりファイル名に'\n'が含まれていたのが原因みたいです。
fgetsで名前を入力したあと'\n'を'\0'に変える処理を加えたところ
ファイルを作成してくれるようになりました。
アドバイスを下さった皆さんありがとうございます。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧