文字列入れ替えのプログラムとは?

このQ&Aのポイント
  • 文字列入れ替えのプログラムを作成するための質問です。
  • 具体的なアルゴリズムの一部について分からない点があります。
  • どうやって文字列の一部を切り出し、別の位置に並べ替えるかが分からず困っているようです。
回答を見る
  • ベストアンサー

文字列入れ替えのプログラムについて

こんばんは。 文字列入れ替えのプログラムを作っているのですが、分からない部分があるので教えて頂きたいです。 入力ファイルには、 AAAAAAA(必ず7文字)【半角スペース】B(文字数はバラバラ)【tab】C(文字数はバラバラ) というデータが複数入っているものとします。 このファイルを読み込んで、 B【tab】C;;;(セミコロン3つ)AAAAAAA という順に並べ替えるプログラムを作成したいと考えています。 アルゴリズムとしては、 (1)ファイルから1行読み込む (2)読み込んだ行のうち最初の7文字を配列に保存 (3)半角スペースを除き、それ以降(B【tab】C)を出力ファイルに書き込む (4)(2)で保存したものに;;;をつけ、(3)の後ろに書き込む というのを考えていますが、(3)の工程をどうすればいいか分からず困っています。 (改行(\n)までをファイルに書き込めばいいと思うのですが、プログラムでどう書けばいいかが分かりません) よろしくお願いします。 #include<stdio.h> void main(void){ FILE *fin; FILE *fout; char buff[200]; char *p1; char word[200]; int i=0; /*読み込み用ファイルを開く*/ fin = fopen("input.txt", "rt"); if( fin == NULL ){ printf( "File open error1\n" ); return; } /*書き込み用ファイルを開く*/ fout = fopen("output.txt", "wt"); if( fout == NULL ){ printf( "File open error2\n" ); return; } /*1行ずつ読み込む*/ /*読み込める間繰り返す*/ while(fgets(buff,200,fin) != NULL){ i=0; /* buffの先頭アドレスをp1に与える*/ p1=buff; /*工程2:最初から7文字分を配列wordに保存*/ for (i=0;i<7;i++){ word[i]=*p1; *p1++; } /*半角スペース部分をとばし、p1をBの最初の文字にする*/ *p1++;      ここで工程3を行う     /*工程4:保存しておいた文字列を書き込む*/ fprintf(fout,";;;%s\n",word); } fclose(fin); fclose(fout); }

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

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

> 改行(\n)までをファイルに書き込めばいいと思うのですが、プログラムでどう書けばいいかが分かりません その通りに書けばいいだけでは? > /*半角スペース部分をとばし、p1をBの最初の文字にする*/ > *p1++; /* ここでの * p1 ++ の * は不要というか無意味というか */ で、 p1はBの先頭に来ているわけですから p1の指す先が改行になるまで繰り返す {  p1の指す先を1文字出力  p1 ++ } でOKです。 ○元プログラムでの注意点 ・wordへ7文字コピーしていますが、終端文字('\0')を入れている様子がありません。 wordの状態によっては、正しく動作するように見えることもありますが、大抵は何かの問題が発生します。 症状が軽ければ文字化けで済みますが、最悪はシステム破壊まで有り得ます。 ・1行が、改行込みで「半角英数」199文字までなら問題ありませんが、それ以上の長い行があるようなら、扱いに注意が必要です。 ○別解1 >  ここで工程3を行う の時点で、 p1 は、「B\tC\n」という文字列の先頭アドレス、と解釈もできます。 あらかじめbuffの改行コードを'\0'にしておけば、p1 は「B\tC」という文字列の先頭アドレスということになります。 そうすれば fprintf(fout,"%s;;;%s\n",p1,word); で済みます。 ○別解2 C言語での文字列操作は、正直面倒です。 この内容なら ・UNIX系OS標準のsedコマンド (Windows移植版もある) ・Perl,Ruby,Python等のテキスト処理が得意な言語 ・「正規表現による置換」機能を持つ、ある程度高級なテキストエディタ 等で簡単にできます。

sou-e9
質問者

お礼

回答ありがとうございます。 私の作っていたプログラムでは色々問題があったようですね・・・。 strtokを用いて同じ内容のプログラムは作れたのですが、自分で作っていた方のプログラムでもできるように直しておきたいと思います。

その他の回答 (3)

回答No.3

#include <stdio.h> #include <string.h> int main() { char* line = "ABCDEFG B_string_B\tC_string_C\n"; char* token; for ( token = strtok(line," \t\n"); token != NULL; token = strtok(NULL, " \t\n") ) { printf("[%s] ", token); } return 0; }

sou-e9
質問者

お礼

ありがとうございます。 無事プログラムを作ることができました。 やはりstrtokを使う方がかなり楽にできますね・・・。

  • notnot
  • ベストアンサー率47% (4846/10257)
回答No.2

>word[1] = strtok(NULL,'\n'); strtokのデリミタは文字列なので、 word[1] = strtok(NULL,"\n"); です。

sou-e9
質問者

お礼

ありがとうございます。 無事にプログラムができました。

回答No.1

strtokでA,B,Cを抽出すればいぃんじゃなくて?

sou-e9
質問者

補足

回答ありがとうございます。 strtokを用いて、 word[0] = strtok(buff," "); word[1] = strtok(NULL,'\n'); のように、半角スペースがきたら区切り(AAAAAAAの部分) 改行がきたら区切る(B【tab】Cの部分) とすればいいかと思いやってみたのですが、改行コードの部分でエラーになりました。(\nがcharでないからだと思います) この部分はどう指定してやればいいでしょうか?

関連するQ&A

  • 文字列変換のプログラムについて

    こんにちは。 C言語で以下のようなプログラムを作りたいと考えているのですが、うまく実装できず困っています。 入力ファイルには、【単語(ひらがな)+Tab+その読み(音素列)】が書かれているとします。 例: あいうえお(Tab)a i u e o かきくけこ(Tab)ka ki ku ke ko ・・・ (音素は半角空白で分けられているものとします) このファイルを読み込んで、【単語(ひらがな)+Tab+単語(カタカナ)+Tab+その読み(音素列)】を別のファイルに書き込む  例: あいうえお(Tab)アイウエオ(Tab)a i u e o かきくけこ(Tab)カキクケコ(Tab)ka ki ku ke ko ・・・ というプログラムを作りたいと考えています。 アルゴリズムとして、 (1) ファイルから1行読み込む (2) Tab文字がくるまでの文字列を配列に保存(例でいう「あいうえお」の部分です) (3) Tab文字の次の文字から行末までの文字列を配列に保存(例でいう「a i u e o」の部分です) (4) (2)の1文字ずつをカタカナに変換(ASCIIコードの変換で可能?) (5) (2)(3)(4)を用いて出力用ファイルに書きこむ という流れを考えたのですが、(2)の部分でまず手こずっています。 #include<stdio.h> main(){ FILE *fin; FILE *fout; char buff[200]; char word[200]; int i=0; /*読み込み用ファイルを開く*/ fin = fopen("input.txt", "r"); if( fin == NULL ){ printf( "File open error\n" ); return; } /*書き込み用ファイルを開く*/ fout = fopen("output.txt", "w"); if( fout == NULL ){ printf( "File open error\n" ); return; } /*1行ずつ読み込む*/ /*読み込める間繰り返す*/ while(fgets(buff,200,fin) != NULL){ /*タブ文字がくるまで拾う*/ while(buff[i] != '\t'){ /*文字列を配列wordに保存*/ word[i] = buff[i]; i++; } /*保存できているかの確認*/ printf("%s",word); fclose(fin); fclose(fout); } 実行後、wordの中身が表示されるのですが、 あいうえお,(文字化け)(文字化け) というように、【,(文字化け)(文字化け)】という謎の文字がついてしまいます。 また、入力ファイルの中身が2行以上でも、 あいうえお,(文字化け)(文字化け) あいうえお,(文字化け)(文字化け)・・・ というように、1行目の結果しか出てこないです。 どこを直せばいいのでしょうか? (というかそもそもCよりPerlとかで作ったほうがもっと楽なのかもしれないですが・・・) 教えて頂けると助かります。よろしくお願いします。

  • ファイルの入出力を行っての文字列反転

    入力した文字列を反転させて出力したいのですが どうしたらよいでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> /* 定数 */ #define DELIMITER "/ ," /* 区切り文字 */ int main(void) { FILE *fin,*fout; char infile[40],outfile[40],s[256],s2[256]; char *token; char *strch[50]; int count = 0; int i; printf("入力ファイル名="); gets(infile); printf("出力ファイル名="); gets(outfile); if( (fin=fopen(infile,"r"))==NULL) { /* 入力ファイルオープン */ printf("入力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } if( (fout=fopen(outfile,"w"))==NULL) { /* 出力ファイルオープン */ printf("出力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } while(fgets(s,256,fin)!=NULL) { /* 入力ファイルから読み込んだデータを */ token = strtok(s, DELIMITER); while (token != NULL) { strch[count] = token; token = strtok(NULL, DELIMITER); count++; } for(i = count; i > 0; i--) { strcat(s2, strch[i]); } fputs(s2,fout); /* 出力ファイルに書き込み */ } fclose(fin); /* 入力ファイルクローズ */ fclose(fout); /* 出力ファイルクローズ */ return 0; }

  • ファイルの英字を全部小文字に変換して新規テキストに出力

    テキストファイルの英字を全部小文字に変換して新規テキストに出力するプログラムをつくりましたがうまくいきません。なにがいけないですか? #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define STR_MAX 256 int main(void) { FILE *fi, *fo; /* ファイルポインタ用 */ char fin[100], fout[100]; /* ファイル名用 */ char buff[STR_MAX], *q; /* 文字列用 */ printf("入力ファイル名 : "); /* プロンプト表示 */ gets(fin); /* ファイル名入力 */ printf("出力ファイル名 : "); /* プロンプト表示 */ gets(fout); /* ファイル名入力 */ q = buff;   /* 入力ファイルオープン */ if((fi = fopen(fin, "r")) == NULL){ printf("入力ファイルがオープンできません\n"); exit(1); /* 強制終了 */ }   /* 出力ファイルオープン */ if((fo = fopen(fout, "w")) == NULL){ printf("出力ファイルがオープンできません\n"); exit(1); /* 強制終了 */ } while(fgets(buff, STR_MAX, fi) != NULL){ /* 1行読み込み */ *q = tolower(*q); ++q; fprintf(fo, "%s", buff); /* 1行出力 */ } fclose(fi); /* 入力ファイルクローズ */ fclose(fo); /* 出力ファイルクローズ */ return(0); }

  • ファイルの入出力を行って文字を変換する

    入力するファイルにa~zを記入しておき、 出力するファイルにaなら1、bなら2、zなら26に変換させたいのですがどうしたらよいでしょうか? #include <stdio.h> #include <string.h> #define DELIMITER "/ ," /* 区切り文字 */ int main(void) { FILE *fin,*fout; int count=0; int i; char s[256], s2[256]; char alpha[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; int kazu[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26}; char *taken; char *strch[50]; if( (fin=fopen("file1.txt","r"))==NULL) { printf("入力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } if( (fout=fopen("file2.txt","w"))==NULL) { printf("出力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } while(fgets(s,256,fin)!=NULL) { while (token != NULL) { strch[count]=token; token = strtok(NULL, DELIMITER); count++; } memset(s2, NULL, sizeof(s2)); fprintf(fout,"%d\n",s2); } fclose(fin); fclose(fout); return 0; }

  • ファイル入出力で

    現在ファイル入出力の項目をしているのですが、以下の内容で実行すると エラーが出てどうしても実行できません。主にどこを直せばいいのでしょうか? /* ファイルをコピーするプログラム */ #include <stdio.h> int main(void) { FILE *fin, *fout; char infile[40], outfile[40]; char str[256]; printf("コピー元ファイル = "); scanf("%39s", infile); printf("コピー先ファイル = "); scanf("%39s", outfile); if( (fin = fopen(infile, "r") ) == NULL) { printf("Input file open error.\n"); return 1; } if( (fout = fopen(outfile, "w") ) == NULL) { printf("Output file open error.\n"); fclose(fin); return 1; } while(fgets(str, sizeof(str), fin) != NULL) { fputs(str, fout); } fclose(fin); fclose(fout); return 0; } エラーは FILE 、fin, fout,NULLの未定義です。 よろしくお願いします。

  • 文章中から特定の文字列を抜き出すプログラムについて C言語

    log.txtの文章からIPを抜き出しip.txtに書き込むというものです。log.txtの文章は基本的にfrom IP:port の順です。しかし文章中にfromがないとip.txtで空欄になってしまいます。 例192.168.1.100  192.168.1.110 理想はfromがない行はなにも追加せず次に移りたいのですがどうすればいいでしょうか? 例192.168.1.120 192.168.1.130 192.168.1.140 void addLine(const char*,FILE*); char *getFromIP(const char*,char*); int main() { FILE *pFileA = fopen("log.txt","rt"); char buff[256]; if(pFileA){ FILE *pFileB = fopen("ip.txt","wt"); if(pFileB){ for(;fgets(buff,256,pFileA) != NULL;){ char buff2[32] = {'\0'}; addLine(getFromIP(buff,buff2),pFileB); } fclose(pFileB); } fclose(pFileA); } return 0; } char *getFromIP(const char *line, char *buff) {  char *src, *dst;        src = strstr(line, "from");  if(src==NULL) { return buff; }   src += 4;            dst = buff;          while(1) {   if(isspace(*src))  {    src++;    continue;          }   else break;         }                    while(1) {   *dst = *src;          if(*dst == ':')        {    *dst = '\0';          break;           }   if(*dst == '\0')       {   break;           }  dst++;            src++;           }  return buff;         } void addLine(const char *str,FILE *pFile){ char buff[1024]; sprintf(buff,"%s\n",str); fputs(buff,pFile); }

  • 文字列の比較について

    99としか書いてないファイルxxx.txtが有り、以下のようにして読み込みました。 char aaa[256]; if((fin=fopen("c:\\xxx.txt","r"))==NULL){ AfxMessageBox("読み込みファイルオープン出来ません"); return TRUE; } while((fgets(aaa,256,fin))!=NULL){ } fclose(fin); そしてstrcmpで比較したところ、1が返り等しくないと判定されます。 strcmp(aaa,"99") どうすれば等しいと判定できるようになりますか?

  • 修正箇所の指摘のお願い(文字列の書き出し)

    C++についての質問です。 あるテキストファイルを読み込み、行頭の空白文字(スペース)を 削除して、別のテキストファイルへ書き出すプログラムを 作成しています。 下記のようにコーディングを行いましたが、 読み込みファイルの1行目が書き出されず、最終行が2回 書き出される状態となってしまいました。 お手数ですが、修正箇所を教えて頂けないでしょうか。 ************************************************************ #include <iostream> #include <string> #include <fstream> using namespace std; #define INPUT_FILE "C:\\input.txt" #define OUTPUT_FILE "C:\\output.txt" int main() { ifstream fin(INPUT_FILE); ofstream fout(OUTPUT_FILE); char str[255]; if(!fin) { cout << "入力ファイルを開けません\n"; return 1; } if(!fout) { cout << "出力ファイルを作成できません\n"; return 1; } fin.getline(str,254); while(!fin.eof()) { std::cin.setf( std::ios::skipws ); // スペースの読み飛ばし fin >> str; fout << str << std::endl; } fin.close(); fout.close(); return 0; } ************************************************************ よろしくお願いします。

  • ファイル中のデータの読むとき・・・・

    こんにちは。ファイルにあるテキストデータを用意してそれを読み込んでいって、処理をするというプログラム書いてるんですけど、たとえば 大まかな構造として、 int fncCheck(char*pch,char item) { int count=0; int i=0; for(i=0;i<strlen(pch);i++) {if(pch[i]==item) { count++; } } return count; } int main() { FILE *fin,*fout;  //ここでいろいろ宣言 if((fin=fopen("Thermoplasmaacidophilum ","r"))==NULL) { cout<<"No files exist in current directory!\n"; exit(-1); } if((fout=fopen("Thermoplasmaacidophilum _out","wb"))==NULL) { cout<<"Output file can't open!\n"; exit(-1); } if((fin=fopen("Thermoplasmaacidophilum ","r"))!=NULL) { fwrite(SMF_header,14,1,fout); fwrite(SMF_firsttrack,36,1,fout); fwrite(SMF_track,13,1,fout); do {    //ここにdoに関する処理 } while(numread==100); while(c=fscanf(fin,"%c",c)!=EOF) {   //ここに処理をずらずら } printf("There are %d bases!!\n",n); fclose(fin); fclose(fout); } return 0; } ・・・のように書くと、一つ目のdo-while文は実行されるんですが、二つ目のwhile文が実行されません。一回目でファイルのデータを最後まで読んでるので、元にもどってもう一回やってくれないんでしょうか?初心者なものでそこらへんがよくわかんないんですが・・。どなたか助けてください。

  • 文字列から空白を取り除きたいのですが

    C言語を勉強しはじめて間もない者です。 文字列から空白を取り除く(空白は左に詰めることで埋める)処理をしたいのですが、下記のようなやり方でうまくできなくて困っています。 ↓を実行すると" 1234"なら"12344"になるはずだったのですが、うまくいきません。何がおかしいのでしょうか?? よろしければご教授願います。 ※文字列は半角のみ想定しています。 int i = 0; char str[] = " 1 23 4 5"; char *p; p = str;   while( *p != '\0' ){     if ( isspace(*p) != 0 ){       while( *(p + i + 1) != '\0' ){         *(p + i) = *(p + i + 1);         i++;       }     }     p++;   }  

専門家に質問してみよう