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

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

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

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

Q&A

解決済

5回答

2799閲覧

c言語でファイルから一文字ずつ読み込んでchar配列に代入したい

K.M.PEANUTS

総合スコア40

C

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

0グッド

0クリップ

投稿2021/07/13 01:19

編集2021/07/13 01:54

c

1char name[50]; 2 3while(1) 4 while(1) { 5 c = fgetc(sfp); 6 if('A' <= c && c <= 'Z') c += 32; 7 if('a' > c || c > 'z') break; 8 name[i] = c; 9 i++; 10 } 11 if(c == EOF) break; 12 name[i] = '\n'; 13 tinsert(root, name); 14 15 i = 0; 16 }

上のコードで、sfpから一文字読み込み、その文字が大文字なら小文字に変換後name[i]に代入したいのですが、実行するとうまくいかずname[i] = cのところで例外が発生しました。と出てきます。なにが原因で、どのように変更すれば良いのでしょうか?
やりたいことは、英語で書かれたファイルから1単語ずつ読み込んで単語数を数えようとしてます。

"追記"
tinsertはname[50]に入れた単語を2分木に格納する関数です。

試したこと

c

1 int i; 2 char name[5] = "abcde"; 3 char a[5]; 4 for(i=0; i<5; i++) { 5 a[i] = name[i]; 6 } 7 for(i=0; i<5; i++) { 8 printf("%c", a[i]); 9 } 10 puts(" "); 11 printf("%s\n", a);

実行結果
abcde
abcdeabcde

試したことは、同じようなコードを書いて文字配列に一文字ずつ代入できるか確認してみました。しかし、char a[5]を%sで一文字ずつ表示すると何故かabcdeが2回表示されました。ここら辺の理由がわかっていません。

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

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

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

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

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

rubato6809

2021/07/13 02:45 編集

上のコードはプログラムの一部しかアップされていません。 プログラムの全体をアップしてください。
guest

回答5

0

配列のインデックス(i)が無限に増え続けるパターンが存在する時点であまりよろしくないプログラムです。
まずは、配列の長さを超える時点でループを抜けるように条件設定するのが前提です。
そのうえで、もし想定している終了条件(ここではif('a' > c || c > 'z') break;)で引っかからない理由を、デバッガなりprintfなりで確認してください。

投稿2021/07/13 03:00

tain

総合スコア241

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

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

0

ベストアンサー

変数 i を0に初期化しないまま、つまり不定値のまま while ループを始めたのでは。
int i;int i = 0; に修正する。

投稿2021/07/13 01:49

編集2021/07/13 01:54
rubato6809

総合スコア1380

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

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

K.M.PEANUTS

2021/07/13 04:11

その通りでした。つまらないミス気をつけます。
guest

0

一文字づつ読み込むんじゃなくて、
まとめて読み込んで、そのあとで変換していくようにしましょう

投稿2021/07/13 01:40

y_waiwai

総合スコア87800

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

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

K.M.PEANUTS

2021/07/13 01:50

もう少し詳しく聞かせてほしいです。 name[50]という配列に1単語を読み込みたいのですが、どこまでをまとめて読み込み、1単語を判断してname[50]に代入するのでしょうか?
y_waiwai

2021/07/13 01:51

そのバッファのサイズ、50バイト読み込めばいいんです。 あとの変換や1単語の判定は、その後にすればいいです 今みたいに全部一緒くたでしようとするから、わけわからんようになるんです。
guest

0

name[i] = cのところで例外が発生しました。

51文字以上読み込んだのでしょう。
なお、ちょうど51文字目で例外が発生するとは限りません。

if('a' > c && c > 'z')

'a'より小さくて'z'より大きい文字は存在しないので、この条件は常に偽ですが、この行の意図は何でしょう?

%sで一文字ずつ表示すると

%sは「1文字ずつ表示」では無いです。「NUL文字が出てくるまで連続して表示」です。
質問のコードではNUL文字を使ってないので、%sは使えません。
無理矢理使ったので、たまたまNUL文字が入っていたところまで表示しています。

投稿2021/07/13 01:39

編集2021/07/13 01:40
otn

総合スコア84804

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

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

K.M.PEANUTS

2021/07/13 01:44

> 'a'より小さくて'z'より大きい文字は存在しないので、この条件は常に偽ですが、この行の意図は何でしょう? 自分も今そのミスに気づき、修正しました。が、いまだに同じエラー内容が表示されています。。
guest

0

name[i] = cのところで例外が発生しました。と出てきます。なにが原因で、どのように変更すれば良いのでしょうか?

nameの定義が書かれていないので、なんとも言えません。

しかし、char a[5]を%sで一文字ずつ表示すると何故かabcdeが2回表示されました。

末端のヌル文字が入っていないため、配列の領域を超えて読み込み続けてしまいます。"abcde"の文字列を格納するには、最後のヌル文字を入れて6バイトの領域が必要です。

投稿2021/07/13 01:23

maisumakun

総合スコア145208

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

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

K.M.PEANUTS

2021/07/13 01:28

char name[50]です。 %sは文字列の先頭アドレスを受け取ってヌル文字の前までを表示するのでしたね???? 後半については理解できました。
maisumakun

2021/07/13 01:29

・iは初期化していますか? ・50文字を超えて処理しようとしていませんか?
K.M.PEANUTS

2021/07/13 01:47

『if('a' > c && c > 'z') break;』これを満たす文字が存在しないため、無限ループになっており、iが初期化される段階まで行っていませんでしたので修正しました。これでiは初期化されています。 しかし同じ内容のエラーが出続けているので原因は他にもあるようです。。
maisumakun

2021/07/13 01:51

> これでiは初期化されています。 提示されたコードにはiの宣言すら見当たらないです。
K.M.PEANUTS

2021/07/13 01:55

編集させていただきました????‍♂️
maisumakun

2021/07/13 01:56

宣言はどこですか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問