1

C で記述されたシミュレーション プログラムがあり、乱数を作成して txt ファイルに書き込む必要があります。プログラムのみ停止 - 既に生成された乱数が再度生成されたとき、または - 10 億個の乱数が生成されたとき (繰り返しなし)

私の問題は、生成された long int 乱数を txt ファイルで検索できなかったことです! テキスト ファイルの形式は次のとおりです: 9875 764 19827 2332 ... どんな助けでも大歓迎です.. `

FILE * out;

int checkNumber(long int num){
    char line[512];
    long int number;  
    int result=0; 

    if((out = fopen("out.txt","r"))==NULL){
            result= 1;
    }

    char buf[10];
    itoa(num, buf, 10);


    while(fgets(line, 512, out) != NULL)
    {
       if((strstr(line,buf)) != NULL){
              result = 0;
       }
    }
    if(out) {
        fclose(out);
    } 
    return result;  
}


int main(){
    int seed;
    long int nRNs=0;
    long int numberGenerated;     
    out = fopen ("out.txt","w");

    nRNs=0;
    seed = 12345;

    srand (seed);  

    fprintf(out,"%d\n",numberGenerated);
    while( nRNs != 1000000000 )
    {
      numberGenerated = rand();
      nRNs++;

      if(checkNumber(numberGenerated)==0){
          fclose(out); break; system("pause"); 
      }
      else{
          fprintf(out,"%d\n",numberGenerated);
      }

    }    

    fclose(out);

}`

4

5 に答える 5

1

テキスト ファイルにスペースで区切られたランダムに生成された数字のみが含まれている場合は、strtok()関数 (Google でその使用法) が必要であり、@jackmigacz で言及されているようにバイナリ ツリー構造にスローします。ただし、どのような状況でも、少なくとも 1 回はファイル全体を検索する必要があります。次にftell()、ファイル内で検索した場所を取得する値。別の番号が生成されるfseek()と、最新の番号を取得するために使用できます。でデータを行ごとに取得することを忘れないでくださいfgets()

メモリ要件に注意し、malloc()慎重に使用してください

于 2012-11-28T10:49:57.297 に答える
0

これはうまくいくかもしれませんし、あなたはこのようにアプローチすることができます:(遅いですがうまくいくでしょう)

  int new_rand = rand();
    static int couter = 0;
    FILE *fptr = fopen("txt","a+");
    int i;
    char c,buf[10];
    while((c=getc(fptr))!=EOF)
    {
     buf[j++]=c;
     if(c == ' ')
       {
        buf[--j]='\0';
        i=atoi(buf);
        if(i == new_rand)
           return;
        j=0;
    }
    if(counter < 1000000)
   {
    fwrite(&new_rand, 4, 1, fptr);
    counter++;
   }
于 2012-11-28T11:00:52.737 に答える
0

ツリー(データ構造)で試してください。

于 2012-11-28T10:42:27.910 に答える
0

ファイルを開いてスキャンしないでくださいcheckNumber()。あなたは永遠に待っています。

代わりに、ビット セットデータ構造を使用して生成された数値をメモリに保持し、それを参照します。

ビット セットは、すべての 32 ビット整数を示すのに十分な大きさである必要があるため、2^32 / 8バイト (または512MiB) バイトのメモリを消費します。32-bit * 1,000,000,000これは多くのように見えるかもしれませんが、 ( )よりもはるかに小さいです4GB。また、チェックと更新の両方が一定時間で行われます。

編集: ウィキペディアのリンクはコーディング方法を説明するのにあまり役立たないので、ここに大まかなサンプルを示します: (これを書くより速い方法があります。たとえば、除算の代わりにビット シフトを使用しますが、これは理解しやすいはずです。 )

int checkNumberOrUpdate(char *bitSet, long int num){
    char b = 1 << (num % 8);
    char w = num / 8;

    if (bitSet[w] & ~b) {
        return 1;
    }
    bitSet[w] |= b;
    return 0;
}

メイン関数から適切なサイズにするbitSet必要があることに注意してください。calloc()

于 2012-11-28T11:04:09.570 に答える
0

毎回テキスト ファイルを直線的に検索するのは、非常に多くの数を処理するのに非常に時間がかかります。これまでに生成されたすべての数値をデータ構造に格納して、重複のバイナリ検索を実行できるようにすることができます。ただし、これには大量のRAMが必要になります。32 ビット整数を使用するシステムでは既に 4GB である 10 億の整数の場合、データ構造のオーバーヘッドのためにさらに数個必要になります。私の見積もりでは、最悪のシナリオ (実際には 10 億個の一意の整数になる) で約 16GB です。

メモリ モンスター マシンを持っていない場合は、代わりにデータ構造をバイナリ ファイルに書き込み、そこでバイナリ検索を実行する必要があります。それでもかなり遅くなりますが。

于 2012-11-28T10:49:13.123 に答える