読み込んだ文字列 s[40] から実数値の文字列を切り出し,個別の文字配列に保存する操作がしたいです.
ファイルから1行分の文字列を読み込み,3つの実数値(文字列)を切り出し,文字配列にコピーする,という操作なのですが,例えば,
0.2¥t0.0¥t1.0¥0
という文字配列があったとして
最初の文字を切り出すのに
char s[40], ts[15]; /*file1から一行読み込んだ文字列 s[40],これからコピーする文字配列ts[15]*/
int i, j;
...
fgets(s, 39, file1);
i = 0;
for(j = 0; s[i] != '\t'; j++, i++){
ts[j] = s[i];
}/*1つ目のタブ文字に出会うまで s[] の文字を ts[]にコピーする*/
ts[j] = /*切り出した文字列の最後にヌル文字を代入*/
printf("%s\n", ts); /*0.2が画面表示される*/
というようなプログラムがかけるかと思います.
しかし,2つ目と3つ目の実数値を取り出す際,どのように書けるかがわかりません.
(初期値 i の値を変えるのかな,という想像はしているのですが...)
どのように表せばいいか教えていただけたら幸いです.
わかりづらい箇所があったら申し訳ないです.
よろしくお願いします.
No.4ベストアンサー
- 回答日時:
No.1です。
えっと。。。
file1をfgetしたらforループに入り、その中ですぐfile1をfgetする意味は何でしょう???
そして更にforループが3つも作らねばならない理由は何でしょう?
まずはいきなりソースコードを書くのではなく、日本語の箇条書きやチャート図などを使って処理手順を日本語で書き表してみましょう。
そしてそれをじっくり読み直し、「この通り処理すれば目的のことが出来る」と確認出来たらその通りにコーディングしてみましょう。
なお、その箇条書きやチャート図にはソースコードレベルの詳細さは求めません。例えば、「変数〇〇を定義する」とか「〇〇用のカウンター変数××をインクリメントする」とかいった詳細なことは不要です。
「〇〇ファイルから1レコード読み込む」とか「読み込んだレコードの先頭から最後まで1もじずつ以下の処理を行う」といった感じで、どういう順番で、何を、そう処理するか、がハッキリわかるようにまとめます。
参考まで。
なるほど...今まで直接コードを書き始めていました.
このコードに関しても一度紙に書いてからやり直そうと思います.
ありがとうございます!
No.6
- 回答日時:
No.5です。
> 今までわからないものはブログなどを見て書いていたので,もう一度やり直してみようと思います.
何を目的にどういった方法でプログラミング言語を学ばれておられるのかわかりませんが、「どういう入力を受けてどういう出力をおこなうのか」をしっかり定め、それを行うには「何をどう処理すればそれを行うことができるのか」という処理アルゴリズムを考えることがソフトウェアを作る際に最も大切な事です。いわゆる設計ですね。
ソースコードを書いて、コンパイルリンクをして、代表的な正常データを与えると正しい結果が得られるというデバッグまでが製造です。
その後には各種の正常ケースに加え、異常データや異常ケースを含めてソースコードに表した全てのロジックを通すための試験の項目を設計し、そのためのデータを用意して試験を行います。
で。大きなソフトウェアになると設計も試験も複数フェーズにわかれ各段階ごとにやるべきことが決まっている・・・という形になります。
参考まで。
なるほど...
今まではC言語が必修の授業で,課題をただこなすだけだったのですが,
これから学校の実験や,将来的には仕事などでもプログラミングを使うことになると思うので,どのように処理すればよいか,きちんと考えようと思います.
何回も回答していただき本当にありがとうございます.
No.5
- 回答日時:
No.1です。
追加です。
答えは一つではありません。
処理手順は一つではないということです。
ただ、他の方法と比較して明らかに手順が多かったり、複雑であったりする方法はNGです。
ちなみに勤めていた会社の研修担当として受講者のソースコードを読んだ経験がありますが、いろいろ読むと「この人はあの人の物を写した(or教えてもらった)な」とか「この人のがオリジナルで他の人はそれをまねた(or教えてもらった)な」といったことはすぐにわかります。(^^;
変数名を変えたりメッセージを変えたりしても。。。
ということで自分自身でしっかり考えて「私はこうだ」という処理手順を作れるようになりましょう。独創的である必要は全くありませんから。
そうなのですね...
今までわからないものはブログなどを見て書いていたので,もう一度やり直してみようと思います.
いろいろと教えてくださって本当にありがとうございます.
No.3
- 回答日時:
うーむ・・・。
これって宿題なのかしらん。
いや、もし、実用的にこういうプログラムが書きたい、ってのならC言語じゃない方が良いでしょう。と言うか、恐らく「やりたいこと」をマトモにやるとしたら、100人中96人くらいはC言語の使用を避けるんじゃないかなぁ。
ぶっちゃけ、C言語には文字列がありません。文字列が無い言語で文字列操作をしようとするのに土台無理があります(笑)。文字列を操作する為には「素のC言語」から何個ものレイヤーを重ねてる、ってのが「実用性」で言うと現実です。
例えばC言語が生まれたUNIXでも、素のCでテキストファイルの中の文字列を操作するのを避けさせる為に、sedやらawk等のスクリプト言語が生まれました(ある意味Perlの遠い祖先です)。それくらい文字列操作を直接Cでやるのはクッソメンド臭いのです。間違いなく死にます(謎
いや、何かCで上手いことやれるライブラリ無いのかしらん、って探してみたんですが、見つからなかったんですよね。Windowsを使ってるんだろうし、強力なデータ構造がてんこ盛りのGLibとか、一応調べてみたんですが、多分この辺使うのは難しいでしょうねぇ。
さて、と。取り敢えず前提から。
まずはコピー先の文字配列ts[15]の問題から行きましょう。まずこれが実は問題に合いません。
どういう事かと言うと、他のスクリプト言語、と言われる言語での実行例をお見せします。
# Python での例
>>> s = "0.2\t0.0\t1.0"
>>> s.split("\t")
['0.2', '0.0', '1.0']
>>>
;; Scheme での例
#;1> (import srfi-13) ;; 文字列ライブラリを使用
; loading /var/lib//chicken/11/srfi-13.import.so ...
; loading /var/lib//chicken/11/chicken.fixnum.import.so ...
; loading /var/lib//chicken/11/chicken.platform.import.so ...
; loading /var/lib//chicken/11/srfi-14.import.so ...
Note: re-importing already imported identifier: string->list
Note: re-importing already imported identifier: string-copy
Note: re-importing already imported identifier: string-fill!
#;39> (define s "0.2\t0.0\t1.0")
#;70> (string-tokenize s)
("0.2" "0.0" "1.0")
さて、実は元々、問題としては、これは
> 実数値の文字列を切り出し
と言っていましたが、実は実数値の文字列もクソも関係ないんです。そうじゃなくって、逆に「(タブ等の)区切り文字部分で文字列を分割せよ」と言うのが主題です。こういう作業を「トークンに分ける作業」、すなわち「トーカナイズ」等と呼んだりします。主役は実は「区切り文字(タブの他に例えばスペース、コンマ、ピリオド等を利用する)」の方なんですね。
んで、上で利用したスクリプト言語なんてのは、見て分かる通り、このトーカナイズをやすやすとやってのける機能を持ってるんですが、結果を見て下さい。両者とも文字列を要素に持つリスト(C言語で言う配列みたいなモノ)を返しています。
つまり、このテの機能をC言語でやる場合、「文字配列の配列」を返した方が適する、と言う事が予想出来ます。
と言う事は、最初に挙げた質問で考えると、
ts[15]
ではダメで、
ts[3][5]
にせなアカン、と言う事です。二次元配列ですね。それを使わないといけません。
さて、もう一つは、一応、C言語の標準ライブラリにトーカナイズが出来るライブラリが(貧弱ながらも)含まれています。それはstring.hと言うヘッダなんですが、詳しくはこちらの方を参考にしてください。
C言語関数辞典 string.h:
http://www.c-tipsref.com/reference/string.html
このサイトはCの標準ライブラリを調べる際にはかなり重宝します。なんか分からん時はここで調べましょう。
この内の次の2つの関数を使用します。
strtok(文字列を区切り文字で分割する): http://www.c-tipsref.com/reference/string/strtok …
strcpy(文字列をコピーする): http://www.c-tipsref.com/reference/string/strcpy …
この2つを利用して書くと以下のようになりますね。
#include <string.h>
int main(void)
{
char s[40] = "0.2\t0.0\t1.0\0";
char ts[3][5];
char* temp;
int i = 1;
temp = strtok(s, "\t");
strcpy(ts[0], temp);
while (temp != NULL) {
temp = strtok(NULL, "\t");
if (temp != NULL) {
strcpy(ts[i], temp);
}
i++;
}
return 0;
}
特に出力は噛ましてませんが、「何のファイルを読むのか」具体例もありませんし、改造する為のベースならこれで充分じゃないか、と思います。出力自体も書き足すには苦労しないでしょうしね。
まぁでも、くれぐれも「素のC言語」で、文字列操作の為の実用プログラムを書こう、なんて思わないでください(笑)。世の中にはもっと便利なツールがあるのでそっちを利用しましょう(笑)。
ご回答ありがとうございます.
学校の課題になっております.
他の言語のほうが使い勝手が良いのですね...
もうすぐ夏休みなので自分で勉強しようと思います.
いろいろ例を書いていただき,ありがとうございました!
No.1
- 回答日時:
> しかし,2つ目と3つ目の実数値を取り出す際,どのように書けるかがわかりません.
1つ目のTABを検出したところでforループを抜けるので、その後ろにiで位置付いているTAB文字の次の字から同じようにチェックを続ければよい・・・とは考えませんか?
そう考えると「そもそもTAB文字を検出したところでループ処理を抜けてよいのか?」とはなりませんか?
つまり「入力された文字列の最初から最後までをチェックしTAB文字は読み飛ばして・・・」という処理にすればよさそう・・・とか考えませんか?
そういった部分がアルゴリズムを考えることかと。
小学校ではじまったプログラミング学習に狙うところですね。
参考まで。
ご回答ありがとうございます.
補足のほうで画像を貼らせていただいたのですが,こんな解釈でいいのでしょうか.
お返事いただけたら幸いです.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・【お題】絵本のタイトル
- ・【大喜利】世界最古のコンビニについて知ってる事を教えてください【投稿~10/10(木)】
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・ハマっている「お菓子」を教えて!
- ・最近、いつ泣きましたか?
- ・夏が終わったと感じる瞬間って、どんな時?
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
[Excel VBA]デフォルトプロパティ
-
プログラムによく出てくるst...
-
Shift_JIS(16進)を文字に変換す...
-
nullと""、\\0とEOFの違いにつ...
-
TCL言語で文字列検索方法を教え...
-
C++で入力した文字列から数字を...
-
VB6.0でのバイナリデータの扱い...
-
16進数を2文字ずつ配列に格納し...
-
WSH(VBS)でJSONの文字列を読み...
-
C#でstringをポインタとして渡す
-
引用符と二重引用符
-
関数から配列を返すには?
-
C言語 配列の長さの上限
-
C# 配列の変数宣言について。
-
配列を使わずに、変数名を動的...
-
セグメントエラー
-
配列の要素数に変数を入れたい...
-
define で 配列
-
Run-Time Check Failure #3とい...
-
C言語 配列の再初期化
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C#でstringをポインタとして渡す
-
プログラムによく出てくるst...
-
nullと""、\\0とEOFの違いにつ...
-
シリアル通信で0x00を送信した...
-
%dなどの違い
-
TCL言語で文字列検索方法を教え...
-
WSH(VBS)でJSONの文字列を読み...
-
_tcscpy_s(wcscpy_s)の第二引数...
-
C++で入力した文字列から数字を...
-
VB6.0でのバイナリデータの扱い...
-
16進数を2文字ずつ配列に格納し...
-
VBA-DLLの引数受け渡しについて
-
数字の入った配列をファイルへ...
-
引用符と二重引用符
-
C言語の勉強しています。すみま...
-
c#で他のアプリの文字入力フォ...
-
構造体→文字列→構造体 をする方法
-
バイナリファイル中の日本語文...
-
Excelシートを固定長のテキスト...
-
[C++]WCHARの1文字目しか表示で...
おすすめ情報
こういうことでしょうか?
見づらかったら申し訳ないです.