#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
//読み取るファイルのサイズを取得する関数
int GetFileSize( const char* FileName )
{
fpos_t fsize;
//ファイルポインタの位置を初めから終わりにすることでサイズを取得している
FILE *fp = fopen( FileName, "r" );
fseek( fp, 0, SEEK_END );
fgetpos( fp, &fsize );
fclose( fp );
return (int)fsize;
}
//数字を取得してポインタを進める関数
char* NumGet( char* pMozi, int* pNum )
{
char* pcurrent = pMozi;
char cNum[1024];
int i = 0;
//空白か改行かファイルの終わりまで繰り返す
while( *pcurrent != ' ' && *pcurrent != '\n' && *pcurrent != '\0' ){
cNum[i] = *pcurrent;
i++;
pcurrent++;
}
cNum[i] = '\0';
//charをint変換し、引数のpNumにぶちこむ
*pNum = atoi( cNum );
//空白か改行を指しているの次の数字にポインタがさすようにする
pcurrent += 1;
return pcurrent;
}
//入力されたファイルを二次元配列としてそれぞれ代入していく関数
char* InputFileNumGet( int** Gyouretu, char* pStart, int Gyousuu )
{
int i, j;
int Gnum;
//正方行列の初めを指すようにする
char* pcurrent = pStart;
//行分繰り返す
for( i = 0; i < Gyousuu; i++ ){
//列文繰り返す
for( j = 0; j < Gyousuu; j++ ){
//要素の数字を一つ取得する
pcurrent = NumGet( pcurrent, &Gnum );
//二次配列に取得した値をぶちこむ
Gyouretu[i][j] = Gnum;
}
}
//進んだ分のポインタを返す
return pcurrent;
}
//行列の掛け算を行う関数
//例 a[行][列]
int SumKeisan( int** a, int** b, int yoko, int tate,int Gyousuu )
{
int sum = 0, i;
//行数ぶん繰り返す
for( i = 0; i < Gyousuu; i++ ){
//一つ目の行列では行は変化しないため固定、同様に2つ目の行列は列が変わらないため固定
sum += a[yoko][i] * b[i][tate];
}
return sum;
}
//二次元配列を動的に確保する関数
int** NizigenAlloc(int Gyousuu)
{
int** ppNizi;
int i;
int* base_matrix;
//行数ぶんまず確保する
ppNizi = ( int** )malloc( Gyousuu * sizeof(int* ) );
//行ごとにそれぞれの列を確保していく
base_matrix = ( int* )malloc( sizeof(int) * Gyousuu * Gyousuu );
for( i = 0; i < Gyousuu; i++ ){
ppNizi[i] = base_matrix + Gyousuu * i;
}
return ppNizi;
}
//計算結果を二次配列に確保する関数
int** OutPutKekkaGet( int** ppGyouretuA, int** ppGyouretuB, int** Output, int Gyousuu )
{
int i, j;
//出力する配列
int** ppKekka = Output;
//入力ファイルの行列より計算したものをひとつづつ代入していく
for( i = 0; i < Gyousuu; i++ ){
for( j = 0; j < Gyousuu; j++ ){
ppKekka[i][j] = SumKeisan( ppGyouretuA, ppGyouretuB, i, j, Gyousuu );
}
}
return ppKekka;
}
//計算結果をファイルに書き込む関数
void FileKekkaWrite( FILE* fp, int** ppKekka, int Gyousuu )
{
char cHazime[64], dummy[126];//cWriteData[102400];
int i, j, cnt;
char* pMozi, cWriteData[102400];
sprintf( cHazime, "%d\n\n", Gyousuu );
//行数変わらないので先に書き込む
fwrite( cHazime, strlen( cHazime ), 1, fp );
cWriteData[0] = '\0';
//行数ぶん繰り返す
for( i = 0; i < Gyousuu; i++ ){
//列ぶん繰り返す
for( j = 0; j < Gyousuu; j++ ){
//桁数取得し、その分allocする
cnt = sprintf(dummy, "%d",ppKekka[i][j]);
pMozi = ( char* )malloc( sizeof(char) * cnt + 1 );
//最後の場合は改行、それ以外は空白を入れてあげる
if( j != Gyousuu - 1 ){
sprintf( pMozi, "%d ", ppKekka[i][j] );
}
else{
sprintf( pMozi, "%d\n", ppKekka[i][j] );
}
//書き込みしてfree
fwrite( pMozi, strlen( pMozi ), 1, fp );
free( pMozi );
pMozi = NULL;
}
}
}
int main(int argc, char **argv)
{
fsize;
char *filename;
FILE *fp;
int i = 0;
int Gyousuu;
// int fsize;
char cGnum[16];
char* pstart = NULL, *pcurrent = NULL;
struct timeval tv1, tv2;
if (argc != 3) {
fprintf(stderr, "Usage: %s filename\n", argv[0]), exit(1);
}
filename = argv[1];
if ((fp = fopen(filename, "r")) == NULL) {
perror("fRopen"), exit(1);
}
//ファイルサイズを取得する
fsize = GetFileSize( filename );
//動的領域の確保
pstart = ( char * )malloc( sizeof( char ) * fsize );
//ファイルごと確保したポインタに読み込ませる
fread( pstart, fsize, 1, fp );
pcurrent = pstart;
//文字は読み込んだので用済み
fclose(fp);
//行数を取得する
while( *pcurrent != '\n' ){
cGnum[i] = *pcurrent;
i++;
pcurrent++;
}
cGnum[i] = '\0';
//改行二つ分飛ばして初めの行列にポインタを指すようにする
for( i = 0; i < 2; i++ ){
pcurrent = strstr( pcurrent, "\n");
pcurrent++;
}
Gyousuu = atoi( cGnum );
//順に確保するのは入力ファイルの行列二つと計算結果の行列
int** ppGyouretuA = NizigenAlloc(Gyousuu );
int** ppGyouretuB = NizigenAlloc(Gyousuu);
int** ppKekka = NizigenAlloc(Gyousuu);
//一個目の行列を確保した配列に代入していく
pcurrent = InputFileNumGet( ppGyouretuA, pcurrent, Gyousuu );
//二個目の行列にポインタがさすようにする
pcurrent = strstr( pcurrent, "\n" );
pcurrent++;
//二個目も一個目と同様
pcurrent = InputFileNumGet( ppGyouretuB, pcurrent, Gyousuu );
//計算タイマースタート
printf("start!\n");
gettimeofday(&tv1, NULL);
//行列の掛け算を計算し配列に代入していく
ppKekka = OutPutKekkaGet( ppGyouretuA, ppGyouretuB, ppKekka, Gyousuu );
gettimeofday(&tv2, NULL);
printf("finish!\n");
fprintf(stderr, "Time: %ld msec.\n",
(tv2.tv_sec - tv1.tv_sec) * 1000
+ (tv2.tv_usec - tv1.tv_usec) / 1000);
filename = argv[2];
remove( filename );
if ((fp = fopen(filename, "w")) == NULL) {
perror("fWopen"), exit(1);
}
//ファイルに計算結果を書き込んでいく
FileKekkaWrite( fp, ppKekka, Gyousuu );
fclose( fp );
//領域を解放する
free( pstart );
free( ppGyouretuA[0] );
free( ppGyouretuA );
free( ppGyouretuB[0] );
free( ppGyouretuB );
free( ppKekka[0] );
free( ppKekka );
return 0;
}
]
fpos_tのキャストができません
-
- 記事: 2
- 登録日時: 10年前
fpos_tのキャストができません
行列の掛け算を計算して、ファイルに出力するプログラムを実行してみたのですが、fpos_tという型のfsize(最初の方のです)がint にキャストできないとエラーが出てしまいました。どうすればいいのかがわからないので、わかる方いましたら、教えていただけますでしょうか。
Re: fpos_tのキャストができません
fpos_tがどのように定義されているかは開発環境に依存します。
例えば、整数で定義されているのであればキャスト出来るでしょうが、構造体で定義されている場合はキャストできません。
あなたが使用されている開発環境で、fpos_tがどのように定義されているかをヘッダファイルから調べてみてください。
例えば、整数で定義されているのであればキャスト出来るでしょうが、構造体で定義されている場合はキャストできません。
あなたが使用されている開発環境で、fpos_tがどのように定義されているかをヘッダファイルから調べてみてください。
Re: fpos_tのキャストができません
こういうときはfgetposではなくてftellをつかうのが定石ではないでしょうか。
とは言えftellを使うときはバイナリモードで開くべきで、バイナリモードとテキストモードが混在することになってよろしくないです。
fgetsで読み込んだ分だけ処理していくほうが汎用性は高いと思います。
一行分を一気に読み込むことを前提にできるならそうして、改行まで読み込めなかったらエラーにすれば良いですし。
とは言えftellを使うときはバイナリモードで開くべきで、バイナリモードとテキストモードが混在することになってよろしくないです。
fgetsで読み込んだ分だけ処理していくほうが汎用性は高いと思います。
一行分を一気に読み込むことを前提にできるならそうして、改行まで読み込めなかったらエラーにすれば良いですし。
-
- 記事: 2
- 登録日時: 10年前
Re: fpos_tのキャストができません
MoonGateさん、ISLe()さん、ありがとうございます。
なんとか解決できました!
なんとか解決できました!