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

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

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

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

Q&A

解決済

1回答

6108閲覧

getlineをfgetsで書き換えたい

kmmtprgm

総合スコア8

C

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

0グッド

0クリップ

投稿2017/11/02 13:06

編集2017/11/02 13:11

###前提・実現したいこと
C言語を用いて、ファイル入力で読み込んだテキストに行番号を付けるプログラムをgetline関数を用いて作り、同じプログラムをfgetsで入力しても実行できるようにしたいのですが、上手くいきません

###発生している問題・エラーメッセージ
正しい実行結果は、

1 apple 2 banana 3 character 4 doctor 5 elephant 6 firefighter 7 giant 8 My_name_is_Tarou_Satou 9 Python

上記のような形なのですが、

1 apple 2 banana 3 charact 4 er 5 doctor 6 elephan 7 t 8 firefig 9 hter 10 giant 11 My_name 12 _is_Tar 13 ou_Sato 14 u 15 Python

このようになってしまいます。

###該当のソースコード
#【getlineで作ったソース】

#include<stdio.h> #include<stdlib.h> int main(){ FILE* fr = fopen("abc.txt","r"); //読み込みファイル if(fr==NULL){perror("ReadFileOpenError"); return 0;} FILE* fw = fopen("xyz.txt","w"); //書き出しファイル if(fw==NULL){perror("WriteFileOpenError"); return 0;} size_t sz = 16; char *str = (char*)malloc(sz); if (str == NULL) sz = 0; int i=1; while (getline(&str, &sz, fr) != -1){ fprintf(fw,"%6d %s",i,str); i++; } }

#【fgetsで作っているソース】

#include <stdio.h> #include <stdlib.h> int main() { FILE* fr = fopen("abc.txt","r"); //読み込みファイル if(fr==NULL){ perror("ReadFileOpen");return 0;} FILE* fw = fopen("def.txt","w"); //書き込みファイル if(fw==NULL){ perror("WriteFileOpen");return 0;} size_t sz = 16; //文字列のサイズ char* str = (char*)malloc(sizeof(char)*(sz+1)); //読み込み文字列格納用 if(str==NULL){ sz=0; } int line=1; //行番号 while(fgets(str,sizeof(str),fr) != NULL){ fprintf(stdout,"%6d ",line); fputs(str,stdout); line++; } free(str); fclose(fw); fclose(fr); }

《abc.txt》
apple
banana
character
doctor
elephant
firefighter
giant
My_name_is_Tarou_Satou
Python

よろしくお願いします

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

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

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

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

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

LouiS0616

2017/11/02 13:08

見やすいように工夫しているのは素晴らしいことですが、実は『コードブロック』を用いることが出来ます。編集画面を開き、コードを選択した状態で<code>ボタンを押してください。インデントや#なども正しく表示することが出来ます。
kmmtprgm

2017/11/02 13:12

ご指摘ありがとうございます。修正いたしました。
guest

回答1

0

ベストアンサー

次のように書き換えることで、私の環境では正常に動作しました。
追記:また、szの値を32に変更していました。simiteiさん、ありがとうございます。

C

1while(fgets(str, sz, fr) != NULL){ 2 fprintf(stdout, "%6d ", line); 3 fputs(str, stdout); 4 line++; 5}

fgetsは次のような引数を取ります。引用元

引数
s: ストリームから読み取った文字列を格納するための配列
n: 1 行の最大文字数
stream: ストリーム

strはこのときchar*型の変数ですから、sizeof(str)は同一環境では一定です。

kmmtprgmさんの環境では、sizeof(str)が8であるようです。
隠れているヌル文字を含め、8文字取得・表示できているようですから。


ついでなので、ちょっと気になった点を追記します。
プログラム内のwhile文は、for文に置き換えることで読みやすくなるかと思います。

C

1for(int line = 1; fgets(str, sz, fr) != NULL; line++){ 2 fprintf(stdout,"%6d ",line); 3 fputs(str, stdout); 4}

あと、ファイルを複数開く場合、ファイルポインタの解放はもうちょっと複雑になります。

C

1FILE* fr = fopen("abc.txt", "r"); 2if(fr == NULL){ 3 perror("ReadFileOpen"); 4 return 0; 5} 6 7FILE* fw = fopen("def.txt", "w"); 8if(fw == NULL){ 9 perror("WriteFileOpen"); 10 fclose(fr); 11 return 0; 12}

frのオープンは成功したが、fwのオープンに失敗した場合、frを解放せねばなりません。

投稿2017/11/02 13:31

編集2017/11/02 14:01
LouiS0616

総合スコア35660

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

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

shimitei

2017/11/02 13:57

size_t sz = 16;ではMy_name_is_Tarou_Satouの行を読むのに足りないため、もう少し大きい値を指定する必要があります。
LouiS0616

2017/11/02 13:59

あ、32に変更していたのを忘れていました。 simiteiさん、ご指摘ありがとうございます。
kmmtprgm

2017/11/02 14:03

16は指定のサイズなので、入力量に対して既定のサイズが小さければmallocを用いて領域を変える仕様にしました。お二人ともありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問