• ベストアンサー

データの区切り?

こんにちわ。前回質問に御答え頂いて誠に有難う御座います。 さて、今回の質問なんですが、文字列の分割の方法が分からなくて困っています。 以下プログラムです。 //////////////////////////////////////// /*make_date.cpp*/ #include <stdio.h> #include <string.h> #define MAX_LEN 1000 #define MAX_LEN2 1000 #define BUFFER_SIZE 200 int main() { int i, len, cnt = 0; char *cp2; //「カテゴリー」「更新日」「職種」「登録日」 const char *delim2 = ":"; //改行用単語1 const char *delim3 = "@D"; //改行用単語2 const char *delim4 = "@P"; //改行用単語3 const char *delim5 = "@A"; //改行用単語4 const char *delim6 = "@Q"; //改行用単語5 const char *delim7 = "@W"; //改行用単語6 const char *delim8 = "@Z"; //改行用単語7 const char *delim9 = "@C"; //改行用単語8 const char *delim10 = "@T"; //改行用単語9 char buffer[BUFFER_SIZE]; char aiu[100]; char *wordss[MAX_LEN2]; FILE *fp,*pf; //ファイルポインタ //---------------------------------------------------- //各項目を選ぶ処理(カテゴリ) if((fp=fopen("data.dat","r")) == NULL ){ printf( "datファイルが存在しません。\n" ); } wordss[0] = fgets( aiu, 256,fp ); cp2 = wordss[0]; //そして、保存の為、取得したデータを「entry.bk」に入れ込む。 pf=fopen("entry.txt","w"); //区切り処理1 wordss[0] = strtok(cp2, delim9); //文字列に代入されている状態を確認 printf( "\n\n%s", wordss[0] ); //書き込み処理 fputs(wordss[0],pf); cp2 = NULL; //ファイル・クローズ fclose(pf); //ファイル・クローズ fclose(fp); return 0; } //////////////////////////////////////// /*data.dat*/ 20080714@TSE@C20080816@Z公開20090201@WSE@Q20090205@Aテスト20090206@PSE@D20090206:会議 //////////////////////////////////////// 現在このようなプログラムがあります。 「ddata.dat」の中にある文字列の【20080714】だけを取り出し、 「entry.txt」へ書き出します。(「delim10」を使用し「@T」があったら、改行します。) 次に【SE】だけを取り出し、 「se.txt」へ書き出す処理を作成中なんですが、 試しに【SE】を書き出すのかチェックするため「delim9」を使用し、試してみましたが、書き出されるのが【20080714】になってしまいます。 これを【20080714】【SE】【20080816】と書き出すにはどのようにしたら良いでしょうか? 説明が分かり難く申し訳御座いませんが宜しくお願いします。 タイトルも分かり難く申し訳ないです・・

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

  • ベストアンサー
  • arain
  • ベストアンサー率27% (292/1049)
回答No.4

No1.です。 とりあえず他の気になるところも。 >wordss[0] = fgets( aiu, 256,fp ); >cp2 = wordss[0]; 読み込み時の問題はNo.3氏のとおり。 で、 cp2 = fgets( aiu, 256,fp ); とやらない理由は? >pf=fopen("entry.txt","w"); にエラー処理がないのは? >char *wordss[MAX_LEN2]; は「char *wordss[1000];」となるわけだが、ポインタが1000個もいる理由は?

akianaray
質問者

お礼

色々見てみたところ、問題解決まで近づいてきましたので もう少し調べて作成してみます。 何度もご回答有難う御座います。

akianaray
質問者

補足

返信有難う御座います。 そして遅れてすみません。 >cp2 = fgets( aiu, 256,fp ); これはcp2がちゃんとデータを取得してるかをチェックする為にしたためです、確かに「cp2 = fgets( aiu, 256,fp );」にすれば 「printf( "%s", cp2);」と書けば内容は分かりますね・・ >pf=fopen("entry.txt","w"); え~と、すいません・・エラー処理というのは? これも"r"みたいに書き込みされたかどうかをチェックする処理が必要なんでしょうか? >「char *wordss[1000];」となるわけだが、ポインタが1000個もいる理由は? 始めは10にしていたんですが、エラーが表示されてしまう状態になってしまい、数を増やしたら消えたので・・ 少なすぎたのでしょうか・・ 今現在はファイルを別々に作成するプログラムを作成中です。 【20080714】を作成するプログラム、【SE】を作成するプログラム【20080816】を作成するプログラム・・・ ただ、これも今後数が増えた場合・・その度にファイルを作るプログラムを作成しなければなりません・・・

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

その他の回答 (4)

  • S117
  • ベストアンサー率40% (18/45)
回答No.5

いろいろ突っ込みたいところがたくさんありますが、ほかの回答者が言及してるのでおいておきます。 コードの先頭で、 /*make_date.cpp*/ とありますが、見る限りではCのコードだと思います。微妙な仕様の違いで混乱することがありますのでどっちかはっきりさせた方がいいでしょう。 なお、もしもC++なのであればC++のライブラリの方が使いやすいと思います。以下はCという前提です。 細かいところはともかく最初の部分を取得できていますので、2番目がとれない原因はstrtokの使い方を間違えているのだと思います。一度、使用している処理系のリファレンスでstrtokの使い方を確認した方がいいでしょう。リファレンスを見てもわからないようでしたら、新しく質問するなりしてみてください。また提示されたソースの範囲内でもstrtokに対して使い方を誤解していると思われる部分があります。

akianaray
質問者

お礼

strtok関数の使い方を理解して、作成して見たところ、 問題解決まで近づきました。 もう少しがんばって作成してみます。 ご回答有難う御座いました。

akianaray
質問者

補足

返信有難う御座います。 すいません、遅れてしまいまして・・ >見る限りではCのコードだと思います はい、Cで書いてます。ファイルを保存時に自動的にcppになります。 >2番目がとれない原因はstrtokの使い方を間違えているのだと思います。 どうやらそのようです・・なので、strtok関数について調べてみます。

全文を見る
すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

>これを【20080714】【SE】【20080816】と書き出すにはどのようにしたら良いでしょうか? 20080816 をどこに書込むかの説明がありません。 >タイトルも分かり難く申し訳ないです・・ そういう自覚があるのでしたら、人にわかりやすく伝えるには どうすればよいかをもっと考えるべきでありましょう。 ところで、本題とは関係ないかもしれませんが、 >char aiu[100]; >wordss[0] = fgets( aiu, 256,fp ); aiuのサイズとfgetsで読込むサイズとが食い違っていてもよいのでしょうか?

akianaray
質問者

お礼

問題解決に近づいて来たので、これでやってみます。 ご回答有難う御座います。

akianaray
質問者

補足

返信遅れて申し訳御座いません・・ >20080816 をどこに書込むかの説明がありません。 「update.txt」というファイルを作成し、そのファイルに書き込みます。 >そういう自覚があるのでしたら、人にわかりやすく伝えるには~ そうですね、質問者が分かり難いなんて書いてはいけませんね・・・ >aiuのサイズとfgetsで読込むサイズとが食い違~ よく見てませんでした・・・変更し忘れていました・・ 正式には256に合わせてます。 現在では各項目を一つ、一つファイルを作成し、 【20080714】は【20080714】だけを作るという風にプログラムを作成する事にしました・・ ただ、ファイルは増える事があるので、新しい項目が出来る度にプログラムを作成するのは・・宜しくないと思ってます、

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

どのようなコードを使って試しているのかが全く分かりません. 「うまくいかない」場合のコード全体を示してください. 実は strtok の仕様でそうなっているかもしれんし.

akianaray
質問者

お礼

strtok関数を調べてたら問題解決まで近づいて来ました。 何とかなりそうです。 ご回答有難う御座いました。

akianaray
質問者

補足

返信有難う御座います。 そして、遅れて申し訳御座いません・・ >どのようなコードを使って試しているのか こちらです↓ /*サンプルプログラム*/ #include <stdio.h> #include <string.h> #define MAX_LEN 100 int main() { int i, len; char str[] = "This is a test", *words[MAX_LEN], *cp; const char *delim = " "; cp = str; for (len = 0; len < MAX_LEN; len++) { if ((words[len] = strtok(cp, delim)) == NULL) break; cp = NULL; } for (i=0; i<len; i++) { puts(words[i]); } return 0; } /*サンプルプログラム*/ >実は strtok の仕様でそうなっているかもしれんし どうやらstrtok関数の使い方をよく理解してないようです・・ それが原因なのかもしれません。調べて見ます。

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

環境にによっては、ispunct()で区切り文字に該当するコードはチェックできなかったはず。 @はispunct()に引っ掛かるコード。 他にも[]{}なんかはダメなはず。

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

関連するQ&A

  • C言語・ファイルと文字列の操作プログラムについて!

    ファイルのデータを1行ずつ読み込み、","で区切られた要素に分割して配列に格納するプログラムの作り方を教えてください。 下記のようなファイルがあり、各行の3つめの要素の数字(ハイフンを含む)を各行で比較し、昇順に行をソートするというプログラムを作成しております。 要素数は4つめ以降各行ばらばらです。 [ファイル test.txt] 2013/08/01,16:19,20130801161906-210164001071,,,川口,神奈川,,電話番号 2013/08/01,11:32,20130802003256-116091178056,鈴木,埼玉,mail,電話番号 2013/08/01,15:55,20130801155519-119072194140,,,山田,東京,mail まず、ファイルを読み込み、3つめの要素を下記のように配列s[i]に格納しようとしたのですが、うまく配列に3つめの要素がはいってくれません。 strtokを用いたプログラムを作っているのですが、1行ずつ分割と表示はできるものの、それを配列に格納することができなくて困っております。 配列の格納にstrcpyを用いたところ、途中でプログラムが強制終了し、配列への格納ができませんでした。 [格納の例] s[0]=20130801161906-210164001071 s[1]=20130802003256-116091178056 s[2]=20130801155519-119072194140 [自分のプログラム] #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 300 int main() { char filename[] = "test.txt"; FILE *fp; char data[MAX], *words[MAX],*s[MAX],*cp; const char *delim=","; int g,i=0,j,len; // ファイル・オープン if ((fp = fopen(filename, "r")) == NULL) { printf("ファイルのオープンに失敗\n"); exit(1); } while (fgets(data, MAX, fp) != NULL) //1行読み込む { cp = data; for (len = 0; len < MAX; len++) { if ((words[len] = strtok(cp, delim)) == NULL) //","で文字列を分割 break; cp = NULL; } s[i] = words[2]; //3つ目の要素を配列に格納 i++; } for(j=0;j<3;j++){ //表示 printf("%s\n",s[j]); } [実行結果] 20130801155519-119072194140 20130801155519-119072194140 20130801155519-119072194140 プログラムの訂正箇所,上記と異なるプログラム,大体の流れ… などなんでもかまいませんので、教えていただきたいです。よろしくお願いします。

  • 文字列操作(分割)のプログラムについて!

    ファイルのデータを1行ずつ読み込み、","で区切られた要素に分割して配列に格納するプログラムの作り方を教えてください。 下記のようなファイルがあり、各行の3つめの要素の数字(ハイフンを含む)を各行で比較し、昇順に行をソートするというプログラムを作成しております。 要素数は4つめ以降各行ばらばらです。 [ファイル test.txt] 2013/08/01,16:19,20130801161906-210164001071,,,川口,神奈川,,電話番号 2013/08/01,11:32,20130802003256-116091178056,鈴木,埼玉,mail,電話番号 2013/08/01,15:55,20130801155519-119072194140,,,山田,東京,mail まず、ファイルを読み込み、3つめの要素を下記のように配列s[i]に格納しようとしたのですが、うまく配列に3つめの要素がはいってくれません。 配列の格納にstrcpyを用いたところ、途中でプログラムが強制終了し、配列への格納ができませんでした。 この原因と対策がわからなくて困っております。 [格納の例] s[0]=20130801161906-210164001071 s[1]=20130802003256-116091178056 s[2]=20130801155519-119072194140 [自分のプログラム] #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 300 int main() { char filename[] = "test.txt"; FILE *fp; char data[MAX], *words[MAX],*s[MAX],*cp; const char *delim=","; int g,i=0,j,len; // ファイル・オープン if ((fp = fopen(filename, "r")) == NULL) { printf("ファイルのオープンに失敗\n"); exit(1); } while (fgets(data, MAX, fp) != NULL) //1行読み込む { cp = data; for (len = 0; len < MAX; len++) { if ((words[len] = strtok(cp, delim)) == NULL) //","で文字列を分割 break; cp = NULL; } s[i] = words[2]; //3つ目の要素を配列に格納 i++; } for(j=0;j<3;j++){ //表示 printf("%s\n",s[j]); } [実行結果] 20130801155519-119072194140 20130801155519-119072194140 20130801155519-119072194140 プログラムの訂正箇所,上記と異なるプログラム,大体の流れ… などなんでもかまいませんので、教えていただきたいです。よろしくお願いします。

  • c言語プログラミング実行時エラーについて質問です。

    c言語プログラミングを実行しようとすると、 エラーが出て次のようなメッセージが出てしまいました。 「「7行目」で記述エラーを発見しました。「constant expression」を付け忘れています。」 どなたか原因を教えてください。よろしくお願いいたします。 以下が失敗したプログラムです。 #include <stdio.h> int main(int argc, const char * argv[]) { const char FILENAME[] = "/Users/user/Desktop/date3.txt"; const int LEN = 100; char line [LEN]; char name [LEN]; char birth [LEN]; char address [LEN]; FILE *dat; dat = fopen(FILENAME, "r"); if ( dat == NULL ) { printf(" ファイル %s がオープンできません. ", FILENAME); return -1; } while( fgets( line, LEN, dat) != NULL ) { sscanf( line "%s, %s, %s", name ,birth, address ); printf("name = %s, address = %s\n", name, address ); } fclose(dat); return 0; }

  • C言語のシェルプログラミングの課題が分かりません。

    C言語のシェルプログラミングを作れという課題で、以下のように作ったんですが、実行して何度かコマンドを入力した後、exitによって一発で終わらせることができません。どのように書き換えればいいか教えて下さい。 また、他にも書き換えた方がよいと思えるところがあったら是非教えて下さいm(_ _)m #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/wait.h> #include <sys/types.h> #include MAX_ARGS 10 #include MAX_LEN 100 extern char **environ; void child(int argc, char *argv[MAX_ARGS]); int main(void){ int argc, n = 0; int status; char input[MAX_LEN], *argv[MAX_ARGS], *cp; const char *delim = "\t\n"; while (1){ ++n; printf("$ "); fflush(stdout); if(fgets(input, sizeof(input), stdin) == NULL){ break; } cp = input; for(argc = 0; argc < MAX_ARGS; argc++){ if((argv[argc] = strtok(cp, delim)) == NULL) break; cp = NULL; } if(strcmp(argv[0], "exit") == 0){ exit(0); } pid_t pid = fork(); if(pid == -1){ perror("fork"); exit(1); }else if(pid == 0){ child(argc, argv); }else{ wait(&status); } } return 0; } void child(int argc, char *argv[MAX_ARGS]{ execvp(argv[0], argv); }

  • ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込

    ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込みプログラム」をそのままコンパイルして実行しようと思ったのですが、 sample.c: In function 'main': sample2.c:9: warning: return type of 'main' is not 'int' と、表示されてしまいます。 プログラミング初心者なので、どこが間違っているのかわかりません。 回答またはアドバイスの程、よろしくお願いいたします。 ネットで落ちていたプログラムを以下に記載します。 sample2.c #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("コマンドの入力形式が間違っています.\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("ファイルがオープンできません[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("データが不正です[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("エラー(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("エラー(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("エラー(3)\n"); break; } if(*wp != '\0'){ printf("エラー(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); }

  • c言語についての質問です

    あるdatファイルに時間と振幅のデータが入っているんですが振幅のデータのみを2乗してから2乗したものに1/2乗し正のものだけから振幅の最大値を求め、振幅の最大値の2割に達した時間を出力したいのですが、どのようにすればよいか分かりません。 サンプルプログラムを載せますのでおねがいします。 ちなみにdatファイルには 時間 振幅 時間 振幅 … となっています。 #include <stdio.h> int main(void) { const char * fname = "C2.dat"; char line[BUFSIZ]; double amp, time,arrival, max=0,max20; FILE *fp = fopen(fname, "r"); while (fgets(line, BUFSIZ, fp)) { sscanf(line, "%lf%lf", &time, &amp); if (amp > max) { max = amp; } } fclose(fp); printf("max: %.7lf\n", max); fp =fopen(fname,"r"); while (fgets(line, BUFSIZ, fp)){ sscanf(line, "%lf%lf" , &time, &amp); if(amp > max*0.2){ arrival = time; break; } } fclose(fp); printf("arrival:%.16lf\n",arrival); return 0; }

  • c言語についての質問です

    c言語についての質問です。あるdatファイルに振幅と時間のデータが保存されています。 このdatファイルを読み込み振幅の最大値を求めてから振幅の2割の値を求めます。 そこから再度読み込み振幅の2割を超える時間まで読み込み越えた際の時間を出力したいのですが上手くいきません。途中がけのプログラムをのせるのでお願いします。 datファイルには 時間 振幅 時間 振幅 … のようになっています。 #include <stdio.h> #include <math.h> int main(void) { const char * fname = "C1rbc1(50,0)sq,almi00001.dat"; char line[BUFSIZ]; double amp, time,arrival, max=0,max20; FILE *fp = fopen(fname, "r"); while (fgets(line, BUFSIZ, fp)) { sscanf(line, "%lf%lf", &time, &amp); if (amp > max) { max = amp; max20=max*0.2; } } fclose(fp); printf("max: %.7lf\n", max); printf("0,2*max:%.7lf\n",max20); int main(void) { FILE *fp =fopen(fname,"r"); while (fgets(line, BUFSIZ, fp)){ sscanf(line,"%lf%lf",&time,&amp); if(amp>max20){ arrival=time; break; } } fclose(fp); printf("arrival:%.7lf\n",arrival); return 0; } }

  • C言語 strtok

    失礼します。現在こちらでアドバイスを頂きfgetcを使用して配列に格納をすることができたのですが、CSVをカンマ区切りで格納したいのですが上手くいかず困っています。strtokを使用方法をドキュメントを読んでもうまく区切ったものを配列に入れる方法がわかりません 何卒よろしくお願いします。 ソースコード #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include<string.h> #define MAXITEM 1400 int split(char *str, const char *delim, char *outlist[]) { char *tk; int cnt = 0; tk = strtok(str, delim); while (tk != NULL && cnt < MAXITEM) { outlist[cnt++] = tk; tk = strtok(NULL, delim); } return cnt; } int main(void) { FILE *fp; char *fname = "testfile.csv"; char *tp; char *array[1400]; char *test[11][1400]; char c; int i = 0; int n,y; char *tp[1400]; fp = fopen(fname, "r"); if (fp == NULL) { printf("%sファイルが開けません¥n", fname); return -1; } while ((c = fgetc(fp)) != EOF) { array[i] = (char)c; i++; } tp = strtok(array, ","); puts(*tp); while (tp != NULL) { tp = strtok(NULL, ","); if (tp != NULL)puts(tp); } for (n = 0; n < 11; n++) { for (y = 0; y < 1400; y++) { test[n][y] = tp[y]; printf("%c", test[n][y]); } } fclose(fp); return 0; }

  • ボイヤームーア法について

    課題が分からなくて困っています。課題の内容は「ボイヤームーア法を用いてファイルの先頭からテキストを1行ずつ(1行の文字数は999文字以下とする)読み込み、何行目の何文字目に探索文字列の先頭が存在するか出力するプログラムを作成せよ。探索文字列中に同じ文字が含まれる場合については探索方法を改良せよ」というものです。1行の文字列を探索するプログラムは作れたのですが、複数の行を読み込んで何行目の何文字目かを出力させる方法がどうしてもわかりません。無知な私ですがどうかよろしくお願いします。締め切りは明日なのでなるべく早くお願いします。 #include<stdio.h> #include<string.h> #define MAX1 1000 #define MAX2 256 int bm(char txt[MAX1], char pat[MAX2]) { int a,b,len1,len2,skip[MAX2+1]; len1=strlen(txt); len2=strlen(pat); for(a=0;a<=MAX2;a++){ skip[a]=len2; } for(a=0;a<len2-1;a++){ skip[pat[a]] = len2-a-1; } while(a<len1){  b=len2-1;   while(txt[a]==pat[b]){    if(b==0){ return(a);    }    b--;    a--;   }   a+=skip[txt[a]]; } return(-1); } int main(void) { int x; char filename[MAX2],ex[MAX1],strg[MAX2]; FILE *fp; printf("Input filename:"); scanf("%s",filename); getchar(); fp=fopen(filename,"r"); if(fp == NULL){ printf("read open error!\n"); return(-1); } printf("Input search string:"); scanf("%s",strg); getchar(); for(i=0;i<MAX1;i++){    if(feof(fp)){   break;  } fgets(ex[i],MAXCHR1,fp); } x=bm(ex,strg); if(x==-1){  printf("There is not pattern in the text"); } else{  printf("%s%d\n",strg,x+1); } fclose(fp); return 0; }

  • ワードのデータ

    FILE *fopen( const char *filename, const char *mode ); を使って、 FILE *fp = fopen("あああ.doc", "rb" ); --- c = fgetc(fp); ----- ---- として、エクセルのファイルデータを メモリーに移そうとしたら、 5文字文くらい読んで、 すぐに終了してしまいます。 1.原因は何でしょうか?   ワードデータの特性でしょうか? 2.他の方法でファイルサイズをはかり   EOF にかかわらず、そのサイズ分だけ読み込めば   データをメモリーに移せるのでしょうか?  よろしくお願いいたします。