• 締切済み

whileは2度呼べる!?

質問させていただきます。。 何度か似たような質問をさせて頂いていますが、 今回もちょっと掘り下げた質問になっていますので。。。。 ファイルの内容を読み取って.hファイルに書き込むのですが。 ファイルの中身が POINT_A="POINT_B"+"POINT_C" POINT_B="POINT_C"*"POINT_A"   だとします。 狙いとしては POINT_A POINT_B POINT_C です。下記のソースでは右辺と左辺を分けているのですが.... 重複した場合.hファイルに書き込まないようにしています。 問題の場所は/* 右辺の値をとって.hファイルに書き込む関数 */の部分で2回while を使って読み込みをしているのですが何かおかしいとこは ありますでしょうか?? #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX 10000 int leftsidehfunction(); int rightsidehfunction(); int main(int argc ,char **argv) { if(argc != 2 ){ printf("引数の数があっていません。\n"); } rightsidehfunction(argv[1]); } /* 右辺の値をとって.hファイルに書き込む関数 */ int rightsidehfunction(char cfilename[MAX]) { FILE *ft; // 入力ファイルポインタ FILE *fh; // 出力ファイルポインタ int c; //読み込み文字 char buf[MAX]; //バッファ領域 char buf1[MAX]; char cPid[MAX]; // 採取したPID char *cWorkRegiAdd; // 採取文字列作業域アドレス char *cStoRegiAdd; // 文字列格納域アドレス char *cRegiTab[MAX]; // 文字列登録表 int iflag = 0; // 0/1; 右/左のクオート int ichs = 0; // chrの文字数 int istr = 0; // strの文字数 int k; // ntrの探索index int iOid; //OID char cgetfilename[MAX]; char *p; strcpy(cgetfilename,cfilename); ft = fopen(cgetfilename, "r"); strtok(cgetfilename,"."); strcat(cgetfilename,".h"); fh = fopen(cgetfilename, "a+"); if (ft == NULL || fh == NULL) { printf("%s ファイルを開けません。\n",cgetfilename); } while ((c = fgetc(ft)) != EOF) { switch (c) { case '"': iflag = 1 - iflag; /*右のクオート*/ while(fgets(buf1,sizeof buf1,fh) != NULL){ strtok(buf1," "); p = strtok(NULL," "); if (iflag == 0) { cPid[ichs] = '\0'; cWorkRegiAdd = cPid; for(k = 0;k < istr;k++){ if(*cRegiTab[k] != *cWorkRegiAdd) continue; if(strcmp(cRegiTab[k],cWorkRegiAdd) == 0) break; } if(k == istr){ //no hit in str[] cStoRegiAdd = malloc(strlen(cWorkRegiAdd) + 1); strcpy(cStoRegiAdd,cWorkRegiAdd); cRegiTab[istr] = cStoRegiAdd; istr++; db_obj_find_pid(cStoRegiAdd, &iOid); if(iOid <= 0 ){ if(p != cStoRegiAdd){ fprintf(fh, "#define %s 0\n", cStoRegiAdd); }else if(p == cStoRegiAdd){ break; } }else{ if(p != cStoRegiAdd){ fprintf(fh, "#define %s output[obj[%d].outputs + 2].Analog\n",cStoRegiAdd, iOid); }else if(p == cStoRegiAdd){ break; } } } ichs = 0; } iOid = 0; } break; case '\n': if (iflag == 1) { cPid[ichs] = '\0'; iflag = 0; } ichs = 0; break; default: if (iflag == 1) { cPid[ichs] = c; if (ichs < MAX - 1) { ichs++; } } break; } } if (ichs>0) { cPid[ichs]='\0'; } fclose(ft); fclose(fh); return 0; }

みんなの回答

noname#88772
noname#88772
回答No.9

 こんにちは。  プログラムを修正するよりプログラムの設計変更をした方がいいです。 “うまくいったので”という理由ならなおさらです。 もっと楽に実現できる方法を考えるようにして下さい。  おそらく与えられた問題をそのままの形でプログラムを書こうとして いると思われますので仕様の追加や変更があった場合に使い物にならなく なります。 例えば以下のような場合です。  “拾ったキーワードを昇順または降順に並び替えて”  “拾ったキーワードの中で先頭に特定の文字を含むのだけ出して”  #8さんの回答でプログラムを設計すると上記の仕様追加もシンボル テーブルの操作で実現できますし、あらかじめ仕様追加に対応した プログラムが作成できます。  ご参考までに。

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

#6 を簡単に言うと 「こんな面倒なことをしている理由が分からない」 ではないかな. この見解には私も賛成です. はっきりいって 1. 当該出力ファイルから読み込んでシンボルテーブルを作る 2. 入力ファイルから式を読み込んでシンボルテーブルを更新する 3. シンボルテーブルを参照しながら改めて出力ファイルに書きだす という処理の方が明らかに簡単だと思うんだけど, こんな面倒な処理をしようとしている理由は何でしょうか? ちなみに, 出力の .h ファイルで重複してはいけないとする理由を教えていただけると嬉しい.

lilhalileh
質問者

補足

今やってるやりがたがしっくりするから。 というよりこれをやったらうまくいったので......。 重複してはいけないのはそういう決まりごと。

全文を見る
すると、全ての回答が全文表示されます。
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.7

いや、ですから#5で > 元コードを生かす形なら > cRegiTabとnをグローバル変数化する って書いてるんですけど。動かしてみた訳じゃないですが、今のコードでは確実に右辺切り出し処理の結果は左辺切り出し時にチェックされません。 単純にこれを解消するならグローバル変数を使うのが楽です。 あまり推奨できる手段でもありませんが、一番簡単な解法ではあります。 以下余談な訳ですが、 > 書式は決まっていない "左辺=右辺"までは書式が決まってますよね?右辺自身の書式はたしかに変動してるようですけど、それを処理するコードは既に書かれていますし。 なので、取得した行に対して左辺処理と右辺処理を一度に行う、というやり方がある訳です。 これならグローバル変数を使うまでもなく一関数内で処理ができます。

全文を見る
すると、全ての回答が全文表示されます。
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.6

こういう処理は、普通は、トークンが現れる度に、メモリ上の登録リストを見て、リストにトークンが無ければリストに登録、リストにあれば無視、と言うのを繰り返し、最後にリストを出力する、と言う方法を取る。 で「リストに登録済みかどうか?」のチェックに、ハッシュを使うとか、ライブラリにあるリストオブジェクトを重複無しモードで使うとか、ちょっとした工夫をする。 「ファイルに出力済みのデータと重複してるかどうか調べる」と言うのは、使用可能なメモリが極端に少ないとか、ファイルアクセスがメモリアクセスよりも高速だとか、かなり特殊な環境ででしか行わない。 普通、仕事でそういうソースコードを記述したら、上司に後頭部を殴られる。

lilhalileh
質問者

補足

あなたの見解は分かりました。。。。 とどのつまり出来るんでしょうか?? 出来ないんでしょうか?? かなり特殊な環境じゃ使われないでは分からないんですど。。

全文を見る
すると、全ての回答が全文表示されます。
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.5

複数の補足にまったく同じもの(コードも含めて)を載せるのは正直うっとうしいです。特にコードは一箇所で提示してくれれば十分。 で本題ですが、元コードをなるべく生かす形でやるなら cRegiTabとnをグローバル変数化する のがたぶん楽です。このコードでは左辺処理と右辺処理で処理済文字列が別のローカル変数であるため左辺と右辺の重複チェックが働かないので。 が、自分で組むとしたら左辺・右辺で関数を分けずに一行ごとに一括処理する方向で作りますね。 書式は決まってるようなのでさほど面倒ではないと思いますが。

lilhalileh
質問者

補足

え....と 書式は決まっていないですよ。 例えば KEN=("MMK2","MSX") とか KOL="HIMWARI"+1000000"OKL"とか 不規則なので.....。いろいろ試行錯誤して左辺と右辺を 分けるというやり方を選びました。 つまり私の考える案ではできないということでしょうか?? 他の可能性とかじゃなく出来るかどうかをお聞きしているんですが。。。。。。。

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

とりあえず別方面から ・コンパイルが通っているソースを提示すること。  これは何度も指摘しているので説明は省く ・「意図する結果」と「実行した結果」を明示すること。  回答者はソースを解析して実行結果を「推測」するしかない。非常に時間の無駄が生じる。 ・fopen()失敗時、開くことができたファイルはクローズしてから終了すること。 ・malloc()に対応したfree()が存在しない。  システム系によっては終了しても確保された領域がそのままゴミとして存在したままになることがある。 ・if-elseやseitch-caee、for/while文には「何を行っているか(なんの条件か)」は明記する。  解析の手間にもなるし、後で自分で火ソースを見直す時に泣きを見ることになる。 あと、auto変数で5000Byte(MAX:10000 * 配列五つ)ってのも気になる。 「スタックオーバーフロー」起こす元になるよ。 本当にそれだけの領域が必要なのかな?

lilhalileh
質問者

補足

アドバイスは真摯に受け止めて今後留意していきたいと思います。 で本題ですが動くものを載せました。テキストの内容が KO="AB"+"AC" AB="KO"+"AC" の場合 結果は #define KO 0 #define AB 0 #define AC 0 #define KO 0 #define AB 0 となります  これを重複したやつをなくして #define KO 0 #define AB 0 #define AC 0 このような結果にするにはどうしたらいいでしょうか?? #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX 1024 int main() { rightsidehfunction(); leftsidehfunction(); } /* 左辺の値をとって.hファイルに書き込む関数 */ int leftsidehfunction() { FILE *ft; FILE *fh; char buf[MAX]; char *cPid[MAX]; char *cWorkRegiAdd; char *cStoRegiAdd; int n = 0; int istr = 0; int k; char *p; ft = fopen("test.txt","r"); fh = fopen("test.h","a+"); if (fh == NULL || ft == NULL) { printf("ファイルを開けません。\n"); return 1; } /* ファイルを1行ずつ読み込む処理 */ while (fgets(buf, sizeof buf, ft) != NULL){ cWorkRegiAdd = strtok(buf, "="); for(k = 0;k < n;k++){ if(*cPid[k] != *cWorkRegiAdd)continue; if(strcmp(cPid[k],cWorkRegiAdd) == 0)break; } if(k < n) continue; cStoRegiAdd = malloc(strlen(cWorkRegiAdd) + 1); strcpy(cStoRegiAdd,cWorkRegiAdd); cPid[n] = cStoRegiAdd; n++; fprintf(fh, "#define %s 0\n", cStoRegiAdd); } fclose(fh); fclose(ft); return 0; } /* 右辺の値をとって.hファイルに書き込む関数 */ int rightsidehfunction() { FILE *ft; // 入力ファイルポインタ FILE *fh; // 出力ファイルポインタ int c; //読み込み文字 char buf[MAX]; //バッファ領域 char buf1[MAX]; char cPid[MAX]; // 採取したPID char *cWorkRegiAdd; // 採取文字列作業域アドレス char *cStoRegiAdd; // 文字列格納域アドレス char *cRegiTab[MAX]; // 文字列登録表 int iflag = 0; // 0/1; 右/左のクオート int ichs = 0; // chrの文字数 int istr = 0; // strの文字数 int k; // ntrの探索index int iOid; //OID char *p; ft = fopen("test.txt", "r"); fh = fopen("test.h", "w"); if (fh == NULL || ft == NULL) { printf("ファイルを開けません。\n"); return 1; } //ファイルを1文字ずつ読み込む while ((c = fgetc(ft)) != EOF) { switch (c) { case '"': iflag = 1 - iflag; /*右のクオート*/ if (iflag == 0) { cPid[ichs] = '\0'; cWorkRegiAdd = cPid; for(k = 0;k < istr;k++){ if(*cRegiTab[k] != *cWorkRegiAdd) continue; if(strcmp(cRegiTab[k],cWorkRegiAdd) == 0) break; } if(k == istr){ cStoRegiAdd = malloc(strlen(cWorkRegiAdd) + 1); strcpy(cStoRegiAdd,cWorkRegiAdd); cRegiTab[istr] = cStoRegiAdd; istr++; fprintf(fh, "#define %s 0\n", cStoRegiAdd); } ichs = 0; } break; case '\n': if (iflag == 1) { cPid[ichs] = '\0'; iflag = 0; } ichs = 0; break; default: if (iflag == 1) { cPid[ichs] = c; if (ichs < MAX - 1) { ichs++; } } break; } } /* ファイルの最後が改行じゃなかった場合 */ if (ichs>0) { cPid[ichs]='\0'; } fclose(ft); fclose(fh); return 0; }

全文を見る
すると、全ての回答が全文表示されます。
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.3

「コンパイルエラー以外の質問なら、ちゃんとコンパイル可能なソースを書きましょう」ってのは他の方からも言われている通りです。 それはさておき、ループは条件の書き方次第で何重にでもできます。まぁそんなループは推奨される書き方じゃないですが。 何がどううまくいかないのか、が書いてないですが、まずいのはたぶんここ。 > while(fgets(buf1,sizeof buf1,fh) != NULL){ 「書き込み済みファイルの中身を使った既出チェック」をやっているようなのに、ループ前にfhをファイル先頭に戻してないのでファイル終端から読み始めてしまい、絶対にループインしない。 #かつチェック後にファイル終端に戻さないと悲惨なことに どうやるのかはfseek()を調べてください。

lilhalileh
質問者

補足

アドバイスは真摯に受け止めて今後留意していきたいと思います。 で本題ですが動くものを載せました。テキストの内容が KO="AB"+"AC" AB="KO"+"AC" の場合 結果は #define KO 0 #define AB 0 #define AC 0 #define KO 0 #define AB 0 となります  これを重複したやつをなくして #define KO 0 #define AB 0 #define AC 0 このような結果にするにはどうしたらいいでしょうか?? #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX 1024 int main() { rightsidehfunction(); leftsidehfunction(); } /* 左辺の値をとって.hファイルに書き込む関数 */ int leftsidehfunction() { FILE *ft; FILE *fh; char buf[MAX]; char *cPid[MAX]; char *cWorkRegiAdd; char *cStoRegiAdd; int n = 0; int istr = 0; int k; char *p; ft = fopen("test.txt","r"); fh = fopen("test.h","a+"); if (fh == NULL || ft == NULL) { printf("ファイルを開けません。\n"); return 1; } /* ファイルを1行ずつ読み込む処理 */ while (fgets(buf, sizeof buf, ft) != NULL){ cWorkRegiAdd = strtok(buf, "="); for(k = 0;k < n;k++){ if(*cPid[k] != *cWorkRegiAdd)continue; if(strcmp(cPid[k],cWorkRegiAdd) == 0)break; } if(k < n) continue; cStoRegiAdd = malloc(strlen(cWorkRegiAdd) + 1); strcpy(cStoRegiAdd,cWorkRegiAdd); cPid[n] = cStoRegiAdd; n++; fprintf(fh, "#define %s 0\n", cStoRegiAdd); } fclose(fh); fclose(ft); return 0; } /* 右辺の値をとって.hファイルに書き込む関数 */ int rightsidehfunction() { FILE *ft; // 入力ファイルポインタ FILE *fh; // 出力ファイルポインタ int c; //読み込み文字 char buf[MAX]; //バッファ領域 char buf1[MAX]; char cPid[MAX]; // 採取したPID char *cWorkRegiAdd; // 採取文字列作業域アドレス char *cStoRegiAdd; // 文字列格納域アドレス char *cRegiTab[MAX]; // 文字列登録表 int iflag = 0; // 0/1; 右/左のクオート int ichs = 0; // chrの文字数 int istr = 0; // strの文字数 int k; // ntrの探索index int iOid; //OID char *p; ft = fopen("test.txt", "r"); fh = fopen("test.h", "w"); if (fh == NULL || ft == NULL) { printf("ファイルを開けません。\n"); return 1; } //ファイルを1文字ずつ読み込む while ((c = fgetc(ft)) != EOF) { switch (c) { case '"': iflag = 1 - iflag; /*右のクオート*/ if (iflag == 0) { cPid[ichs] = '\0'; cWorkRegiAdd = cPid; for(k = 0;k < istr;k++){ if(*cRegiTab[k] != *cWorkRegiAdd) continue; if(strcmp(cRegiTab[k],cWorkRegiAdd) == 0) break; } if(k == istr){ cStoRegiAdd = malloc(strlen(cWorkRegiAdd) + 1); strcpy(cStoRegiAdd,cWorkRegiAdd); cRegiTab[istr] = cStoRegiAdd; istr++; fprintf(fh, "#define %s 0\n", cStoRegiAdd); } ichs = 0; } break; case '\n': if (iflag == 1) { cPid[ichs] = '\0'; iflag = 0; } ichs = 0; break; default: if (iflag == 1) { cPid[ichs] = c; if (ichs < MAX - 1) { ichs++; } } break; } } /* ファイルの最後が改行じゃなかった場合 */ if (ichs>0) { cPid[ichs]='\0'; } fclose(ft); fclose(fh); return 0; }

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

うう, インデントが崩れると全く読めない. さておき, わざわざ while をネストする必要性って何だろう. ちょっとは速くなるのかなぁ? あと表面的に眺めた限りでは途中の if 文, if(p != cStoRegiAdd){ は必ずこの条件が成り立つような気がするのですが, それは意図したとおりでしょうか?

lilhalileh
質問者

補足

アドバイスは真摯に受け止めて今後留意していきたいと思います。 で本題ですが動くものを載せました。テキストの内容が KO="AB"+"AC" AB="KO"+"AC" の場合 結果は #define KO 0 #define AB 0 #define AC 0 #define KO 0 #define AB 0 となります  これを重複したやつをなくして #define KO 0 #define AB 0 #define AC 0 このような結果にするにはどうしたらいいでしょうか?? #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX 1024 int main() { rightsidehfunction(); leftsidehfunction(); } /* 左辺の値をとって.hファイルに書き込む関数 */ int leftsidehfunction() { FILE *ft; FILE *fh; char buf[MAX]; char *cPid[MAX]; char *cWorkRegiAdd; char *cStoRegiAdd; int n = 0; int istr = 0; int k; char *p; ft = fopen("test.txt","r"); fh = fopen("test.h","a+"); if (fh == NULL || ft == NULL) { printf("ファイルを開けません。\n"); return 1; } /* ファイルを1行ずつ読み込む処理 */ while (fgets(buf, sizeof buf, ft) != NULL){ cWorkRegiAdd = strtok(buf, "="); for(k = 0;k < n;k++){ if(*cPid[k] != *cWorkRegiAdd)continue; if(strcmp(cPid[k],cWorkRegiAdd) == 0)break; } if(k < n) continue; cStoRegiAdd = malloc(strlen(cWorkRegiAdd) + 1); strcpy(cStoRegiAdd,cWorkRegiAdd); cPid[n] = cStoRegiAdd; n++; fprintf(fh, "#define %s 0\n", cStoRegiAdd); } fclose(fh); fclose(ft); return 0; } /* 右辺の値をとって.hファイルに書き込む関数 */ int rightsidehfunction() { FILE *ft; // 入力ファイルポインタ FILE *fh; // 出力ファイルポインタ int c; //読み込み文字 char buf[MAX]; //バッファ領域 char buf1[MAX]; char cPid[MAX]; // 採取したPID char *cWorkRegiAdd; // 採取文字列作業域アドレス char *cStoRegiAdd; // 文字列格納域アドレス char *cRegiTab[MAX]; // 文字列登録表 int iflag = 0; // 0/1; 右/左のクオート int ichs = 0; // chrの文字数 int istr = 0; // strの文字数 int k; // ntrの探索index int iOid; //OID char *p; ft = fopen("test.txt", "r"); fh = fopen("test.h", "w"); if (fh == NULL || ft == NULL) { printf("ファイルを開けません。\n"); return 1; } //ファイルを1文字ずつ読み込む while ((c = fgetc(ft)) != EOF) { switch (c) { case '"': iflag = 1 - iflag; /*右のクオート*/ if (iflag == 0) { cPid[ichs] = '\0'; cWorkRegiAdd = cPid; for(k = 0;k < istr;k++){ if(*cRegiTab[k] != *cWorkRegiAdd) continue; if(strcmp(cRegiTab[k],cWorkRegiAdd) == 0) break; } if(k == istr){ cStoRegiAdd = malloc(strlen(cWorkRegiAdd) + 1); strcpy(cStoRegiAdd,cWorkRegiAdd); cRegiTab[istr] = cStoRegiAdd; istr++; fprintf(fh, "#define %s 0\n", cStoRegiAdd); } ichs = 0; } break; case '\n': if (iflag == 1) { cPid[ichs] = '\0'; iflag = 0; } ichs = 0; break; default: if (iflag == 1) { cPid[ichs] = c; if (ichs < MAX - 1) { ichs++; } } break; } } /* ファイルの最後が改行じゃなかった場合 */ if (ichs>0) { cPid[ichs]='\0'; } fclose(ft); fclose(fh); return 0; }

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

コンパイルできません。 >int rightsidehfunction(); >int rightsidehfunction(char cfilename[MAX]) プロトタイプ宣言と実体の定義が違います。 >if (ft == NULL || fh == NULL) { >  printf("%s ファイルを開けません。\n",cgetfilename); >} ファイルが無くてもアプリケーションは続行します。 >db_obj_find_pid 未定義とコンパイルエラーが出ます。 db ← 名前からしてデータベース関係のライブラリでしょうか? (検索しても見当たりませんでした) 他にもたくさん(sizeofのカッコ等)ありますが、 致命的なエラーのみをざっと見た感じで出しました。 (まだあると思います)

lilhalileh
質問者

補足

お返事ありがとうございます。 せっかくやっていただいたんすけど.... 残念ながらコンパイルは通りません。 ちょっと特殊な部分があるんで....... ご指摘いただいた部分に関しては留意します。 whileを2度呼んでるところありますよね?? そこで何か気づく点とかありますでしょうか?? さっきからコンパイルは通るんですけど 実行しても結果がうまくいきませんで。。

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

関連するQ&A

  • 文字列を比較

    文字列を比較して 一つでも一致したらファイルに書き込まず抜ける 一つも一致しなかった場合一度書き込んで抜けるという操作を 下記のコードで実現したいんですけど、 "cPid[n] = cStoRegiAdd; for(j = 0;j < MAX;j++){ if(cPid[n] != cRegiTab[j]){ iflag = 1; } } if(iflag == 1){ fprintf(fh,"#define %s 0\n",cStoRegiAdd); }" の部分で何かおかしいとこはありますか?? もしあれば教えていただきたいんですけど?? #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX 1024 char *cRegiTab[MAX]; // 文字列登録表 int n = 0; int main() { rightsidehfunction(); leftsidehfunction(); } /* 左辺の値をとって.hファイルに書き込む関数 */ int leftsidehfunction() { FILE *ft; FILE *fh; char buf[MAX]; char buf1[MAX]; char *cPid[MAX]; char *cWorkRegiAdd; char *cStoRegiAdd; int istr = 0; int k; char *p; char *q; int s; int i; int j; int iflag = 0; ft = fopen("test.txt","r"); fh = fopen("test.h","a+"); if (fh == NULL || ft == NULL) { printf("ファイルを開けません。\n"); return 1; } /* ファイルを1行ずつ読み込む処理 */ while (fgets(buf, sizeof buf, ft) != NULL){ cWorkRegiAdd = strtok(buf, "="); for(k = 0;k < n;k++){ if(*cPid[k] != *cWorkRegiAdd)continue; if(strcmp(cPid[k],cWorkRegiAdd) == 0)break; } if(k < n) continue; cStoRegiAdd = malloc(strlen(cWorkRegiAdd) + 1); strcpy(cStoRegiAdd,cWorkRegiAdd); cPid[n] = cStoRegiAdd; for(j = 0;j < MAX;j++){ if(cPid[n] != cRegiTab[j]){ iflag = 1; } } if(iflag == 1){ fprintf(fh,"#define %s 0\n",cStoRegiAdd); } n++; } fclose(fh); fclose(ft); return 0; } /* 右辺の値をとって.hファイルに書き込む関数 */ int rightsidehfunction() { FILE *ft; // 入力ファイルポインタ FILE *fh; // 出力ファイルポインタ int c; //読み込み文字 char buf[MAX]; //バッファ領域 char buf1[MAX]; char cPid[MAX]; // 採取したPID char *cWorkRegiAdd; // 採取文字列作業域アドレス char *cStoRegiAdd; // 文字列格納域アドレス int iflag = 0; // 0/1; 右/左のクオート int ichs = 0; // chrの文字数 int istr = 0; // strの文字数 int k; // ntrの探索index int iOid; //OID char *p; ft = fopen("test.txt", "r"); fh = fopen("test.h", "w"); if (fh == NULL || ft == NULL) { printf("ファイルを開けません。\n"); return 1; } //ファイルを1文字ずつ読み込む while ((c = fgetc(ft)) != EOF) { switch (c) { case '"': iflag = 1 - iflag; /*右のクオート*/ if (iflag == 0) { cPid[ichs] = '\0'; cWorkRegiAdd = cPid; for(k = 0;k < istr;k++){ if(*cRegiTab[k] != *cWorkRegiAdd) continue; if(strcmp(cRegiTab[k],cWorkRegiAdd) == 0) break; } if(k == istr){ cStoRegiAdd = malloc(strlen(cWorkRegiAdd) + 1); strcpy(cStoRegiAdd,cWorkRegiAdd); cRegiTab[istr] = cStoRegiAdd; istr++; fprintf(fh, "#define %s 0\n", cStoRegiAdd); } ichs = 0; } break; case '\n': if (iflag == 1) { cPid[ichs] = '\0'; iflag = 0; } ichs = 0; break; default: if (iflag == 1) { cPid[ichs] = c; if (ichs < MAX - 1){ ichs++; } } break; } } /* ファイルの最後が改行じゃなかった場合 */ if (ichs>0) { cPid[ichs]='\0'; } fclose(ft); fclose(fh); return 0; }

  • 重複文字を出力させない!!

    こんにちは!! ご質問させてください。 右辺値のダブルクオートくくりの 文字列をテキストから読み込みファイルに書き込む処理ですが..... うまく取れません。下記にソースコードを提示しましたので 一読の上アドバイスいただけたらと思います。 テキストファイルのないようは k="seikyo"-"himawari" k="north"+"seikyo" これを読み込んだ場合.tファイルに書き込む内容は seikyo himawari north seikyo ですが重複した場合は書き込まないようにプログラムしたつもりです。 seikyo himawari north としたいと思っています。 希望通りの形にならないので皆様どうか お力をお貸しください。よろしくお願いします。 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<syslog.h> #define MAX_REC_A 256 #define MAXFIELD 128 #define BUFFLEN 256 #define MAX 10000 #define MBF 1024 int makemoutputhrightside(); int main(int argc ,char **argv) { makemoutputhrightside(argv[1]); } /* 右辺の値をとって.tファイルに書き込む関数 */ int makemoutputhrightside(char sum[BUFFLEN]) { FILE *ft; FILE *fh; int c; char cPid[BUFFLEN]; char *p; char *q; char *str[BUFFLEN]; int flag = 0; int i = 0; int n = 0; int k; char filename[64]; char cdmy[MAX]; strcpy(filename,sum); strcat(filename,".txt"); ft = fopen(filename, "r"); fh = fopen("moutput.t", "a"); if (ft == NULL || fh == NULL) { syslog(LOG_ERR,"開けないファイルがあります。\n"); return 1; } //ファイルを1文字ずつ読み込む while ((c = fgetc(ft)) != EOF) { switch (c) { case '"': flag = 1 - flag; /*右のクオート*/ if (flag == 0) { cPid[i] = '\0'; p = strcpy(cdmy,cPid); for(k = 0;k < n;k++){ if(*str[k] != *p) continue; if(strcmp(str[k],p) == 0) break; } if(k < n) continue; q = malloc(strlen(p) + 1); strcpy(q,p); str[n] = q; fprintf(fh, "%s ",q); i = 0; } n++; break; case '\n': if (flag == 1) { cPid[i] = '\0'; fprintf(fh, "%s \n", cPid); } flag = 0; } i = 0; break; default: if (flag == 1) { cPid[i] = c; if (i < BUFFLEN - 1) { i++; } } break; } } /* ファイルの最後が改行じゃなかった場合 */ if (i>0) { cPid[i]='\0'; fprintf(fh,"%s\n",cPid); } fclose(ft); fclose(fh); return 0; }

  • ファイルを読み込んだ時に同じ文字が重複した場合.kファイルに書き込まない

    こんにちは。 テキストファイルの内容が KENIA=ナイル川 NORTH=小さな旅人 KENIA=せせらぎ 上記のファイルを読み込んだ際に下記のコードで実行すると .hファイルに書き込まれる内容は..... KENIA NORTH KENIA ですが同じ言葉が出現した場合(重複した場合)ファイルに書きまないようにしたいと思っています。すなわち KENIA NORTH   としたいと思っています。 この場合どうしたらいいでしょうか?? テキストファイルは例であり内容は不規則ですので。。。。 力をお貸しください。よろしくお願いします。 #include<stdio.h> int makemoutputhleftside(); int main(int argc,char **argv){ makemoutputhleftside(argv[1]); } int makemoutputhleftside(char sum[64]) { char buf[1024]; char cPid[256]; int iOid; FILE *ft; FILE *fh; char filename[64]; int i; strcpy(filename,sum); strcat(filename,".txt"); ft = fopen(filename,"r"); fh = fopen("moutput.h","w"); if (ft == NULL || fh == NULL) { printf("開けないファイルがあります。\n"); return 1; } /* ファイルを1行ずつ読み込む処理 */ while (fgets(buf, sizeof buf, ft) != NULL) { strcpy(cPid, strtok(buf, "=")); fprintf(fh, "#define %s \n", cPid); fclose(fh); fclose(ft); return 0; }

  • 書式付標準出力をするには??

    こんにちは テキストファイルを読み込んで .hファイルに書き込んでいるものなのですが.... #include <stdio.h> #define MAX 256 int main() { FILE *in, *out; char *p, buf[MAX]; int lhs, in_quote; in = fopen("moutput.txt", "r"); if (in == NULL) { printf("Cannot open sample.txt\n"); return 1; } out = fopen("moutput.h", "w"); if (out == NULL) { printf("Cannot open sample.h\n"); return 1; } while (fgets(buf, MAX, in) != NULL) { lhs = 1; in_quote = 0; for (p = buf; *p != '\0'; p++){ if (*p == '=') { lhs = 0; fputc('\n', out); } else if (*p == '"'){ if (in_quote) { in_quote = 0; fputc('\n', out); } else in_quote = 1; }else if (lhs || in_quote){ fputc(*p, out); } } } } 上記のプログラムでfputc(*p,out)で出力させている 部分があると思いますが。 実はこれを書式付で出力させたいと思っています。 今現在読み込んでいるファイルは "POINT_a"="POINT_b"+1000*"POINT_D" で出力結果は POINT_a POINT_b POINT_D なのですが これを VALUE: POINT_a VALUE: POINT_b VALUE: POINT_D にしたいのですが fputcのところをどうしたらいいでしょうか?? ご教授よろおしくおねがいします。

  • 逆ポーランドで電卓

    100 10 + = 110 この答えを下のようにするには、どうしたらいいですか? [100] [10] + = 110 教えて下さい。 下にプログラムを書いて置いたので、指摘をして下さい。 #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define isSpace(c) isspace((c) & 0xFF) #define isDigit(c) isdigit((c) & 0xFF) #define isAlpha(c) isalpha((c) & 0xFF) char buf[1024], buf2[1024], *p, *p2, c, o[] = "+-*/"; int get(void) { do c = *p++; while (isSpace(c)); return c; } void expr(const char *s) { char c2; if (*s) for (expr(s+2); c==s[0] || c==s[1]; ) c2 = c, expr(s+2), p2 += sprintf(p2, " %c", c2); else if (get() == '.' || isDigit(c)) p2 += sprintf(p2, " %.15g", strtod(p-1, &p)), get(); else if (c == '(') expr(o), c == ')' ? get() : (c = 1); else if (c == '-') expr(s), p2 += sprintf(p2, " _"); else if (isAlpha(c)) exit(0); else c = 1; } double calc(char *p) { double v[100]; int i = 0; for(;;) switch (*p++) { case '\0': return v[i-1]; case ' ': break; case '_': v[i-1] = -v[i-1]; break; case '+': --i; v[i-1] += v[i]; break; case '-': --i; v[i-1] -= v[i]; break; case '*': --i; v[i-1] *= v[i]; break; case '/': --i; v[i-1] /= v[i]; break; default: v[i++] = strtod(p-1, &p); break; } } int main(void) { (fgets(p = buf, sizeof buf, stdin)); *(p2 = buf2) = 0,expr(o), c ? puts(" エラー") : printf("%s = %.15g\n", buf2, calc(buf2)); return 0; }

  • CSVを用いた検索プログラム動かし方

    #pragma warning( disable: 4996 ) #include <stdio.h> #include <string.h> #include <fstream> using namespace std; typedef struct tagKOTOWAZA{ char japanese[50]; char english[50]; }KOTOWAZA; int main() { char buf[256]; KOTOWAZA c[200]; int i, count; /*ifstream strtok strcpy を使ってファイルを読み込む*/ //=====ここから===== ifstream fin("Book1.csv"); if(fin.is_open()){ //ファイル内容の表示とクローズ for(count=0;fin.getline(buf, sizeof(buf)), !fin.eof();count++){//読み込める間 //printf("%s",buf);デバッグ用 char *p; p = strtok(buf,","); if(p)strcpy(c[count].japanese,p); p = strtok(NULL,","); if(p)strcpy(c[count].english,p); } fin.close(); }else{ printf("ファイルのオープンに失敗しました。\n"); return 1; } //=====ここまで==== return 0; } ここからどうすればCSVファイルに書いた 漢字,English を検索できるのかがわかりません・・・ 言語はC++を使っていますvisualstudio2012を使っています。 どうすればいいのか全く分かりません。 よろしくお願いします。

  • メモリ

    #include "stdafx.h" #include <ctype.h> #include <string.h> #include <stdlib.h> int check(int a[100], int n); typedef struct { char number[6]; char class_type[20]; char name[8]; char subject[5]; } my; my data[100]; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char bufG[1111]; int i; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) !=NULL){ str=buf; while(*str != '\0'){ if(*str != ','){ for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; switch(field){ case 0: strcpy(data[line].number, bufG); break; case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; } field++; } else{ str++; } } line++; field = 0; } int p, q; int a[100]; int u = 0; for(p = 0; p < line; p++){ for(q = 0; q < line; q++){ if(strcmp(data[p].class_type, data[q].class_type) == 0 && strcmp(data[p].subject, data[q].subject) == 0 && p != q ){ //処理 } } } } fclose(fp); return 0; } 先日文字列入れ替えについてご質問したものですが メモリの取り方についてご質問します。 先日このプログラムにおいて my data[100]と固定してるのはいけないという意見をもらったので メモリを取得しようと思ってるのですが できればdata[i].○○の形でアクセスしたいのでこのままの形は あまりかえたくないです。この場合 while(fgets(buf,1000,fp) !=NULL){ str=buf;     int len = strlen(buf); my *o; o = (my *)calloc( len + 1, sizeof(my *)) while(*str != '\0'){ としてみたのですがこれは実際どうなのでしょうか? NULLは帰ってきてないみたいなので割り当ては出来てるとは思うんですが この一行の文字列の大きさにぴったり合うメモリを割り当てたいのですが ちゃんとなっているか調べる方法を教えて下さい。

  • fgets関数を使用したときの文字あふれについて

    fgets関数を用いて文字列を入力し、その長さを測るプログラムを作っています。 #include <stdio.h> #include <string.h> #define MAX 256 int main ( int, char *[] ); int main ( argc, argv ) int argc; char *argv[]; { char buf[( MAX )]; while ( 1 ){ memset ( buf, 0, sizeof( buf )); fgets ( buf, MAX, stdin ); if( fgets == NULL ){ break; } printf("入力した文字列の長さは%dです\n" ,strlen( buf )); } return 0; } このプログラムでは、256までしか文字列の長さを測ることができません。 もしこのプログラムで256を超える文字列を入力してしまうと、文字のあふれが発生し、 「入力した文字列の長さは256です」 「入力した文字列の長さは(あふれた文字列の長さ)です」 とこのようになってしまいます。 このプログラムで256以上の文字を読み捨てて、 「入力した文字列の長さは(あふれた文字列の長さ)です」 を表示しないようにできるのでしょうか? また読み捨てた文字列の長さを知ることはできるのでしょうか? もしかしたらfgets関数を使用すると不可能なのではないか?と思っています。 分かる方が居ましたらどうか教えて下さい。 よろしくお願いします。

  • javaのコンパイルができません。

    コンパイルができません エラーの内容とソースコードは次です Microsoft Windows [Version 6.0.6002] Copyright (c) 2006 Microsoft Corporation. All rights reserved. C:\Users\j1409061\Documents\java\MeikaiJava>javac SR091409061.java SR091409061.java:7: 式の開始が不正です。 const int MAX_INT = 2147483647; ^ SR091409061.java:8: 式の開始が不正です。 const int BUFFER_SIZE = 100; ^ SR091409061.java:9: ';' がありません。 int main();{ ^ SR091409061.java:16: ']' がありません。 char buf[BUFFER_SIZE]; ^ SR091409061.java:16: 式の開始が不正です。 char buf[BUFFER_SIZE]; ^ SR091409061.java:22: 式の開始が不正です。 n = sscanf(buf, "%d %c", &data, &c); ^ SR091409061.java:22: 式の開始が不正です。 n = sscanf(buf, "%d %c", &data, &c); ^ SR091409061.java:73: 式の開始が不正です。 n = sscanf(buf+i, "%d", &data); ^ SR091409061.java:96: class、interface、または enum がありません。 } ^ エラー 9 個 C:\Users\j1409061\Documents\java\MeikaiJava> //最大値と最小値を求めよう // C:\Users\j1409061\Documents\java\MeikaiJava\SR091409061.java class SR091409061 { public static void main(String args[]) { Scanner stdIn = new Scanner(System.in); const int MAX_INT = 2147483647; const int BUFFER_SIZE = 100; int main();{ /* 変数を定義、初期化 */ int data; int max = -1; int min = MAX_INT; bool data_exist = false; int i, n; char buf[BUFFER_SIZE]; printf("Please input data : "); while(true) { /* データ(1行分読み込み) */ fgets(buf, BUFFER_SIZE, stdin); /* データ取り出しと計算 */ n = sscanf(buf, "%d %c", &data, &c); if( ( n == -1 ) || ( n == 0 ) ) { break; } else if (n == 1) { // the number of data is 1. data_exist = true; data = abs( data ); if(max < data){ /* maxを変更 */ max = data; } if(min > data){ /* minを変更 */ min = data; } } else if (n == 2) { // the number of data is larger than 2. i = 0; while (true) { data_exist = true; data = abs( data ); if(max < data){ /* maxを変更 */ max = data; } if(min > data){ /* minを変更 */ min = data; } // 空白文字を読み飛ばす while (true) { if(buf[i] == ' ') { i++; } else { break; } } // 数字(0から9)を読み飛ばす while (true) { if( ( buf[i] >= '0' ) && ( buf[i] <= '9' ) ) { i++; } else { break; } } // 行末なら終える if(buf[i] == '\n') { break; } // データ読み込み.読み込みに成功したら次の文字へ(i++), 失敗したら終える(break). n = sscanf(buf+i, "%d", &data); if(n == 0) { break; } i++; } } if(n == 0) { break; } } /* 最大値, 最小値を出力 */ if (!data_exist) { printf("No data.\n"); } else { printf("Max = %d\n",max); printf("Min = %d\n",min); } return 0; } } } } よろしくお願いします

  • CArray

    #include <ctype.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE -1 char* get(char **p_str); char *get_line(char buf[]); int comp_rtn(const void *p1, const void *p2); typedef struct { int number; char class_type[10]; char name[15]; char subject[10]; int ten; } my; my *data; void myswap(my *p, my *q); int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufFormat; char *bufG; int line2 = 0; if((fp=fopen("jjj.txt","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); if((fp=fopen("jjj.txt","r"))==NULL){   printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); while(fgets(buf,1000,fp) != NULL){ bufFormat = get_line(buf); str = bufFormat; while(*str != '\0'){ bufG = get(&str); switch(field){      case 0: data[line].number = atoi(bufG); break case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; case 4: data[line].ten = atoi(bufG); break; } str++; field++; } line++; field = 0; } fclose(fp); qsort(data,line,sizeof(my),comp_rtn); for(int m = 0; m < line; m++){ printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject); printf("%d\n", data[m].ten); printf("\n"); } free(data); return 0; } void myswap(my *p, my *q) { my temp; temp = *p; *p = *q; *q = temp; } char *get(char **p_str) { int i; char *str; str = *p_str; static char bufG[1000]; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else if(*str == '\\'){ str++; if(*str == 'c'){ bufG[i] = ','; } else if(*str == '"'){ bufG[i] = '"'; } } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; *p_str = str; return bufG; } char *get_line(char buf[]) { int in_quotation = FALSE, i = 0; char* str = buf; static char bufG[1000]; while(*str != '\0'){ if(*str=='"'){ if(in_quotation == TRUE){ str++; if(*str == '"'){ bufG[i] = '\\'; i++; bufG[i] = '"'; i++; } else{ in_quotation = FALSE; bufG[i] = *str; i++; } } else{ in_quotation = TRUE; } } else{ switch(*str){ case '\n': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'n'; i++; } else{ bufG[i] = *str; i++; } break; case ',': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'c'; i++; } else{ bufG[i] = *str; i++; } break; default: bufG[i] = *str; i++; } } str++; } bufG[i] = '\0'; return bufG; } 以前上記のソースになるプログラムの質問をいくつかしました。 これはCで組んでますがC++で組みなおすに当たり 今mallocを使っていますがCArrayを使用するように薦められました どういう感じになるのかさっぱりわかりません。