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

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

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

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

Q&A

解決済

5回答

1876閲覧

ファイルからの文字列の取得と分割(c言語)

shimi_py

総合スコア11

C

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

0グッド

1クリップ

投稿2019/01/14 02:59

c言語の学習をしている者です。
ファイル内の、区切り文字で区切られた3つのデータを読み込むプログラムを作りたいのです。
データの区切りは、区切り文字としての";" か、"改行"で区切られ、データは文字列です。(後に、atof()でdouble型に変更し、計算する予定。)
例)
aaa.txt

x=20; y=12 z=3

bbb.txt

y=12 x=20; z = 3

これらのファイルから、
x=20
y=12
z=3
という3つの文字列を取得したい。(任意のスペースあり)

ファイルからのデータ取得と、文字列操作を勉強中なのですが、行き詰ってしまいました。
特に、

  1. 改行コードを含めた1つの文字列として、ファイルから取得することはできるのか。
  2. それができない場合、どのようにすれば3つに分けられるのか。

教えていただけると幸いです。

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

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

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

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

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

guest

回答5

0

改行コードを含めた1つの文字列として、ファイルから取得することはできるのか。

fgets()関数で取得可能ですね。
fgets() — ストリングの読み取り

サンプル書こうかと思ったのですが、上記リンクが良く書かれているので、
見てください。

文字列の分割は、strtok関数を使えば、良いでしょうか。
こちらも strtok() — ストリングのトークン化
あるいは、 strtok_r() — ストリングのトークン化 (再開可能)
推奨は、strok_r() ("_r" 付き... 安全)

投稿2019/01/14 03:37

編集2019/01/14 03:44
pepperleaf

総合スコア6383

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

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

0

ベストアンサー

fscanf の書式を使って空白文字列の他に ; も無視するように設定するとラクだと思います!
(サンプルは scanf を使って標準入力→標準出力の流れにしておきます)

備考: 標準入力から安全に文字列を受け取る方法いろいろ - Qiita

c

1#include <stdio.h> 2 3int main(void) 4{ 5 // 255バイト+NULLバイトのスペースを確保 6 char buffer[256]; 7 8 // ・255バイト以内で区切り文字以外を連続するだけ読み取る 9 // ・255バイトを超えた部分や区切り文字自身は読み捨てる 10 // ・EOF (-1) が返されるまでの間は読み続ける 11 for (int r; (r = scanf("%255[^\r\n\t ;]%*[^\r\n\t ;]", buffer)) != EOF; scanf("%*c")) { 12 13 // 読み込めた場合のみ r=1 になっている 14 if (r > 0) { 15 puts(buffer); 16 } 17 } 18 19 return 0; 20}

【補足】

もし z = 3 のような式の間に半角スペースが入ってくる場合には strtok も絡めてもうひと工夫必要ですね。

c

1#include <stdio.h> 2#include <string.h> 3 4int main(void) 5{ 6 // 255バイト+NULLバイトのスペースを確保 7 char buffer[256]; 8 9 // ・255バイト以内で区切り文字以外を連続するだけ読み取る 10 // ・255バイトを超えた部分や区切り文字自身は読み捨てる 11 // ・EOF (-1) が返されるまでの間は読み続ける 12 for (int r; (r = scanf("%255[^\r\n;]%*[^\r\n;]", buffer)) != EOF; scanf("%*c")) { 13 14 // 読み込めた場合のみ r=1 になっている 15 if (r < 1) { 16 continue; 17 } 18 19 // 空行判定用変数 20 int skip = 1; 21 22 // 余分な文字を削ぎ落として出力 23 for (char *t = strtok(buffer, "\t "); t != NULL; t = strtok(NULL, "\t ")) { 24 skip = 0; 25 printf("%s", t); 26 } 27 28 // 空行ではなければ改行コードを出力 29 if (!skip) { 30 putchar('\n'); 31 } 32 } 33 34 return 0; 35}

投稿2019/01/14 04:01

編集2019/01/14 06:29
mpyw

総合スコア5223

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

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

mpyw

2019/01/14 06:14 編集

>> (後に、atof()でdouble型に変更し、計算する予定。) KEY=VALUE の形に落とし込んだあとは,sscanf で捌くのが最も簡単だと思います。オーバーフロー検知とかやりたかったらいったん VALUE を直接 double にせずに文字列のまま分割したあと strtod を使ったほうがいいですが…
shimi_py

2019/01/14 08:02

fscanfに変更し、正常に動作することを確認しました。丸投げな質問であったにもかかわらず丁寧に回答いただき、感謝しております。
mpyw

2019/01/14 08:04

最近C言語ほとんど書いてなくてブランクあったのでいい復習になりましたw
guest

0

getline なら POSIXなので多くの環境で使用できると思います。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4int 5main(void) 6{ 7 FILE *stream; 8 char *line = NULL; 9 size_t len = 0; 10 ssize_t read; 11 12 stream = fopen("/etc/motd", "r"); 13 if (stream == NULL) 14 exit(EXIT_FAILURE); 15 16 while ((read = getline(&line, &len, stream)) != -1) { 17 printf("Retrieved line of length %zu :\n", read); 18 printf("%s", line); 19 } 20 21 free(line); 22 fclose(stream); 23 exit(EXIT_SUCCESS); 24}

投稿2019/01/14 03:59

fu7mu4

総合スコア1088

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

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

0

... 改行コードを含めた1つの文字列として、ファイルから取得することはできるのか ...

できます。

参考情報

  • C言語関数:read

http://www.orchid.co.jp/computer/cschool/CREF/read.html

"c" ファイル 読み込み
などで google 検索してファイルの内容全体を読み込む方法を調査してみてください。

追記
ファイル内容をすべて読み込み, その内容を表示、さらに 改行や ; で区切り、SPAECE は無視するようなものを書いてみました。
質問文にある aaa.txt が処理だけるだけのものです。エラー処理や改行コードの OS ごとの差、 SPACE 文字の扱い などは調節をすることが必要です。
sss.c

c

1#include <stdio.h> 2#include <string.h> 3 4 int main(void) { 5 FILE * fp; 6 char buff[100+1]; 7 int rc; 8 9 fp = fopen("aaa.txt", "r"); 10 if (fp == NULL) { 11 printf("ファイルオープンエラー\n"); 12 return -1; 13 } 14 15 rc = fread(buff, 1, 100, fp); 16 if (rc == -1) { 17 printf("ファイル読み込みエラー\n"); 18 } 19 fclose(fp); 20 21 buff[rc] = '\0'; 22 printf("%s\n", buff); 23 24 char exps[10][20]; 25 int exp_num = 0; 26 exps[0][0] = '\0'; 27 char * exp_p = exps[0]; 28 29 for (char * p = buff; *p; p++) { 30 char c = *p; 31 if (c == '\n' || c == ';') { 32 *exp_p = '\0'; 33 if (strlen(exps[exp_num]) > 0) { 34 exp_num++; 35 } 36 exp_p = exps[exp_num]; 37 *exp_p = '\0'; 38 } else if (c != ' ') { 39 *exp_p++ = c; 40 } 41 } 42 43 for (int i = 0; i < exp_num; i++) { 44 printf("%d\t[%s]\n", i, exps[i]); 45 } 46 return 0; 47}

実行例
イメージ説明

投稿2019/01/14 03:42

編集2019/01/14 07:41
katoy

総合スコア22324

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

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

shimi_py

2019/01/14 07:37

有用なサイトの提供感謝します。
katoy

2019/01/14 07:43

質問文に書いたサイトはあんまり良いコードが記載されていませんでした。 fread の説明ページにあるコードをベースに、質問文の動作をするものを書いてみました。
shimi_py

2019/01/14 08:04

上記サイトからfreadに飛ぶことができ、大変参考になりました。追記のコード、ありがとうございます。コードを読み取り、実践してみます。
guest

0

Cなど不要。そう、シェル芸ならね!

bash

1$ cat aaa.txt bbb.txt|tr -d ' '|grep -oE '[a-z]+=[0-9.]+'|sort -u 2x=20 3y=12 4z=3

投稿2019/01/14 03:23

hichon

総合スコア5737

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

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

shimi_py

2019/01/14 07:39

うぎゃあ。すごい。 しかしcの勉強なので、、、泣
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問