fgets関数に関して

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
sky

fgets関数に関して

#1

投稿記事 by sky » 15年前

はじめましてskyです。fgets関数を用いてpgmファイルの始めの2行(添付ファイルの場合, P2, 304,322)をそれぞれ、変数header, width, heightに格納するプログラムを考えているのですがfgets関数は一行ずつ読み込む関数ですよね?304,322は同じ行にあるのにこれを別々の変数に格納する方法がよくわかりません。

サイトや参考書を見て以下までできました。これからどうしたら良いか行き詰ってます。
OS:UNIX,コンパイル:gcc

#include<stdio.h>
#define BUFFER_SIZE 200
void main(){
char buffer[BUFFER_SIZE];
FILE *fp;
fp = fopen("test_barbarar.pgm", "r");

// ファイルオープン失敗か?
if ( !fp ){
printf("ファイルオープンエラー\n");
return;
}

// 1行ずつ読み込んで表示する
while( fgets(buffer, BUFFER_SIZE, fp) ){
printf("%s", buffer);
}

// ファイルクローズ
fclose(fp);
}

添付ファイルtest_barbarar.のサイズが大きくて貼れなかったので、初めの4行は以下のようになってます。
P2
304 322
255
161 162 162 161 161 162 160 160 157 158 165 163 161 164 163 165 164 162


長々と失礼しました。どうかよろしくお願いします。

バグ

Re:fgets関数に関して

#2

投稿記事 by バグ » 15年前

fscanf関数を使用してはいかがでしょうか?

バグ

Re:fgets関数に関して

#3

投稿記事 by バグ » 15年前

#include<stdio.h>

#define BUFFER_SIZE 200
#define HEADER_SIZE 8

int main(void)
{
    char buffer[BUFFER_SIZE] = {0, };
    char header[HEADER_SIZE] = {0, };
    int width = 0, height = 0;
    FILE *fp;

    // ファイルオープン
    fp = fopen("test_barbarar.pgm", "r");

    // ファイルオープン失敗か?
    if (fp == NULL)
    {
        printf("ファイルオープンエラー\n");
        return;
    }

    // header, width, heightを読み込む
    fscanf(fp, "%s", header);
    fscanf(fp, "%d%d", &width, &height);

    // header, width, heightを表示する
    printf("header = %s\n", header);
    printf("width  = %d\n", width);
    printf("height = %d\n", height);

    // ファイルクローズ
    fclose(fp);

    return 0;
}

バグ

Re:fgets関数に関して

#4

投稿記事 by バグ » 15年前

おっと、ファイルオープンに失敗した際の戻り値を設定するのを忘れておりましたm(__)m
#include<stdio.h>

#define BUFFER_SIZE 200
#define HEADER_SIZE 8

int main(void)
{
    char buffer[BUFFER_SIZE] = {0, };
    char header[HEADER_SIZE] = {0, };
    int width = 0, height = 0;
    FILE *fp;

    // ファイルオープン
    fp = fopen("test_barbarar.pgm", "r");

    // ファイルオープン失敗か?
    if (fp == NULL)
    {
        printf("ファイルオープンエラー\n");
        return -1;
    }

    // header, width, heightを読み込む
    fscanf(fp, "%s", header);
    fscanf(fp, "%d%d", &width, &height);

    // header, width, heightを表示する
    printf("header = %s\n", header);
    printf("width  = %d\n", width);
    printf("height = %d\n", height);

    // ファイルクローズ
    fclose(fp);

    return 0;
}

sky

Re:fgets関数に関して

#5

投稿記事 by sky » 15年前

バグさん、丁寧にご回答まことにありがとうございます。
一応課題でfgetsを使うことを指定されています。fgetsは一行ずつファイルから読み込む関数と解釈しているのですが添付ファイルの2行目が304 322となってるので これをそれぞれ違う変数に格納するやり方を教えて頂ければ幸いです。私の記述の仕方が悪かったです。本当にすみません。

non

Re:fgets関数に関して

#6

投稿記事 by non » 15年前

fgetsをした後で、sscanfを使う方法があります。

たかぎ

Re:fgets関数に関して

#7

投稿記事 by たかぎ » 15年前

ちがう変数とのことですが、どんな変数でしょうか?
例えば、文字列として扱えばよいのであれば、sscanfよりstrtokの方がむしろ楽です。
整数値として扱うのであれば、strtolやstrtoulを使うべきです(もちろん、strtollやstrtoimaxが使えるなら、それでもOK)。

sky

Re:fgets関数に関して

#8

投稿記事 by sky » 15年前

nonさん>>
ありがとうございます。fgets関数で2行分だけ読み込みsscanfを用いるということでしょうか。
2行分だけ読み込むことは可能なんですかね?

たかぎさん>>
お手数おかけします。返答ありがとうございます。
304と322という整数をそれぞれ widthとheightに格納するということです。

問題がfgets関数を用いてpgmファイルの始めの2行(添付ファイルの場合, P2, 304,322)をそれぞれ、変数header, width, heightに格納するプログラムを作成せよ。
ってなっててstrtolやstrtoulはまだ習ってないです。ホントにすみません。 画像

バグ

Re:fgets関数に関して

#9

投稿記事 by バグ » 15年前

それならば、nonさんの言われるように、fgets関数でいったん文字列としてファイルの内容を取得しておいて、sscanf関数を使用して、文字列→数値へ変換してやればいいと思いますよ。
これらの手間を一度に行えるのがfscanf関数なので、結局同じことではあるのですが…(^_^;)

sscanf関数の使い方が分からなければ、下記URLを参照ください。
http://www.bohyoh.com/CandCPP/C/Library/sscanf.html

sky

Re:fgets関数に関して

#10

投稿記事 by sky » 15年前

バグさん本当にありがとございます。
プログラム苦手なので考えるのに時間がかかりますけどやってみます。
また分からないことがあればよろしくお願いします。

sky

Re:fgets関数に関して

#11

投稿記事 by sky » 15年前

今先生に確認をしたところfgetsのみでやりなさい(fscanfやsscanf使わないでやって)。と言われました汗
すみません。 画像

Blue

Re:fgets関数に関して

#12

投稿記事 by Blue » 15年前

トークン分割用:strtok
  数値変換用:strtolやatoi(はあまりよろしくないけど)

はつかってもよい?

そもそも
>304と322という整数をそれぞれ widthとheightに格納するということです。
widthとheightは何型?
char型の配列であれば、strtolとかは不要。
画像

sky

Re:fgets関数に関して

#13

投稿記事 by sky » 15年前

Blueさん
strtokも使ってはいけないみたいです。widthとheightは何型か特に指定されていないです。 画像

Blue

Re:fgets関数に関して

#14

投稿記事 by Blue » 15年前

>widthとheightは何型か特に指定されていない
のであれば、char型配列にしてしまえばw

2行目は先頭から空白の手前までをwidthに、空白の後ろから改行もしくは終端までをheightに
入れるような処理を書けばよいですね。

未検証だけどこんな感じ?
char width[8] = ""; // サイズは適当
char height[8] = "";
char* p; // 検索用
int i;   // 格納用

i = 0;
for (p = buffer; *p != ' ' && *p != '\0'; ++p, ++i) {
    width = *p;
}
width = '\0';

if (*p != '\0')
{
    ++p;
    i = 0;
    for (; *p != '\0' && *p != '\n'; ++p, ++i) {
        height = *p;
    }
    height = '\0';
}

画像

sky

Re:fgets関数に関して

#15

投稿記事 by sky » 15年前

Blueさん>>
ありがとうございます。すこしお尋ねしたいのですが…
width = *p;
}
width = '\0';←これはどういう意味ですかね?

Blue

Re:fgets関数に関して

#16

投稿記事 by Blue » 15年前

>width = '\0';←これはどういう意味ですかね? 
文字列の終端文字を格納しているだけです。

sky

Re:fgets関数に関して

#17

投稿記事 by sky » 15年前

全体的なのがまだできてないのでもうすこし考えてみます。
丁寧にご回答ありがとうございました。

sky

Re:fgets関数に関して

#18

投稿記事 by sky » 15年前

Blueさん>>
参考にさせてもらいました。以下のようにしたのですが…
#include <stdio.h>

#define BUFFER_SIZE 200

void main(){
char buffer[BUFFER_SIZE];
char header[10];
char width[10]="",height[10]="",space[10];//格納
char *p;
int i;

FILE *fp ;
FILE *new;

fp = fopen("test_barbarar.pgm", "r");

// ファイルオープン失敗か?
if ( !fp ){
printf("ファイルオープンエラー\n");
return;
}


fgets(header, BUFFER_SIZE, fp);
printf("header=%s", header);

fgets(buffer, BUFFER_SIZE, fp);
i = 0;
for (p = buffer; *p != ' ' && *p != '\0'; ++p, ++i) {
width = *p;
}
width = '\0';

if (*p != '\0')
{
++p;
i = 0;
for (; *p != '\0' && *p != '\n'; ++p, ++i) {
height = *p;
}
height = '\0';
}

printf("width=%s", width);
printf("height=%s", header);

// ファイルクローズ
fclose(fp);
}

実行結果
header=p2
width=(null)header=(null)
となってしまいます。何がいけなかったのでしょうか?何度もすみません。

fatens

Re:fgets関数に関して

#19

投稿記事 by fatens » 15年前

>fgets(header, BUFFER_SIZE, fp);
header[/url]のサイズは10なのに、関係のないBUFFER_SIZEを渡すのはどうかと。
10 または、sizeof(header) / sizeof(header[0]) にするほうが良いと思います。

>printf("width=%s", width);
>printf("height=%s", header);
printf 関数に渡すべきは文字列の先頭アドレスなのに、文字を渡しています。
また、このときのiは何を意図しているのでしょう?

閉鎖

“C言語何でも質問掲示板” へ戻る