アプリ版:「スタンプのみでお礼する」機能のリリースについて

windows7 64bitでcygwinを使用しています。

32bitを1つの組として、いくつかの組で構成されたバイナリデータがあります。
このバイナリデータにいくつの組があるのか調べるため、以下のようなソースを記述したのですが、うまくいきません。
どこを修正すればよろしいでしょうか。
御教授願います。


int main()
{
long long int i;
long long int hex[1];
long long int aaaa;
int bb;
int ret;
FILE * fp;
i = 1;
bb = 1;
for(;;){
fp = fopen("kimi.dat", "r");
bb = fread(&hex[1],4,i,fp);
aaaa = i;
i = aaaa + 1;
ret = fclose(fp);
if (bb != aaaa) {
printf("%lld\n",aaaa);
printf("%lld\n",i);
printf("%d\n",bb);
exit(1);
}
}
}

gcc -std=c99でコンパイルしました。
結果は
1431440333
1431440334
1
のように表示されました。

データファイルは900MB以上あります。

A 回答 (5件)

forループ内で毎回ファイルオープンクローズを繰り返し


都度先頭からファイルを読もうとしているコードになっています
まともに動かしたいならhexのデータサイズはファイルサイズ分確保する必要があります
    それ(データいくつ書かれてるか)求めるために書いてるコードとしては
    本末転倒だし効率も悪いものとなっています

このままだともメモリ破壊しまくります(現状破壊されてるから処理が終わってる)
(実行環境によって結果は不定となります)

long long int hex[1]; を unsigned char hex[4];
bb = fread(&hex[1],4,i,fp); を bb = fread(&hex[0],4,1,fp);
if (bb != aaaa) {   を  if (bb != 1) {
に変更

for(;;){
fp = fopen("kimi.dat", "r");
の部分を
fp = fopen("kimi.dat", "rb");
for(;;){
に入れ替え(&ちょっと変更)

ret = fclose(fp);
if (bb != aaaa) {
の部分を
if (bb != 1) {
ret = fclose(fp);
に入れ替えればとりあえずはまともに
動くような気はする(※ 未確認)

ファイルサイズ求めて4で割るだけでもいい気がしました
    • good
    • 0

脱出方法を明記していない無限ループの中で、毎回ファイルをオープンクローズしていいのでしょうか。

    • good
    • 0

単純に32bit型の値がファイルに何個含まれているか見るだけなら、こういう方法もあると思いますが、そういうわけにいかないんですよね?


% ls -l kimi.dat
-rwxr-xr-x 1 me mycomputer 900000000 Jan 1 1980 kimi.dat

% expr 900000000 / 4

それとも、32bitデータが連続して詰まっているファイルがあって、そのデータの出現回数を調べてますか?
そうすると、こんなプログラムになりますでしょうか?
#include <err.h>
#include <errno.h>
#include <sys/types.h>
#include <db.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
DB *db;
DBT key, value;
FILE *fp;
uint32_t data, counter;

/* Use memory database instead of making own hashmap */
db = dbopen(NULL, O_RDWR|O_CREAT, 0700, DB_HASH, NULL);

fp = fopen(argv[1], "r");
if (fp == NULL) {
err(errno, "fopen");
}
while (!feof(fp) && fread(&data, sizeof(data), 1, fp) == 1) {
key.data = &data;
key.size = sizeof(data);
if (db->get(db, &key, &value, 0) == 0) {
counter = *((uint32_t*)value.data);
} else {
counter = 0; /* suspect no entry */
}
counter++;
value.data = &counter;
value.size = sizeof(counter);
db->put(db, &key, &value, 0);
}
fclose(fp);

/* print elements in the DB one by one */
while (db->seq(db, &key, &value, R_NEXT) == 0) {
printf("0x%x: %ld\n", *((uint32_t*)key.data), *((uint32_t*)value
.data));
}
db->close(db);

return 0;
}

自分でhashを作るのは面倒なのでBerkeleyDBを使いましたが...
    • good
    • 0

全部ですね。



ロジックもムチャクチャだし。
Cも変だ、1から勉強し直した方が良さそうだ。
    • good
    • 0

何がどう「うまくいかない」のかは知らないが, ロジックが謎.


fread の使い方もおかしいし, それ以前にポインタまわりがダメダメ.
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!