C言語で可変長から固定長に変換する方法とは?

このQ&Aのポイント
  • C言語で可変長から固定長に変換する方法について教えてください。
  • 可変長のファイルを固定長にそろえるためのプログラムがうまく動作しないです。
  • fprintfを使った際にファイルの長さが40に揃わない問題が発生しています。
回答を見る
  • ベストアンサー

C言語で可変長から固定長に変換方法は??

C言語で可変長から固定長に変換方法は?? ある可変長のファイルがあって、レコード長を全て40にそろいたいと思って以下のようにプログラム作りました: ・・・・・(省略) len = strlen(buf); // fscanf使ってファイルから読みみ込んだものbufに格納 n = 40-len; char * str = (char *)malloc(n+1); memset(str, ' ', n); strcat(buf,str); //レコード40バイトになるまで空白を詰めていく fprintf(fpt,buf);//fprintf使って新しいファイルに書き込み ・・・・・・(省略) 実行してみたところ、全部40という長さになっていない、40超えるものも多数出ました。 これは何がだめですか?fprintfをつかったからだめですか?それともmalloc freeにする必要ありますか?まったく検討つかないです。どうかよろしくお願いします

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

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8522/19371)
回答No.9

>while(fgets(buf,REC,fp)!= NULL){ >len = strlen(buf); >printf("レコード長 :%d\n",len); >} >結果は >レコード長 :39 >レコード長 :2 よくあるミスです。 fgetsの2番目の引数は「文字列の終端文字であるヌル文字を格納する分を含んだ、バッファの実サイズ」を指定する事になっています。 そして、困った事に「改行文字は、文字列の文字数に含み、改行文字も読み込む」のです。 では、質問者さんのプログラムを検証してみましょう。 while(fgets(buf,REC,fp)!= NULL){ RECは40です。そのため、fgetsは「bufが一杯になる39文字までを読んで、読み込みを打ち切り、末尾にヌル文字を付加」します。 len = strlen(buf); bufには「39文字+終端のヌル文字」が入っているので、strlenは終端のヌル文字の手前にある文字数の「39」を返し、lenは39になります。 printf("レコード長 :%d\n",len); printfは「レコード長 :39+改行」を表示します。 while(fgets(buf,REC,fp)!= NULL){ RECは40です。そのため、fgetsは「さっき読み残した1文字と、改行文字を読んで打ち切り、末尾、つまり改行文字の後にヌル文字を付加」します。 len = strlen(buf); bufには「読み残した1文字+改行文字1文字+終端のヌル文字」が入っているので、strlenは終端のヌル文字の手前にある文字数の「2」を返し、lenは2になります。 printf("レコード長 :%d\n",len); printfは「レコード長 :2+改行」を表示します。 結果、質問者さんのプログラムは レコード長 :39 レコード長 :2 を表示する事になります。 これは「意図した結果ではないが、fgets()関数の仕様通りの動作」であり「正常に動作している」のです。 単に「意図通りの引数を指定しなかった為、意図した動きをしなかっただけ」なのですね。 そういう訳で「40文字+改行1文字+終端ヌル1文字」で、バッファは42バイト必要で、fgetsには「42文字あるバッファ」と「42」を指定しなければならないのです。 レコード長の定義として「#define REC 40」と定義しているのなら、以下のように書かねばなりません。 #define REC 40 char buf[REC + 2] /* 改行文字と終端ヌル文字も格納できるように、レコード長より2文字分大きいバッファを用意しなければならない */ (途中省略) while(fgets(buf,siziof(buf),fp)!= NULL){ /* fgetsの第2引数に定数は指定しない事。必ず「sizeof(指定したバッファ)を指定すること */ len = strlen(buf); if (buf[len - 1] == '\n') buf[--len] = '\0'; /* 末尾に改行があるなら、末尾の改行を終端文字ヌルで上書きして取り去り、その分、lenを1減らす */ printf("レコード長 :%d\n",len); }

その他の回答 (8)

  • chie65535
  • ベストアンサー率43% (8522/19371)
回答No.8

追記な訂正。 >fprintf(fpt,40,"%-40s\n",buf); は fprintf(fpt,"%-40s\n",buf); の誤り。度々すいません。

teakay84
質問者

お礼

ありがとうございました。私がやりたいこと的中に当たりました。早速アドバイス通りにプログラム実行してみたのです。作られたファイルをレコード長の長さを確認するため以下のプログラムを作りました。 while(fgets(buf,REC,fp)!= NULL){ len = strlen(buf); printf("レコード長 :%d\n",len); } 結果は レコード長 :39 レコード長 :2 というふうになったですが、これはどいう意味か、教えて頂ければ嬉しいのですが。。。もしかしたら長さ2のところは改行と終端文字の値でしょうか? ちなみに、C言語を詳しくなるため、お勧めの本があれば教えて頂きたいです。よろしくお願いします

  • chie65535
  • ベストアンサー率43% (8522/19371)
回答No.7

蛇足な追記。 今回のように「40文字の幅に左詰めでファイルに書く」のではなく「40文字以下の、n文字の空白文字の文字列」が欲しいなら char * str = (char *)malloc(n+1); memset(str, ' ', n); str[n] = '\0'; (中略) free(str); でも構わないけど、もっと簡単に char *str; str = " (ここに空白を40文字並べる:注参照) " + 40 - n; でOK(但し、strが指す文字列は読み込み専用なので書き換えできない) 注:このサイトで投稿すると「連続した複数の半角空白」は「1つの半角空白」に勝手に直されて投稿されるので40個の空白を並べて書けません。実際にプログラムに書く時は「40個の空白を並べて」書いてください。

  • chie65535
  • ベストアンサー率43% (8522/19371)
回答No.6

>これは何がだめですか? strにn文字分の' 'を埋め込むまでは良いが、そのstrに終端文字の'\0'を付けてないのがダメ。 厳しい事を言えば、fscanfを使うのもダメだし、memsetを使うのもダメだし、mallocを使うのもダメだし、mallocがエラーを返してくるのをチェックしてないのもダメだし、ちゃんとfreeしているか明記してないのもダメ。 で、どうして失敗しているのかと言うと、例えば 1行目が30文字 2行目が20文字 3行目が35文字 だったとしよう。 1行目は、nが40-30で10、+1して11文字のバッファがmallocで返される。 そこに10文字の' 'を埋める。 運良く、mallocが返したメモリは「最初は全部ゼロで埋まってる」ので、strには「10文字の空白+終端文字を意味する運良く最初からあったゼロ」が出来る。 それを「30文字のbufにstrcatする」ので「30文字+10文字」になる。 そして、使い終わったstrはfree(str);で開放される(けど、そのメモリには10文字の空白が残ってる) 一見、1行目は正しく動く。 2行目は、nが40-20で20、+1して21文字のバッファがmallocで返される。 そこに20文字の' 'を埋める。 運良く、mallocが返したメモリは、さっき使ったメモリと同じ場所なので「10文字の空白と、11文字目以降全部ゼロで埋まってる」ので、strには「20文字の空白+終端文字を意味する運良く最初からあったゼロ」が出来る。 それを「20文字のbufにstrcatする」ので「20文字+20文字」になる。 そして、使い終わったstrはfree(str);で開放される(けど、そのメモリには20文字の空白が残ってる) 一見、2行目も正しく動く。 3行目は、nが40-35で5、+1して6文字のバッファがmallocで返される。 そこに5文字の' 'を埋める。が、そこには「前回mallocして、使用後にfreeした、使い終わったメモリの残骸」があるので、その残骸には「既に20文字の空白が埋まっている」ので、5文字の' 'を埋めても意味は無い。 残念ながら、mallocが返したメモリは、さっき使ったメモリと同じ場所なので「20文字の空白と、21文字目以降全部ゼロで埋まってる」ので、strには「20文字の空白+終端文字を意味する運良く最初からあったゼロ」が出来る。空白を5文字しか埋めてないのに。 それを「35文字のbufにstrcatする」ので「35文字+20文字」になる。5文字の空白を足すつもりで、終端文字を付け忘れた所為で、20文字の空白が足されちゃう訳だ。 そして、使い終わったstrはfree(str);で開放される(けど、そのメモリには20文字の空白が残ってる) そして、質問者さんは >全部40という長さになっていない、40超えるものも多数出ました。 って悩む事になる。 とりあえずの修正なら memset(str, ' ', n); の直後に str[n] = '\0'; ってのを追加すれば大丈夫。 で、mallocとかstrlenとかmemsetとか使わず、最も簡単に済ます方法は、以下の通り。 char buf[260] /* scanfを行うのに充分な大きさを確保しておく。もちろん、buf[41]ではダメ */ ・・・・・(省略) buf[40] = '\0'; /* 元々のbufが40文字以上だった時に41文字目以降を捨てる。これを忘れると41文字以上の行が出来てしまう */ fprintf(fpt,40,"%-40s\n",buf); /* 左揃えで40文字の幅に書き込めば終わり */ で、本当の所を言うと「buf[40] = '\0';の処理で、行末で40バイトに切り捨てる際に、漢字などの2バイト文字の後半バイトだけ切り捨ててしまう」と言う事が起きないように「レコードの末尾に2バイト文字の先頭バイトだけ残る場合は、それを空白に置き換える」と言う処理も必要だったりする。 以下蛇足。 冒頭の「fscanfを使うのもダメ」な理由。 もし「入力ファイル名の指定を間違えて、読みこんだファイルがテキストファイルじゃなく、空白文字や改行コードが出てこないバイナリファイルだった」としたら、scanfは何文字のデータをbufに入れようとするだろう? 「うっかり、5メガバイトある動画ファイル」を入力に指定したら?そして、その5メガバイトの中に「空白文字や改行コードが1つも無い」としたら? scanfは、言われた通り、bufに「空白文字や改行コードが現れるまで読みこもう」とするだろう。 そして「bufのアドレスに5メガバイトのデータを読み込もう」として、プログラムが落ちてしまう。メモリをグチャグチャに壊したままで。 なので「絶対の保障」が無い限り、scanfやfscanfは使っちゃいけない。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

単に、 fprintf(fpt,"%-40s\n",buf); でいいんじゃないかと。

  • ssk38
  • ベストアンサー率44% (22/49)
回答No.4

#include <stdio.h> #include <string.h> #define BUFSIZE 10000 #define WIDE 40 int main(int argc, char *argv[]) { FILE *fp; char buf[BUFSIZE]; int n; if (argc == 1) { fprintf(stderr, "USAGE: %s <input>\n", argv[0]); return 1; } if (NULL == (fp = fopen(argv[1], "r"))) { perror("fopen error"); return 1; } while (NULL != fgets(buf, BUFSIZE, fp)) { while (buf[strlen(buf)-1] == '\n' || buf[strlen(buf)-1] == '\r') { buf[strlen(buf)-1] = '\0'; } for (n = strlen(buf); n < WIDE; n++) { buf[n] = ' '; } buf[WIDE] = '\n'; buf[WIDE+1] = '\0'; fprintf(stdout, "%s", buf); } return 0; } ポイントは文字列の長さと改行コード'\n'と終端文字'\0'

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.3

質問の内容も、何をやりたいのかも、何故やりたいのかも、何がわからないのかも、 伝わってきません。 ひとつひとつ整理していってください。 ●目的。 ●理由。 ●わかっている事。 ●わからない事。 ●期待する動作。 ●現状どうなっているのか。 > 可変長から固定長 可変長、固定長と書かれていますが、何を指していますか? 可変長、固定長がどい言うものか理解していますか? > ある可変長のファイルがあって、 これは、何かのデータを格納してあるテキストファイルか何かですか? > レコード長を全て40にそろいたい どう言うファイルレイアウトを想像していますか? ファイル仕様書にはどう定義されていますか? > 実行してみたところ、全部40という長さになっていない、40超えるものも多数出ました。 どのようにして確認しましたか? > fprintfをつかったからだめですか? ファイルの書式によります。 ファイル仕様書にしたがってください。 > それともmalloc freeにする必要ありますか? 判断にあたいするだけの情報が提供されていないようです。 これでは、回答できません。 > まったく検討つかないです。 状況を整理する事からはじめてください。 わかっている事とわかっていない事の切り分けなど進めると、 もう少し有効的な質問が書ける様になるかと思います。 ●以下憶測で作成したサンプルプログラムです。 ---------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) {   char input_filename[] = "input.txt";   char output_filename[] = "output.bin";   FILE *pInputFile = NULL;   FILE *pOutputFile = NULL;   char inputBuffer[1024];   char editBuffer[40];   int editBufferLen = 0;      /*    * ●ファイルを開く    */   pInputFile = fopen(input_filename, "r");   if (pInputFile == NULL)   {     perror("入力ファイルを開けませんでした.");     exit(1);   }   pOutputFile = fopen(output_filename, "wb");   if (pOutputFile == NULL)   {     perror("出力ファイルを開けませんでした.");     fclose(pInputFile);     exit(1);   }      /*    * ●ファイルの行毎に処理するためのループ処理    * ファイル終端に達するまで、繰り返し処理する。    */   while (fgets(inputBuffer, sizeof(inputBuffer), pInputFile) != NULL)   {     /*      * ●1行毎の処理      */          sscanf(inputBuffer, "%s", editBuffer);  /* 行末の改行コードを除去 */     editBufferLen = strlen(editBuffer);     memset(editBuffer + editBufferLen, ' ', sizeof(editBuffer) - editBufferLen);     fwrite(editBuffer, 40, 1, pOutputFile);   }      /*    * ●ファイルを閉じる    */   fclose(pInputFile);   fclose(pOutputFile);      return 0; } ----------------------------------------------------------------------

回答No.2

あぁ。それ以前にlenの中身は変なのが入っているんじゃ。。。 それと、ついでなので、 コーディングスタイルとして、n のサイズはチェックした方がよいですね。

回答No.1

単純に、改行コードを出力していないからじゃないですか? fputs() を利用するか、fprintf(fpt,"%s\n", buf)としてみてください。 あと。strcat()は文字列の連結なので、memcpy()を利用した方がよいと思いますよ。

teakay84
質問者

お礼

ありがとうございます。memcpyで試してみたいと思います。

関連するQ&A

  • C言語 Segmentation fault

    program SPROGRAM 17 4 pas104 SIDENTIFIER 43 4 ( SLPAREN 33 4 上記のようなファイルを読みこんで、1行づつ各トークン(programとか17とか)を構造体に格納する関数reader()を作りましたが、これを以下のparser.cで呼びだすと「Segmentation fault(core dumped)」となってしまいます。gdbのrunコマンドでプログラムを実行すると、関数を呼び出す所で Program received signal SIGSEGV, Segmentation fault. 0x0040140f in reader () と表示されました。が,どうすればよいか全然分かりません・・・ どうすれば正しく動作してくれるのか、どなたか教えてください・・・ 以下ソース /*read.c*/ #include "head.h" void reader(void) { fprintf(stdout,"check"); char buf[BUF_LEN]; if (fgets(buf,sizeof(buf),fp) == NULL)/*ここで1行読みこむ*/ {/*いきなりNULLの場合*/ strcpy(t.str, ""); t.num = SEOF; t.line = 1; } else { 省略 } return; } /*parser.c*/ #include "head.h" struct tokenbox t; FILE *fp; int main(int argc, char *argv[]) { if (argc != 2)/*引数チェック*/ { fprintf(stderr,"Usage: (./parser) (file.ts)\n"); return -1; } int len; len = strlen(argv[1]);/*file.ts の長さ取得*/ if((argv[1][len-1] == 's') && (argv[1][len-2] =='t') && (argv[1][len-3] == '.'))/*tsファイルが指定されているかどうか*/ { fp = fopen(argv[1],"r");/*ファイルオープン*/ if (fp == NULL) { fprintf(stderr,"Such ts file is not exist\n"); return -1; } fprintf(stdout,"authenticate ts file!\n");//←これは出力される reader(); //←ここでSegmentation faultと思われる printf("t.str = %s\n", t.str); printf("t.str[0] = %c\n", t.str[0]); printf("t.num = %d\n", t.num); printf("t.line = %d\n", t.line); fclose(fp); return 0; } else { fprintf(stderr,"the file is not ts\n"); return -1; } } ヘッダファイル一部抜粋 /*head.h*/ #include <stdio.h> #include <string.h> #include <stdbool.h> #define BUF_LEN 128 #define TOKEN_LEN 128 struct tokenbox {/*tsファイルの各情報を格納する構造体*/ char str[TOKEN_LEN]; int num; int line; }; extern struct tokenbox t;/*構造体をtと置く*/ extern FILE *fp; /*ファイルポインタ*/

  • C言語の課題で困っています;

    C言語の課題で困ってます; 学校の課題で、キーボードから文字を入力する(最大80文字)。入力された文字列と、入力した文字列を逆順にした文字列を表示する。(malloc,freeを使って作成して下さい) ヒントで #invlude <stdio.h> void main(void){ char *buf; //入力文字列用 char *seq; //入力文字列用コピー用 char *rev; //逆順文字列用 int lec, i; buf =(char*)malloc(81); printf("文字列を入力:"); scanf("%s"buf ); for(i = 0; buf[i] ??? '\0'; i++){ } Ien = i; /* lenに文字列の長さが入る */ seq = ???(??? + 1); /* len+1文字文確保*/ for(i = 0; ???; i++){ seq[0] = buf[0]; } free(buf); rey = ???(len + 1); for(i = 0; < len; i++){ rev[len - i - 1] = seq[i]; } ren[i] ~ '\0'; printd("入力文字列 : %s\n",sep); でたんですが、全然分からなくて足りない部分の答えを教えてもらえると助かります;

  • C言語のプログラム(ポインタについて)

    /* コマンドライン引数で与えられた長い文字列を長さ10文字ずつに分割してp[100][11]に順番に入れ,表示するプログラム <例>./a.out 1234567890ABCDEFG p[1] = "1234567890" p[2] = "ABCDEFG" */ #include <stdio.h> int main(int argc, char **argv) { int i, len; char *str; len=0; for(i=1; i<argc; i++){ len += strlen(argv[i]); } if((str=(char *) malloc(len+1))==NULL){ perror("malloc"); exit(1); } strncpy(str,argv[1],10); for(i=2; i<argc; i++){ strcat(str,argv[i]); } printf("p[%d] = %s\n", i-1, str); } 上に示した処理をするプログラムを作成したいのですが、 今のソースは単に10文字表示するだけで、ここからどうしたらいいのか見当がつきません・・・・・。 なのでどういった改良をすればよいのか教えていただければ助かります。 /*配列aにファイルから値を読み込み、それを表示した後*/ /*配列に格納された値を下に1つずつずらして表示するプログラム(ポインタを使用して)を作成*/ /*(なお、一番上a[0]にはa[99]の値を入れる)*/ /*<例>*/ /*a[0] = 0 */ /*a[1] = 1 */ /*  ・ */ /*  ・ */ /*a[98] = 98*/ /*a[99] = 99*/ /*a[0] = 99 */ 1つずらしたもの /*a[1] = 0 */ /*  ・ */ /*  ・ */ /*a[98] = 97*/ /*a[99] = 98*/ (読み込むファイル[file-100.dat]には0~99の数字が1つずつ改行しながら入っています) できればこちらにも答えていただければ嬉しいです。 この問のソースは書きませんが、ファイルを配列に読み込んで表示してからの処理がいまいちわからず困っています。 すばやい御回答お待ちしております。よろしくお願いします。

  • C言語で分からない部分がいくつかあります。

    長文になります。 市のデータ(cities.txt)を対象として、以下の各機能を持ったプログラムを作成しました。 1.情報の登録と一覧表示 2.情報の削除 3.cities.txt からの情報の読み込み 4.citiesDB.txtへのリスト内容の書き出し 5.人口でソート #include <stdio.h> #include <stdlib.h> #include <string.h> #define STRLEN 32 #define BUF_LEN 128 #define CITYDB_R_FILE "cities.txt" // 読み込み用ファイル #define CITYDB_W_FILE "citiesDB.txt" // 書き出し用ファイル struct cities{ char pref[STRLEN]; char city[STRLEN]; int popl; float area; float dens; char founded[STRLEN]; struct cities *next; }; struct cities *root=NULL; // rootへのポインタは大域変数として定義 void *mymalloc(size_t sz){ void *p = (void *)malloc(sz); if(p == NULL){ fprintf(stderr,"ERR: Can't malloc memory %d bytes.",(int)sz); exit(1); } memset(p,0,sz); return p; } void showCity(struct cities *c, FILE *fp){ fprintf(fp,"%s\t%s\t%d\t%.2f\t%.2f\t%s\n", c->pref, c->city, c->popl, c->area, c->dens, c->founded); } struct cities *genNewCityCell(char *pref, char *city, int popl, float area, float dens, char *founded ){ struct cities *c; c = mymalloc(sizeof(struct cities)); // メモリを確保した c に対して、値を代入する return c; } void showList(FILE *fp){ struct cities *cur= root; while(cur != NULL){ showCity(cur,fp); cur = cur->next; } } void saveList(){ // 書き込み用のファイルを開き、そのファイルポインタ fp に対して、 // showList(fp) を呼ぶ。 void showList() は12行上で定義している printf("File saved to %s\n",CITYDB_W_FILE); } struct cities *line2City(char *buf){ struct cities *c=NULL; int popl; char pref[STRLEN], city[STRLEN], founded[STRLEN]; float area, dens; sscanf(buf, "%s %s %d %f %f %s", pref, city, &popl, &area, &dens, founded); c = genNewCityCell(pref,city,popl,area,dens,founded); return c; } void addCity(struct cities *c){ struct cities **cur= &root; /* rootから順にたどって,末尾に挿入する */ } void inputStr(char *buf,int len){ fgets(buf,len,stdin); buf[strlen(buf)-1]='\0'; } void addNewCity(){ char buf[BUF_LEN] = ""; struct cities *c; while(strlen(buf)<=0){ printf("Input one line:\n"); inputStr(buf, BUF_LEN); } if(strncmp(buf, "Prefecture", 10) == 0) return; c = line2City(buf); addCity(c); } void deleteCityFromList(char *delcity){ /* 順にたどり,当該項目を削除する. addCity() も同様. */ } void deleteCity(){ char buf[STRLEN]; showList(stdout); printf("Select Delete City Name:"); inputStr(buf, STRLEN); deleteCityFromList(buf); } void readListFILE(FILE *fp){ char buf[BUF_LEN]; struct cities *c; while( fgets(buf,BUF_LEN,fp) != NULL){ if(strncmp(buf, "Prefecture", 10) == 0) continue; c = line2City(buf); if(c != NULL) addCity(c); } } void readList(){ /* ファイルCITYDB_R_FILEを読み取り用で開く ファイルが開けない場合のエラー処理 readListFILE(fp); ファイルをクローズ */ printf("File loaded\n"); } void insertCityByPopl(struct cities *sc){ struct cities **cur= &root; /* 順にたどり、挿入すべき箇所に sc を挿入 */ } void sortList(){ struct cities *cur,*fr; cur = root; root = NULL; while(cur != NULL){ insertCityByPopl(genNewCityCell(cur->pref, cur->city, cur->popl, cur->area, cur->dens, cur->founded)); fr = cur; cur = cur->next; free(fr); } showList(stdout); } int main(int argc, char *argv[]){ char buf[BUF_LEN]; while(1){ printf("Menu(a:add, d:delete, l:list, s:sort, w:write file, r:read file q:quit):\n"); fgets(buf,BUF_LEN,stdin); switch(buf[0]){ case 'a': addNewCity(); break; case 'd': deleteCity(); break; case 'l': showList(stdout); break; case 's': sortList(); break; case 'w': saveList(); break; case 'r': readList(); break; case 'q': exit(0); break; } } } ただ、コメントのある部分の関数が完成できません・・・・ どなたか教えてください。

  • C言語に詳しい方お願い致しいます

    文字列Aから文字列Bを除いた結果を表示するプログラムなのですが 一ヶ所分からない部分があります。 #include <stdio.h> #include <string.h> int main(void){  char str1[] = "abcdefg";  char str2[] = "cde";  char str3[128] = "";  char *p1 = str1, *p2;  size_t len;  len = strlen(str2);  while((p2 = strstr(p1,str2)) != NULL) {   strncat(str3,p1,p2 - p1);   p1 = p2 + len;   printf("----\n");   printf("p2=%s\n", p2);   printf("str3=%s\n", str3);   printf("p1=%s\n", p1);  }  strcat(str3,p1);  printf("%s\n",str3);  return 0; } while文中の p1 = p2 + len; なのですが、何故これでp1の内容が「fg」になるのでしょう。

  • reallocについて

    現在、領域を拡張しながら、 ファイルを読み込んで呼び元に返却するPGを作成しています。 reallocがうまくいかないので、試しに小さいのを作って みましたが、これだとreallocの2度目で落ちます。 100文字ずつ呼んでいるので、拡張も100文字ずつ行っています。 メモリ確保に失敗なら、まだ分かるのですが、 ちょっと理由がわかりません。 reallocを複数繰り返していることも問題だと思いますが、 まずは正常に処理を流したいと考えています。 よろしくお願いします。 ~~~~~~ソース~~~~~~~~ //ファイルを読み込んでから領域を確保する #include <stdio.h> #include <string.h> #include <stdlib.h> #define BUFF 100 int main() { FILE *fp; char tmp[BUFF+1]; char *str; int len = 0; fp = fopen( "c:/test.txt" , "rb" ); if(fp ==0){ printf("ファイルがありません\n"); return -1; } //領域を初期化 str = (char *)malloc(1); memset(str,'\0',sizeof(str)); while(feof(fp)==0){ memset(tmp,'\0',sizeof(tmp)); fgets(tmp,BUFF,fp); //領域を再確保 len += BUFF+1; if(NULL == ((char *)realloc(str,len))){ printf("メモリ確保エラー"); } //読み込んだ値を変数に追加 strcat(str,tmp); } printf("文字列\n\n%s\n",str); printf("長さ:%d\n",len); fclose(fp); return 0; }

  • C言語の使い方を教えてください。-C言語入門者

    C言語のプログラムの処理の対象となるファイルはどこに保存したらよいのでしょうか?たとえば下記のプログラムで #include <stdio.h> #include <stdlib.h> #include <string.h> void main(void) { char *line[100], *buf; int i = 0, len, lines; FILE *fp; fp = fopen("textfile.txt", "r"); buf = calloc(128, sizeof(char)); while (i < 100 && fgets(buf, 128, fp) != NULL) { len = strlen(buf); line[i] = calloc(len + 1, sizeof(char)); strcpy(line[i], buf); i++; } fclose(fp); lines = ((i <= 100) ? i :100); free(buf); for(i = 0; i < lines; i++) printf("%s", line[i]); for(i = 0; i < lines; i++) free(line[i]); } で [textfile.txt]という名のファイルをマイドキュメントやコンパイラーを保存しているのと同じ領域に保存してコンパイラーを実行しても所要の結果が得られません。テキストにはプログラムの作り方しか書いてありません。

  • c言語 iconv

    msys環境で実行して,指定されたファイルの文字コードをShift-JISに変換して表示するコードを作成しているのですがうまく表示されません.何がいけないのでしょうか.第1引数に変換対象のファイル名,第2引数にファイルの文字コードを指定しています. #include <stdio.h> #include <string.h> #include <iconv.h> int main(int argc, char *argv[]) { iconv_t conv; char src[10000]; char dst[10000]; int src_len = strlen(src); int dst_len = sizeof(dst) - 1; char *buf_in; char *buf_out; FILE *fp; fp = fopen(argv[1], "r"); if(NULL == fp) { printf("ファイルを開けません\n"); } else { while(fgets(src, 10000, fp) != NULL) { buf_in = src; buf_out = dst; /* 変換器を作成 */ conv = iconv_open("Shift-JIS", argv[2]); /* 変換 */ iconv(conv, &buf_in, &src_len, &buf_out, &dst_len); *buf_out = '\0'; /* 終末処理 */ /* 文字コード後の文字列を表示 */ printf("%s\n", dst); } /* 変換器を終了 */ iconv_close(conv); /*ファイルを閉じる*/ fclose(fp); } return 0; }

  • C言語の関数の戻り値がおかしい?

    #include<stdio.h> #include<ctype.h> #include<stdlib.h> int get_word(char *buf,int buf_size,FILE *fp) { int len; int ch; while((ch = getc(fp)) != EOF && !isalnum(ch));/*→「英数字のとき」このループは飛ばす。*/ if(ch == EOF){/*もし英数字以外が入力されていたらメインプログラムにEOFを返す。*/ return EOF; } len = 0; do{ buf[len] = ch; len++; if(len >= buf_size){ fprintf(stderr,"word too long.\n"); exit(1); } }while((ch = getc(fp)) != EOF && isalnum(ch)); buf[len] = '\0'; return len; } int main(void) { char buf[256]; while(get_word(buf,256,stdin) != EOF){ printf("<<%s>>\n",buf); } return 0; } C言語ポインタ完全制覇という本のP67に載っていたプログラムをそのまま載せています。 get_word関数の中のif文で、EOFを返した時もループwhile(get_word(buf,256,stdin)により再入力するようなプログラムになっています。でも、「!=EOF」と記述されているのだから、EOFが返ったら終了だと思うのですが… なぜ再入力し続けるプログラム(無限ループ)になってしまっているのでしょうか? というか、私の環境で動作させたらおかしいだけじゃないでしょうか? よろしくお願いします。

  • C言語→C#に変換

    C言語→C#に変換 C言語からC#に変換したいのですが、わからないところがあります。 コマンドライン引数からファイル名とキーワードを入力して、キーワードがある行をアウトプットファイルに書き込むという処理です。 C言語のソースは、 main(int argc,char *argv[]){ FILE *fp; FILE *fpp; int i; char KEYWORD[256]; char buf[256]; //(1)アウトプットファイルのオープン fpp=fopen("output.txt","w"); for(i=1;i<argc-1;i++){ if(strcmp(argv[i],"-a")==0){ //(2)入力ファイルのオープン if((fp=fopen(argv[i],"r"))==NULL){ printf("open error!\n"); exit(1); } } //(3)キーワードの代入 if(strcmp(argv[i],"-b")==0){ strcpy(KEYWORD,argv[i]); } } //(4)一行読み込む while(fgets(buf,sizeof(buf),fp)!=NULL){ //(5)キーワードの条件で文字列抽出 if(strstr(buf,KEYWORD)!=NULL){ //(6)アウトプットファイルに出力 fprintf(fpp,"%s",buf); } } //ファイルクローズ fclose(fp); fclose(fpp); } です。 (3)キーワードの代入と、(5)文字列抽出の部分がネットなどで調べてもよくわかりません。 分かる方いらっしゃいましたら教えていただけると幸いです。 宜しくお願いします。 .

専門家に質問してみよう