• 締切済み

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

ファイルのデータを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 プログラムの訂正箇所,上記と異なるプログラム,大体の流れ… などなんでもかまいませんので、教えていただきたいです。よろしくお願いします。

みんなの回答

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

その目的のためだけだったら「C言語は使わず、PerlとかPythonとかRubyとかPHPとか..を使う」 C言語で作りなさい、という宿題なら、ポインタと配列と文字列のところを重点的に勉強しなおす。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

どうしてほとんど同じ質問が出るんだろうね.

参考URL:
http://okwave.jp/qa/q8277830.html

関連する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 プログラムの訂正箇所,上記と異なるプログラム,大体の流れ… などなんでもかまいませんので、教えていただきたいです。よろしくお願いします。

  • ユニコード文字列の分割

    csvやファイルパスをカンマや'\'で分割する関数をユニコードでも 対応できるように改修していのですがやり方が分かりません。 関数のロジックはおおよそ以下の通りです。 (仕事先のセキュリティの関係でソースは持ち出せませんので概要ですが・・・) split(str, item, len, words[item][len], delimiter) char* str: 分割対象の文字列 int item:項目数(上限あり) int len:項目の文字数(上限あり) words[item][len]:文字列を分割、項目として格納する配列 char delimiter:区切り文字 int i=0, j=0; while(*str != NULL){ // 文字列を分割する処理 if(str != delimiter){ words[i][j++] = *str } else if{ words[i][j] = NULL i++; j=0; } ・・・・・・・・・ str++; } // 後処理があります VCの設定がマルチバイト対応だったので問題なかったのですが ユニコードに設定を切り替えるとパスの分割でカタカナの「ソ」 を含む文字列が正しく分割されないという事象が発生しました。 関数内の改修だけで解決する方法があるでしょうか? ある程度プロジェクトが動いているのであまり時間をかけないで 対応する必要があります。 OS: Windows7 SP1 環境: VC++ 2008 MFC

  • データの区切り?

    こんにちわ。前回質問に御答え頂いて誠に有難う御座います。 さて、今回の質問なんですが、文字列の分割の方法が分からなくて困っています。 以下プログラムです。 //////////////////////////////////////// /*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】と書き出すにはどのようにしたら良いでしょうか? 説明が分かり難く申し訳御座いませんが宜しくお願いします。 タイトルも分かり難く申し訳ないです・・

  • 文字列の動的確保とポインタ配列について

    C言語についての質問です。 現在、キーボードから文字列を読み込みファイルに保存するプログラムを作成しています。 プログラムの条件は、以下の通りです。 1: キーボードから英数字(最長でMAX_LEN(1000)-1文字)を入力して文字列(文字配列)dataに格納後、画面に表示する。 2: 入力された文字列と同じ長さの文字列を格納する領域を動的に確保し、文字列dataをその領域に コピーする。なお、必要な文字配列の長さは文字列の長さ+1バイトである。 3: 文字列endが入力されるか、入力された文字列がNUM_STRING(10)個になるまで1~2の処理を繰り返す 4: 各文字列へのポインタを格納する(char *)型ポインタの配列str_p(サイズ:NUM_STRING)を定義して利用する。 5:1~2の処理が終了した後で、メモリに格納されたすべての文字列をファイルに出力する。ファイル名はoutput.txtとし、最初の行に文字列の個数を、次の行以降に入力された順番と「逆の順番」で文字 列を出力すること。 実行例 input ->st22 st22 input->st1 st1 end ファイルの中身 2 st1 st22 現在完成しているプログラムは以下の通りです。 #include<stdio.h> #include<string.h> #include <stdilb.h> #define NUM_STRING 10 #define MAX_LEN 1000 int main (void) { int n, i; char data[MAX_LEN] = {}; char *str_p[NUM_STRING]; FILE *fp; do { printf("input->"); scanf("%s", data); if (strcmp(data, "end") == 0) { break; } else { printf("%s\n", data); n++ 2の処理 } while(n <= NUM_STRING); if ((fp = fopen("output.txt", "w")) == NULL) { fprintf(stdout, "File open error\n"); } fprintf(fp, "%d\n", n); for (i = n-1; i>0; i--) fprintf(fp, "5s\n", str_p[i]); fclose (fp); return 0; } 特に動的確保のところがよく分かりません。 回答よろしくお願いします。       

  • ファイル操作のプログラムについて

    下記のsample1.txtの1列目とsample2.txtの1列目の文字列が一致する行をつなげて出力するプログラムを組みたいと思い、test.cを書きましたが、うまく動きませんでした。これは何が原因なのでしょうか。 回答よろしくお願いします。 -------------------sample1.txt-------------------- J02220-2222 3.999 null J03424-2222 900.0 0.43 J03666-2223 30.0 0.23 J04000-4422 98.0 0.43 -------------------sample2.txt-------------------- J03424-2222 900.0 0.43 J03342-4423 4.000 0.99 J02220-2222 3.999 null -------------------test.c--------------------------- #include<stdio.h> int main(void) { FILE *fp ,*gp; int ret; char xl[30],nx1[30],xb[30]; char xls[30],nx2[30],xlb[30]; fp=fopen("sample1.txt","r"); gp=fopen("sample2.txt","r"); while(fscanf (fp,"%s%s%s",xl,nx1,xb)==3){  while(fscanf (gp,"%s%s%s",xls,nx2,xlb)==3){  ret=strcmp(xl,xls);  if(ret == 0){  printf("%s\t%s\t%s\t%s\t%s\t%s\n",xl,nx1,xb,xls,nx2,xlb);    }  }  } fclose(fp); return 0; } インデントが反映されいなかったらすいません。 ------------出力結果------------------- J02220-2222 3.999 null J02220-2222 3.999 null -----------望む出力結果-------------- J02220-2222 3.999 null J02220-2222 3.999 null J03424-2222 900.0 0.43 J03424-2222 900.0 0.43

  • C# 文字列の分割

    VS2005を使用しているものです。 複数のURL(入力)を格納したString型の配列があるのですが、 この配列から各要素(URL)の最後尾にあるファイル名だけを 取り出して別のString型の配列に入れたいのですが Splitなどを駆使すればよいのでしょうか? 例 C:\○○○\▲▲▲\××.拡張子 (元の配列の要素の一例)   などから××.拡張子の文字列だけを取り出して   別の配列に格納する感じです。 splitを使う際は\などを区切りに考えています。 for文の中でsplitを駆使しようと考えたのですが、分割した文字列を別で配列に格納して、その最後尾の要素だけ取り出したいのですが、URLの長さは入力によってまちまちなのでどのようにして取り出せばよいか困っています。 勉強不足で恐れ入りますが、何かご教授願えれば幸いです。

  • C言語 文字列格納

    テキストファイルから整数データ又は文字列を読み込んで配列に格納する動作についての質問です。 テキストファイルが1行区切りの整数型なら1次元配列で for(i = 0; i < maxSize; i++) { fscanf(fp,"%d", &data[i]); } テキストファイルが1行区切りの文字列なら2次元配列で for(i = 0; i < MAXSIZE; i++) { if (fscanf(fp,"%s", &data[i][300]) == EOF) break; } for(j = 0; j < i; j++) printf("%s\n", data[j]); みたいな具合に格納できたんですが、 テキストファイルが1行区切りのデータではなく、空白文字区切りの文字データだった場合、それぞれどのようにして配列に格納すればいいかがわかりません。 イメージとしては、1文字目から見ていって空白が出ればそこで切って格納していくというかんじなのですが・・・ 質問の内容がわかりにくいかもしれませんが、是非教えてください。お願いします。

  • 空欄を含む文字列のテキスト

    C言語についての質問です。宜しくお願いします。 以下の書式で表されたテキストファイルを読み込む場合を考えます。 1 2   配列nは要素数が1個,配列mは要素数が2個であることを表します。 9    そして,nの要素は9,mの要素は5と8です。 5    つまり n[0] = 9, n[1] = {5,8} といった具合に格納したいのです。 8    nの要素数i個,mの要素数j個について行いたいのですが,どうすればいいでしょうか。 プログラムはscanf等で入力待ちの状態で,データはテキストファイルからリダイレクトします。

  • 文字列の操作

    こんにちは。 以下のような、文字列があるとします。 NUMBER1(ヌル\0)からNUMBER1000(ヌル\0)までの文字列があるとします。 NUMBERは付属で、ほしい文字列が1から1000までNUMBERの次にある場合、1から1000までを取得する方法として、 Buf[100] int x=0; while(Buf[x]!='\0') //ナル文字までの長さを取得 x++; memmove(&Buf[0],Buf[x-1],4); //NUMBER1の場合、長さは7。しかしほしい文字列は第6要素なのでx-1。 しかし・・・これを行うと、 NUMBER10:長さ8 NUMBER100:長さ9 ・ ・ となり、二桁以上の場合は、memmove(&Buf[0],Buf[x-2],4)と、 第2引数を手動で可変しなければなりません。 そこで、NUMBER\01\0 NUMBER\01000\0というように、 NUMBERの次にヌル文字(あってますでしょうか?)\0を挿入し、次の要素に1から1000まで文字列を挿入。そして文字列終端が分かるように再度\0を挿入します。 しかしこのような場合、ヌルを2つ挿入することで、上記に示したプログラムでは、手前の\0までしか長さを取得しないので、うまくいきません。 そこで、文字列の区切りを示すための方法として、なにかありますでしょうか? 文字列は最後に、\0を挿入することで判別すると書いてありますが、 NUMBERVISUALC++\0というような文字列を配列に格納してある場合、 NUMBERとVISUALC++をどのように分けて取得するのでしょうか? それとも、第6要素から取得した文字列があると言う事が分かっている場合、第6要素からを指定するプログラムを作るということになるのでしょうか? よろしくお願いします。

  • 文字列の探索

    ファイル名を指定して文字列の探索を行うというプログラムをC言語で作成したのですが、 コンパイルのときに警告で「問題のあるポインタの変換(関数 main )」と出て、うまい具合に動きません。改良点を教えてください。 #include<stdio.h> #include<string.h> #include<stdlib.h> unsigned char *s1; unsigned char *s2; unsigned char *cp; FILE *fp; char fname[64]; void TestStrStr(void); main(){ s1 = calloc(256, sizeof(unsigned char)); s2 = calloc(256, sizeof(unsigned char)); printf("Input Filename..."); scanf("%s",fname); while(1){ fp = fopen(fname, "r"); if(fp == NULL){ printf("ファイルを開くことができません...\n"); printf("Input Filename..."); scanf("%s",fname); }else break; } s1=fp; // printf("文字列1を入力してください:"); // scanf("%s",s1); printf("文字列2を入力してください:"); scanf("%s",s2); TestStrStr(); return 0; } void TestStrStr(void){ cp = strstr(s1, s2); if(cp == NULL) printf("'%s'に'%s'のいずれの文字も含まれない.\n", s1, s2); else printf("'%s'の中に現れる'%s'という文字列は%d文字目にある.\n", s1, s2, cp - s1 + 1); free(s1); free(s2); }

専門家に質問してみよう