• ベストアンサー

ファイル操作について。

noname#11476の回答

  • ベストアンサー
noname#11476
noname#11476
回答No.1

ファイルの中身はどんな場合でもただの1byte単位の数字の羅列にすぎません。 そこには型の情報はありません。 2byteで一文字というのは読み出して使うプログラム側で管理する必要があります。 根本的な勘違いは、fgetc の働きにあります。 fgetc はファイルから 1byte(1文字ではない)を取り出すという関数でしかありません。2byteとってることはしないと言うことです。 戻り値はintですが、この時点ではまだ「文字」として扱っているわけではありません。 int(これが2byteでも4byteでも同じで)の変数の中に1byteの数字を入れているだけです。 だから、charに型キャストするんです。このキャストで上位バイトは捨てられます。 マルチバイト文字を扱うのでしたら、fgetwcという関数があります。こちらは1文字拾ってきてくれます。 (返す値は wint_t 型になります)

Nickee
質問者

お礼

よくわかりました。fgetwcについても勉強させてもらいます。(m__m) ありがとうございました。

関連するQ&A

  • int型のchar型への代入について

    VC++6.0のfgetcのヘルプに以下のようなコードが有りました。 int型のchをcharのbuffer[i]に代入するということに違和感を感じたのですが、 1.このようにする必要性とは何なのでしょうか? 2.このような代入により具体的には何が行われているのでしょうか? 3.そもそも1文字とりだすfgetcの戻り値がcharでなくintなのはなぜ? 質問が漠然としていて申し訳ありませんが、お願いします。  FILE *stream; char buffer[81]; int ch; 省略   stream = fopen( "fgetc.c", "r" )) 省略 ch = fgetc( stream ); 省略 buffer[i] = ch;

  • fgetc()関数の動作について

    Visual Studio 2008(C++) において↓のようなコードを書いてビルドして、デバッグなしで実行すると、 コンソール上でちゃんとファイルの文字がコンソールに表示されます。 ところで、fgetc()関数のリファレンスを見ると、戻り値がint型を返すと書いてあるのに、 このコードだとchar型のバッファで受けています。char型でもfgetc() 関数の戻り値を受けられる理由がわかりません。 これはやはり、fgetc()がShift-JISコードの文字コード番号そのものを返しているのでしょうか。 (int型の配列で各要素にfgetc()の戻り値をみると、ファイル上の文字の文字コード番号が 入っています。) char型で受けると、文字そのものを受けられるのでしょうか? また、char型で受けた時に、char(1バイト)で、EOF(2バイト)をどうやって格納し、識別しているの でしょうか。 初歩的な質問で申し訳ありませんが、ご回答、よろしくお願いします。 #include <iostream> using namespace std; int main(){ FILE *fin = fopen("testa.txt", "r"); if(!fin){ "入力ファイルをオープンできません。"; return 1; } int i=0; char buf[20]; while((buf[i] = fgetc(fin))!=EOF){ i++; } buf[i]='\0'; cout << buf << endl; return 0; }

  • 文字列操作

    テキストを読みこんで、そのテキストにある単語を抽出するプログラムを作ろうとしています。単語の区切り文字はスペースかタブで、1文字ずつ読みこんで行こうともいます。 しかし、1文字ずつ読みこむ関数fgetcは返値がint型のようです。1文字ずつよみこみながら読みこんだ文字がスペースかタブで無いか見たいのですが、fgetcのint型返り値をchar文字列と比較するにはどうしたら良いでしょうか。

  • C言語のビットフィールドについて

    はじめまして,今C言語を勉強中なのですが, ビットフィールドの宣言について質問があります。 勉強に使用しているテキストでは, ビットフィールドの宣言にはunsigned int型を使用すると書かれています(下記例参照)。 ここで質問は,unsigned charなどの型は推奨されない理由があるのか,ということです。 実際にunsigned char型で実行してもプログラムは動きますし,そちらのほうが語長も短くて済むのでいいような気がします。 テキストの書き方だと,他の型について言及していなかったので,なにか理由かあるのか,それとも特に問題ないのか,疑問に思っています。 わかる方いましたら,回答いただけると嬉しいです。 (ex) struct{ unsigned int bit0:1; unsigned int bit1:1; : unsigned int bit7:1; }bits;

  • バイナリデータのファイル

    FILE *stream1; if( (stream1 = fopen( argv[2], "rb" )) == NULL ) printf( "Can not open plane text file.\n"); /////////////////////////////////////////////////////////////////// // 平文 fseek(stream1, 0, SEEK_END); long filelen = ftell(stream1); fseek(stream1,0,0); int head = sizeof(long); mesLength = filelen + head; int baseByte = kk / 8 + ((kk % 8)?1:0); // 鍵バイト長 int mesByte = baseByte - 1; // 処理単位バイト数(暗号化ではbyte減らしておく) //暗号化 if(mesLength <= mesByte*20){//63が暗号化の作業サイズ *20= bufp = (char*)new(char[filelen +1+ int(kk/8 + 2)+head]); if(bufp == NULL){ cout << "No Memory" <<"\n"; cout.flush(); return(-1); } // 平文 *(long *)bufp = filelen; int i = head; do{ c = fgetc(stream1); bufp[i]=c; i=i+1; }while(c!=EOF); bufp[i-1]=NULL; for(int j=0; j<(kk/8+2); j++){ bufp[j+i] = NULL; } mesLength = i-1; // 平文長(バイト) + head 上のように、古い形でファイルを扱っています。 wchar_t を基本にプログラムを書き換えようとしていますが、 ファイルの扱いで、上記の部分と似たような扱いがしやすいのは、 _wfopen CreateFile の、どちらでしょうか? バイナリファイルが扱いやすいもの、8ビットごとの操作が可能なものを探しています。 それとも、あきらめて古いままのほうが良いのでしょうか? よろしくご指導下さい。

  • ファイル操作

    あるファイルから長さの違った数字や文字を読み込んで配列に格納したいのですが数字などの長さが違うとなんかおかしくなってしまいます; 例えば 1 a 1 2 a 2 3 b 3 4 b 4 などのファイルはできるのですが 0 1 2 3 a 3 4 b 4 5 c 5 の場合5つの配列に格納したいのです。1行目で1つ2行目で1つ3行目の 左、真ん中、右の数字でそれぞれ1つづつ格納したいのです。 それで自分でやったのですが typedef struct path{ int left [100]; int right[100]; char center [100]; }Path; int main(int argc,char *argv[]) { FILE *fp; Path path; int i=0; int first; int second[100]; fp = fopen(argv[1],"r"); while(fscanf(fp,"%d %c %d",&path.left[i],&path.center[i],&path.right[i])==3){ i++; } fclose(fp); このようにやると3行目からはきちんとよみこむのですが1、2行目がうまくできません@@; firstとsecondのそれぞれ1、2行目を入れたいのです。 fscanfをもう1つ増やすしてもやってみましたがうまくいきませんでした。 ちなみにfscanf関数のところをならったばかりです。 fgetcとかそのようなのを使うのでしょうか?(よくわからないですけど) よろしくお願いします。ちなみにLinuxでgcc、C言語です。

  • waveファイルの8bitデータの調整

    VS2003.NET/C++でプログラミングをしています。 今、WAVEファイルで音声データを取って、フェードを掛けようと思うのですが、8bitだと上手くいきません。  16bitの場合は、2byte分読み込み、それから小数で割っているんですが、8bitの場合、1byteに左チャネル、2byte目には右チャンネルといった形で格納されているはずなんですがそのようにしても上手くいきません。  上手くいった16bitデータの音量調整を下記に載せておきます。 8bitにするにはどうしたらいいでしょうか? int nMeter; <- 音量を100分割で表す int nSize; <- データのサイズ LPBYTE lpData1; <- 相手の音声 LPBYTE lpData2; <- 音声を加工 // サイズ分を加工 for( int i = 0; i < nSize; i+=2 ) { // 16bit なので 2BYTEずつ確保 char n1 = (char)( lpData1[ i + 0 ] ); char n2 = (char)( lpData1[ i + 1 ] ); // nMeter で音量調整(倍率をかける) int n = (int)( (float)( ( n2 << 8 ) | ( n1 & 0xFF ) ) * (float)( nMeter / 100.0f ) ); // 加工済みデータを保存 lpData2[ i + 0 ] = ( n & 0x00FF ) >> 0; lpData2[ i + 1 ] = ( n & 0xFF00 ) >> 8; } 上手くいってない8bit版は次の通りです int nMeter; <- 音量を100分割で表す int nSize; <- データのサイズ LPBYTE lpData1; <- 相手の音声 LPBYTE lpData2; <- 音声を加工 // サイズ分を加工 for( int i = 0; i < nSize; i+=4 ) { // 16bit なので 2BYTEずつ確保 char n1 = (char)( lpData1[ i + 0 ] ); char n2 = (char)( lpData1[ i + 1 ] ); n1 -= 128; n1 * (int)(bMeter / 100.0); n2 * (int)(bMeter / 100.0); n1 += 128; n2 += 128; // 加工済みデータを保存 lpData2[ i + 0 ] = n1; lpData2[ i + 1 ] = n2; } よろしくお願いします。

  • テキストファイルの変換なのですが

    課題でドラックアンドドロップされたファイルの文書の全角カタカナを半角カタカナに変換するというソフトが思うとおりに動きません。 ご協力をお願いします。 ファイルの文字コードはS-jisです。 ドラックアンドドロップをしてテキストファイルを読み込むところまではうまくいきました。 テキストファイルを1バイトずつ読み込んで、全角カタカナの領域である「0x83」の判定を読み込むことはできるのですが、それ以降がうまくいきません。 テキストファイルの文字列に関するアドレスに関する知識不足だとは思うのですが、考えても分かりません。 以下に、コードを載せさせていただきますので解決だけでなく改良もあれば教えてください。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <mbstring.h> #define BYTE unsigned char char *getStrTailPoint(char *); char *getDotPoint(char *,char *); char* changeCode(int); void StringCat2(char *, char *); void main(int argc,char** argv ) { //tail…パス+ファイル名のENDポイントアドレス //dot…拡張子のポイントアドレス char *tail ; char *dot; //bfp…BaseFilePointAddress //mfp…MakedFilePointAddress FILE *bfp,*mfp; //makedFileName…作られるファイルの名前 char makedFileName[1000]; static int i; //ファイルからの文字を格納する一時格納する変数 char *r,tmp[3]; int p; BYTE q; if(argv[1]!=NULL){ // argv[1]…ドラックアンドドロップされたファイルとパスが格納 //ファイルを開く if(NULL ==(bfp=fopen(argv[1],"r"))) { printf("指定されたファイルを開けません"); getchar(); exit(1); } tail = getStrTailPoint(argv[1]); dot = getDotPoint(argv[1],tail); //makeFileNameに"."までの元の名前を格納 for(i = 0;&argv[1][i]<=dot;i++){ if(&argv[1][i]<dot){ makedFileName[i]=argv[1][i]; }else{ makedFileName[i]='\0'; } } //makeFileNameに"__"と拡張子を挿入 strcat(makedFileName,"__"); strcat(makedFileName,dot); //新規ファイルの作成 if(NULL ==(mfp=fopen(makedFileName,"w"))){ printf("新規ファイルを作れません"); getchar(); exit(1); } //既存ファイルから新規ファイルにテキストをコピー //新規ファイルの全角文字を半角文字へ while((p = fgetc(bfp)) != EOF) { q=(BYTE)p; if(0x83==q){ /*r=changeCode(p); fputs(r,mfp); break;*/ fputc('2',mfp); continue; } fputc(p,mfp); } //ファイルを閉じる fclose(bfp); fclose(mfp); } return ; } /* *getStrTailPoint   *文字列のENDポイントアドレスを調べる関数 */ char *getStrTailPoint(char *string){ char *p; int i ; int len = strlen(string); for(i=0;i<=len+1;i++){ if(*string=='\0'){ p=string; return p; } string++; } return string; } /* *getDotPoint *ファイルの拡張子の名前が始まるポイントアドレスを検出する関数 */ char *getDotPoint(char *string,char *tail){ char *p; int i; int len = strlen(string); for(i=0;i<len;i++){ if(*tail=='.'){ p=tail; return p; } tail--; } return tail; } char* changeCode(int ch){ char p[3]; char *zenkaku ={"アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ\0"}; char *hankaku ={"アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョ\0"}; char *hankaku2 ={"カキクケコサシスセソタチツテト"}; char *hankaku3 ={"ハヒフヘホ"}; char *dakutenn ={"゛゜"}; do{ if(*zenkaku<='ョ'||ch==*zenkaku){ p[0]=*hankaku; p[1]='\0'; return p; break; }else if(ch==*zenkaku){ if(*zenkaku<='ド'){

  • C++でcsvファイルから文字列を取得するのに

    C++でcsvファイルから文字列を取得するというものを作っているのですが、うまく取り出すことができません。ファイルはオープンできて、文字列にも分けられているのだとは思うのですが、どこのデータを表示させても"1aa"としか表示されません。なにも格納されていない所は"1aa"とは表示されず空白ですが。 以下に取り出す際使用しているコードを記載するので、うまい具合にいくアドバイスがありましたらお願いします。 ↓で格納させる場所を作っています。 typedef struct { char* Input; char* Output; char* AddName; char* Path; char* LED; int VS; char* Title; char* Copy; } csvdata_t; csvdata_t csvdata[100]として別の場所で宣言してます ↓この関数で格納させています void loadData(){     FILE *fp;    fp = fopen(csvTitle,"r");//ここでのファイルパスは通っています    int n,num,i;        int input[1024]; char inputc[1024]; for(i = 0; i < 1; i++)//最初の1行読み飛ばす while(fgetc(fp) != '\n'); n = 0; num = 0; while(1){ for(i = 0;i < 64; i++){ inputc[i] = input[i];// = fgetc(fp);//1文字取得する input[i] = fgetc(fp); if(inputc[i] == '/'){//スラッシュがあれば while(fgetc(fp) != '\n');//改行までループ i = -1;//カウンタを最初に戻して continue; } if(input[i] == ',' || input[i] == '\n'){//カンマか改行なら inputc[i] = '\0';//そこまでを文字列とし break; } if(input[i] == EOF){//ファイルの終わりなら goto EXFILE;//終了 } } switch(num){ case 0: csvdata[n].Input = inputc;break; case 1: csvdata[n].Output = inputc;break; case 2: csvdata[n].AddName = inputc;break; case 3: csvdata[n].Path = inputc;break; case 4: csvdata[n].LED = inputc;break; case 5: csvdata[n].VS = atoi(inputc);break; case 6: csvdata[n].Title = inputc;break; case 7: csvdata[n].Copy = inputc;break; case 8: break; } num++; if(num == 9){//9まできたら num = 0;//0に戻す n++;//次の行へ } } EXFILE: fclose(fp); }

  • 変数 および ポインタのサイズ(バイト数)について

    sizeof演算子を使ってchar int float double型のバイト数を調べると、char 型については1バイトと決まっていて、int float doubleについては2から8バイト(処理系によって違う)なのは理解できます。しかし、char* int* float* double*型(ポインタ型)のバイト数は2から4バイトになるのが多いとおもいますが、どういう理由でポインタ型のバイト数が決まるのか、その理由をお教え願いたく思います。16ビットcpuあるいは32ビットcpuと言うハードの影響なのかそれとも何かソフトによるのか、その理由を知りたいと思います。なお私の処理系ではポインタは全て4バイトになっています。特に不思議に思うのはchar型は1バイトなのに、char*型が4バイトになっていることです。 宜しく願います。