• ベストアンサー

ファイルから読み出し

ファイルを読み込んで画面表示するプログラムを作っているのですが、ファイルの扱い?がよくわかりません。 以下のフォーマット・書式とします。 ・フォーマット 番号__氏名__年齢 ・書式 番号:半角3桁まで 氏名:半角/全角問わずで半角20文字/全角10文字まで 年齢:半角2桁まで この場合に、以下のようにするとこの行で止まってしまいます。 特にエラーが出ていないのです。何故なんでしょう? fscanf(*fp,"%3d %20s %2d",&p->no,&p->name,&p->age);

質問者が選んだベストアンサー

  • ベストアンサー
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.7

以前の質問も含め、この意味不明キャストは講師の指示な訳ですね。そこは了解しました。 #しかし酷い講師だなぁ……せめて名前くらいは役割に合わせればいいものを。 > 「文字列(半角スペース)文字列」の場合に、半角スペース後の文字列が > 次の数字と勘違いされてしまいます。 > これを分離せずに理解させる方法はないものでしょうか? scanf()系を使い、セパレータを半角スペースにしている限りは無理です。strchr()とstrncpy()の複合で文字列解析・分解するかなぁ。 ベタに「20文字+前後半角スペース」って決めうちなら fscanf(fp, "%3d%22s%3d\n", &no, name, &age); としておいてnameに入る前後スペースを後で除去する方向でもいけるかもしれませんが、私ならこの方法はとりません。

sakuranb22
質問者

お礼

氏名の後の年齢が固定値(2桁数字)なので それを判断基準に入れてそうでなければ半角+名前の続きと 認識させて前の文字列につけるというのはどうでしょうか (まだ試していないです) そもそもファイルに登録されているということは それが正しい値である、という裏付けになるので 半角後の氏名が数字2桁で無い限りは氏名であると断言 出来る事になります。 まだ作成していませんが、新規で「番号__氏名__年齢」を 追加する際に、番号や年齢には入力制限を課すため、 入力保存したファイルを読み込む時には正しい値が ファイルに格納されているのは保証されると思ってます。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (9)

  • Lchan0211
  • ベストアンサー率64% (239/371)
回答No.10

> ・フォーマット > 番号__氏名__年齢 > 氏名:半角/全角問わずで半角20文字/全角10文字まで となっているのだから、無条件で20文字を取得するのは 出された課題の仕様に違反しているのでは? 半角プランクが出現した時点で氏名の終わりと認識する のが課題の仕様だと思いますよ。 FILE*をconst char *にキャストしている件についても、 課題内容をそのまま見せていただいてないので想像ですが、 たぶん課題の指示は、const char *で「ファイル名」を引き渡すこと であって、ファイルポインタ(FILE*)をキャストして渡せとは 書いてないのでは? もっと課題の仕様をよく読んで、思い込みの解釈をしないよう 気をつけるべきかと思います。

sakuranb22
質問者

お礼

課題の指示では int file_read(const char* pFileName); を使う事が指示なのでいかに自分の思い込みが正しかろうと自分本位に作っては意味がないのです。 経験者というにも関わらず、実務経験が無いんじゃないでしょうか? こう言う形で提供してくれと言われたらどういう理由があろうとそう返すべきでは? そこで勝手に自分で変えて調整されてない内容の引数を渡したところでは本末転倒ですよ。 人は名前を書くときどうしますか? 田中一郎さんがいやとした場合、書き方は以下なだけあり、全てに対応する必要があります。 「田中一郎」 「田中(全角スペース)一郎」 「田中(半角スペース)一郎」 「ichiro tanaka」 後者の2つは正確に読み取れなくなります。 意図した動きをしないことが仕様違反です。 半角スペース以後を年齢と取る事が仕様とでもいいたいのですか? あなたも思い込みの激しい解釈をしたコメントはしない方がいいですよ。

全文を見る
すると、全ての回答が全文表示されます。
回答No.9

malloc からの戻り値はキャストしましょう。 また malloc と free は対です。 確保したメモリはどこへ行ってしまったのでしょう???

sakuranb22
質問者

お礼

>freeしていない理由 他の方へのコメントだけみればその理由がわかります

全文を見る
すると、全ての回答が全文表示されます。
  • arain
  • ベストアンサー率27% (292/1049)
回答No.8

No.5 >さらにお聞きしたいのです。 >ファイルから読み込む際ですが、数字_文字列(半角20文字固定)_数字と並んでいる中、 >この文字列が「文字列(全角スペース)文字列」ならば大丈夫ですが、 >「文字列(半角スペース)文字列」の場合に、半角スペース後の文字列が >次の数字と勘違いされてしまいます。 fscanf()を使用し間に半角スペースがある限り回避は不能。 データフォーマットでそれぞれの項目が固定長であればfread()で取り込んで分割するといったことはできるけど…… No.6 >あなたにはあなたの教え方があるし、 >講師には講師の教え方がある、それで納得していただけませんかね? 「理解」はしますが「納得」は無理ですね。 >講師がダメであると言って何をしたいんでしょうか・・・・ 「何をしたい」ではなく「教えられてる生徒がかわいそう」とは思いますよ。 一番重要な「可読性」とか「設計の容易さ」ってところを台無しにしてかえってC言語をわかりにくくしてますから。 特に「学校」で「教える」ということであれば、捻ることよりも基本機能を理解し覚えることを重要視すべきであり、 今回であれば、「ファイルの読み込み」と「動的なメモリ確保(と構造体のポインタ操作)」の二点でしょう。 その部分を重要視すべきであり、引数の件はやるべきではないですね。 引数をやるのであれば、関数で「戻り値」や「値渡し」「参照渡し」といったところで行うべきですから。 本来こういった流れになるはずです。 ---------- (前提として、関数、構造体、ポインタ[メモリ操作]を学習している) 1.ファイルの種類、ファイルのオープン/クローズを学ぶ 2.ファイルの読み書きを学ぶ(fscanf、fread、fgetsなど) 3.ファイル名を別の関数に渡して、開いたファイルのファイルポインタを返す関数を作る 4.(3.のファイルポインタを利用して)ファイルの読み書きを行う関数を作る ---------- 類似の質問や、インターネット上にある「質問と同じような引数名のソースを使用している」C言語の説明サイトなどからすれば、 こんな感じで教えるのが妥当と思いますが。

sakuranb22
質問者

お礼

あなたは何のためにこのQ&Aを利用しているのでしょうか? 見たところ土日祝日以外の昼間を中心に利用しているようですが、 社会人であれば労働時間帯ですよね。会社では2chが使えないから 利用できる掲示板で、相手の気持ち等無視して、自分の意見や考えを 無理矢理押し付けたい、そう取れます。 おそらくyahoo知恵袋も同就業時間帯に用いて同じ事をしているの だと思いますが・・。 あなたがやっていることは質問者の意図した回答ではなく、 あなた個人の思う意見の押し付けと他人に対する誹謗中傷以外の 何物でもないです。どうしても言いたい事を書くのを抑えて本分を アドバイスをするか、或いはそれさえも自制出来ないのであれば アドバイス自体を書くべきではないです。 非常に不快です。

全文を見る
すると、全ての回答が全文表示されます。
  • arain
  • ベストアンサー率27% (292/1049)
回答No.6

No.5から 今回(前にもた類似質問でもの類似質問)の場合は、どう考えても、 「main()でファイルオープンしたファイルポインタを渡す」ではなく、 「main()ではファイル名入力だけ、ファイルのオープンと読み込みは別の関数で」と考えるのが引数の型や名前からも正しいように思えますよ。 >仕様とは最低限これを入れろと言われたら入れるべきであって、 >他により良い方法を知っているとしてもそうはせずに >あくまで入れろと言われた方法でやるのが筋ではないでしょうか。 > 「これ」とはどこを示していますか? 類似質問を見ても、「ファイルポインタを渡して読み込みだけ行え」とは言っていないと思いますよ。 本当にそういう指示があったのなら、その講師の力量を疑います。 (というか、実務経験から言えば、「疑う」とか以前に「使い物にならない」と判断しますが) 関数や引数、変数等の命名は、プログラムをする上で「わかりやすく」つけるのが基本です。 わざわざひねくれたことをして認識間違いによるバグを誘発させるような行為は一番やってはいけないことです。 >何かしら意図があるものと思ってます。例えば、キャストを覚える、等。 キャストを覚えるのであれば、こういった変なキャストは行いません。 行うとしても通常void型のポインタへの変換です。 >講師がおかしいと自分本位でやってしまっては、それこそ仕様違反だと思います。 私なら、まずはこの意味不明なことをする講師に疑問をぶつけますが。

sakuranb22
質問者

お礼

実務と学校は違うでしょう。 実務でgetsやgotoは禁止ですが、学校では習いますし。 あくまで、基本的な遣い方だと思いますが。 あなたにはあなたの教え方があるし、 講師には講師の教え方がある、それで納得していただけませんかね? 講師がダメであると言って何をしたいんでしょうか・・・・

全文を見る
すると、全ての回答が全文表示されます。
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.5

> fscanf((FILE*)pFileName,"%3d %20s %2d\n",&p->no,p->name,&p->age); http://okwave.jp/qa4420902.html ↑でも指摘しましたが、関数のプロトタイプ宣言がint file_read(const char* pFileName)ならpFileNameには外でfopen()した結果のFILE *を無理やりconst char *にキャストして渡すのではなく、ファイル名を渡してfile_read()内でfopen()しましょう。これも課題なら、そう実装することが期待されています。 というか私が講師ならこんな実装を見たらたとえ動作してても落第にします。「仕様どおりに作ってない」ということで。 あと、pは(少なくとも初回は)NULLになってるのでsegmentation faultが発生するはずです。 ここはpではなくメモリを確保したばかりのmemが正しいのでは? pにmemを代入してもいいですが。 また、ループ終了条件が「ファイルを読みきった」であるはずですが、その判定が見当たりません。 ファイル終端に来てるのに検出せずに無限ループで回ってるのでは?

sakuranb22
質問者

お礼

仕様とは最低限これを入れろと言われたら入れるべきであって、 他により良い方法を知っているとしてもそうはせずに あくまで入れろと言われた方法でやるのが筋ではないでしょうか。 何かしら意図があるものと思ってます。例えば、キャストを覚える、等。 講師がおかしいと自分本位でやってしまっては、それこそ仕様違反だと思います。 memで解決しました! でも、ファイルを読み込むとうまく出来ないんですよね・・ ずれて読み込まれてしまうようです・・ ループに関してはとりあえず1周して動くのを確認してから 追加する予定です。自信がないのでちょっとずつ作ってます。

sakuranb22
質問者

補足

さらにお聞きしたいのです。 ファイルから読み込む際ですが、数字_文字列(半角20文字固定)_数字と並んでいる中、 この文字列が「文字列(全角スペース)文字列」ならば大丈夫ですが、 「文字列(半角スペース)文字列」の場合に、半角スペース後の文字列が 次の数字と勘違いされてしまいます。 これを分離せずに理解させる方法はないものでしょうか? 無条件で文字列20文字分を取得させるような方法ってないですか?

全文を見る
すると、全ての回答が全文表示されます。
  • arain
  • ベストアンサー率27% (292/1049)
回答No.4

firstの定義と、LISTメンバが無いので推測ですが おそらくNO.2氏の通りでしょう。 ちなみに >first.next=NULL; > >p=first.next; >q=&first; > >while(p!=NULL){ >q=p; >p=p->next; >} pはNULLなので、whileの意味がありませんが。 ところで、「ファイルポインタ」を使用するのに(const char* pFileName)とする理由は? この記述なら通常は「ファイル名」もしくは「フォルダも含めたファイル名」の渡し方ですが。 # 最近、まったく同じ引数の名前とFILE型キャストしているのを見た気がする。

sakuranb22
質問者

補足

同じクラスの人も質問してるのかもしれませんね^^ 色々と参考にさせていただいてます! >pはNULLなので、whileの意味がありませんが。 そうでした。

全文を見る
すると、全ての回答が全文表示されます。
回答No.3

構造体定義とかもほしいですね。 first はグローバル変数ですか? あとコンパイルできません。 int file_read(const char* pFileName){ struct LIST* p,*q,*mem; int ret=0; first.next=NULL; p=first.next; q=&first; while(p!=NULL){ q=p; p=p->next; } do{ // メモリ領域確保 mem=malloc(sizeof(struct LIST)); if(mem==NULL){ printf("異常終了(メモリ不足)\n"); return -1; // 異常終了 } >&p->name >間違いでは? 実行してみましたが & を付けても付けなくてもエラーでませんでした。

sakuranb22
質問者

お礼

こちらがグローバルです。 //********************定数定義 #define MAX 20 //********************構造体宣言 struct LIST{ // 線形リスト int no; // 社員番号 char name[MAX]; // 氏名 int age; // 年齢 int sex; // 性別 struct LIST* next; // 次の要素へのポインタ }; struct LIST first; // リストの先頭 &は外してました。すみません。 ファイルの方は、(_は半角スペースです) 123__あああああいいいい____20 といった羅列です。 メイン処理は、本関数がコールされるまではこんな感じです。 //********************メイン処理 int main() { int ret,i; char FileName[MAX]; // 入出力ファイル名 FILE *pFileName; // 入出力ファイルポインタ first.next=NULL; /***** 入出力ファイル名入力 *****/ printf("\n入出力ファイル名入力\n"); scanf("%s",&FileName); /***** 入力ファイルオープン *****/ if((pFileName=fopen(FileName,"r"))==NULL){ printf("異常終了(ファイルがありません)\n"); return -1; } /***** ファイルからリスト作成 *****/ ret=file_read((const char*)pFileName); if(ret==-1){ printf("異常終了(file_read)\n"); return -1; }

全文を見る
すると、全ての回答が全文表示されます。
回答No.2

>ファイルの扱い?がよくわかりません。 どういうように分からないかが分からないので答えようがありません。 >番号__氏名__年齢 この表示だと 番号や氏名は _ で区切るのですか? それとも質問用に入れているのですか? >&p->name 間違いでは? &p->name ⇒ p->name

全文を見る
すると、全ての回答が全文表示されます。
  • arain
  • ベストアンサー率27% (292/1049)
回答No.1

情報不足です。 最低でも、プログラムの最初からその行までは提示してください。

sakuranb22
質問者

補足

_は半角空白です。 これでいいですか? int file_read(const char* pFileName){ struct LIST* p,*q,*mem; int ret=0; first.next=NULL; p=first.next; q=&first; while(p!=NULL){ q=p; p=p->next; } do{ // メモリ領域確保 mem=malloc(sizeof(struct LIST)); if(mem==NULL){ printf("異常終了(メモリ不足)\n"); return -1; // 異常終了 } fscanf((FILE*)pFileName,"%3d %20s %2d\n",&p->no,p->name,&p->age);

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • Excelでバイト数の最大数が決まったデータを作りたいんです!

    上手く説明出来ないんですが・・。 エクセルで、項目それぞれにバイト数の最大数が決まったデータを作りたいんです。 例えば ◆職員番号・・・バイト数12(半角)         職員番号は8桁なので、その後ろに残り12バイトまでの半角パディング。 ◆氏名 ・・・ バイト数16(全角8字まで)         全角8文字以内なら、その後ろに残り8文字までの全角パディング。         全角8文字を超す氏名なら、8文字で切る。 ◆カナ ・・・ バイト数58(半角)         半角カナ文字で残りの58バイトまで半角パディング。 *これをcsvに変換します! これを文字列だけ打ち込んだら、自動で最大バイト数まで半角・全角を埋めるようにすることは出来るでしょうか? また、氏名のところのように自動で8文字までの入力しか出来なくするようにすることは出来るでしょうか? 説明が下手で申し訳ないんですが、おわかりになる方ご教授下さい。 よろしくお願いします!!

  • 全角半角を意識した文字分割

    A列           B列   C列  D列  E列     あいうえおかきくけこ  あ   いう  えお  か アイウエオカキクケコ    アイウ   エオ  カキ ク あイウえオかきくけこ    あ   イウえ  オか き 先ほど同じような質問を一度しているのですが、 A列に全角半角混在のテキスト項目があります。 B列、C列、D列、E列に以下のルールで分割したいのですが、 Excel関数で 実現可能でしょうか? 可能な場合は式をご教授して頂けますでしょうか。宜しくお願い致します。 ※全角をバイト数指定で分割して文字化けしないように全角半角を考慮して分割した いと考えております。 B列(半角3文字)  A列3桁目が半角の場合は半角3文字 A列3桁目全角の場合は半角2文字(全角1文字) C列 (半角4文字) A列4桁目が半角の場合は、左端4桁目~半4文字分 A列4桁目が全角の場合は、左端3桁目~半角4文字 D列(半角4文字) A列7桁目が半角の場合は、左端7桁目~半4文字分 A列7桁目が全角の場合は、左端6桁目~半角4文字 E列(半角2文字) A列11桁目が半角の場合は、左端11桁目~半2文字分 A列11桁目が全角の場合は、左端10桁目~半角2文字

  • [Ruby]外部ファイルの全角文字削除ができない原因を教えてください

    Rubyでの全角文字削除について質問です。 (環境:Windows XP,cygwin) コマンドライン引数で指定した外部ファイルを読み込んで全角文字を削除しようとすると、 全角文字が削除できないのですが、この原因がわかる方がいらしゃいましたら教えてください。 ・外部ファイル(Shift_JIS,改行=CR+LF) "7桁の| 郵便番号を| 入力して|,ください" ・Rubyスクリプト(cygwin上のため、EUC-JP,改行LF) #file.each_line do |line| # line.gsub!(/ /,'') # line.gsub!(/,/,'') # line.gsub!(/|/,'') #end 全角スペース、全角カンマ、全角パイプラインすべて削除できません。 半角文字は上記方法で削除できます。 しかし、スクリプト中に以下のような記述をすると、 #text = "7桁の 郵便番号を 入力して,ください" #print text.gsub(/ |,/,'') 「7桁の郵便番号を入力してください」と全角文字が削除されて表示されます。 教えてください。 よろしくお願いします。

  • CSVファイルの分析について

    CSVファイルで3MB程の容量のファイルが30個近くあります。 このファイルの分析をしないといけないのですが 手作業では無理があるため、マクロなり、関数なりで 対処できないものかと思いご相談させて頂きます。 分析の流れとしては CSVファイルをExcelで開き、特定の文字(3桁か4桁の数字)が 入っているセルを探し、どの数字が何回使われたかをカウントします。 数字は3桁もしくは4桁ですが、全角・半角は統一されていません。 全角のものもあれば、半角のものもあります。 1111が1回、222が4回といった感じです。 みなさんのお知恵をお貸しいただけないでしょうか。 よろしくお願いします。

  • 汎用のファイル読み取り関数について

    ファイルデータを読み取る関数を作成しています. Data *ReadFile (const char *name, Data *data, const char *format, ...) というプロトタイプを考えます. ここでDataはプログラマが自由に定義できる構造体です. この構造体の一例を示すと, typedef struct { int id; /* ID番号 */ char name[32]; /* 氏名 */ char sex; /* 性別 */ int age; /* 年齢 */ char addr[64]; /* 住所 */ } Data; という具合です. 読み取るファイルの書式はプログラムの種類によって 異なりますが, fopen関数やfclose関数を使用するといった 手順は全く同一です. そこで上記のような汎用的な ファイル読み取り関数を書こうと思ったのですが 読み取り部分fscanfの処理をどのように行えばよいか 分かりません. formatで指定する書式は'%'を区切りとする複数の文字列に 分け(例えばformat="%s %d"であればbuffer="%s \0%d\0"), char型のポインタ配列bpで参照できます. 可変引数の部分で 構造体のメンバを指定できるようにしたいのですが... ちなみに呼出側では Data *data; data = ReadFile ("a.txt", data, "%d %s %c %d %s", data->id, ...); というようにしたいと考えています. ソースを以下に示します. どなたかお力をお貸しくださいませ. Data *ReadFile (const char *name, Data *data, const char *format, ...){ FILE *stream; size_t data_size = 1024, buffer_size = 128, bp_size = 16; short i, j, k; char *buffer; char **bp; /* buffer pointer */ va_list ap; /* argument pointer */ (省略) va_start (ap, format); i = 0; k = 0; while (!feof (stream)) { fscanf (stream, bp[i], va_arg (ap, ????)); (省略) } va_end (ap); }

  • アクセス2010でのファイル保存方法

    アクセス2010で、UTF8形式のテキストを開き、レコードごとにデータを 抽出する際でのご質問がございます。 指定された県の郵便番号を、レコードを抽出して、ファイルで保存する際、テキスト型文字コードUTF8に指定して保存したのですが、レコード内のフィールド文字列でスペースを含んだ半角文字14桁と全角文字8桁の混合文字列が、保存後、前半部分の半角文字のスペースがなくなってしまいます。 下記のような例がイメージとなります。 例 ァァァ           亜亜亜亜亜亜亜亜    ↓   ァァァ 亜亜亜亜亜亜亜亜  (半角領域のスペースが1桁しかなくなってしまう) のようになってしまうのですが なにか良い保存方法はありますでしょうか? どうぞよろしくお願いします。

  • 数字をそろえたい

    ワープロで全角で9とうって半角で二桁10とか20とかうつときれいにふたけたも全角一文字としてにんしきできるのに、ワードで全角で9とうって半角で二桁を打つとどうもいがんでしまうのです。。。  どうすればワープロみたいにきれいにそろうのですか?

  • Javaプログラミングについて

    コマンドラインにキーボードで入力した文字をそれぞれの仕様に合わせて作るんですが文字の判別方法が分からなくて困ってます。 (1)半角英数字記号文字10桁(固定) (2)全角文字、半角禁止、250文字まで登録可能@必須 (3)全角文字、半角禁止、250文字まで登録可能@電話番号 (4)半角英数字記号文字ー必須。8桁 (5)全角、半角英数字記号文字混在可。500文字(半角換算)まで登録可能最後の全角文字で、501バイトにならないように注意 以上の5つが仕様です。どなたか教えて下さい。

  • Access Findfirst 半角全角空白

    Access2003のVBAでFindfirstを使用して、下記コードで番号&氏名データ検索をしています。 情報.FindFirst "[番号] ='" & 名簿![番号] & "' AND [氏名] ='" & 名簿![氏名] & "'" 「001」&「日本 太郎」(姓名間全角空白)が存在するか調べた所、 「001」&「日本 太郎」(姓名間半角空白)がヒットしました。 番号は一致してますが、氏名は姓名間の空白が半角、全角と異なるのにヒットしました。 Findfirstは文字列の全角半角空白の判別はしないのでしょうか? 判別するにはどうすればよいでしょうか? 教えてください。

  • EXCELで大文字から小文字へ変換したい

    EXCEL2000の住所録データを筆王の住所録へ変換しているのですが、うまくいきません。(-_-;)それは、郵便番号と電話番号が大文字(全角)になっていて、筆王の郵便番号の桁数でいくと半角で10桁となっています。EXCELのデータが大文字のため入りきれないのです。EXCELの大文字数字(全角)をどうにかして小文字数字(半角)にできないものか?データが多いもので、悩んでいます。どなたかお助けくださいませm(__)m

このQ&Aのポイント
  • EPSON社製品LP-S6160のトナー上部にある黒いフィルムが破れてしまった場合の対処方法について教えてください。
  • LP-S6160のトナー上部には黒いフィルムがあり、それが破れるとトナーの動作に問題が生じる可能性があります。破れたフィルムを修理する方法や代替品について知りたいです。
  • EPSON社製品のLP-S6160のトナー上部にある黒いフィルムが破れてしまった場合、フィルムを交換することが必要です。正しい交換方法や適切な代替品についてご教示いただけますか?
回答を見る