0

テキスト ファイルからランダムな行を選択して結果を出力する方法として、このコードを少し前に取り上げました。残念ながら、選択した行の最初の文字しか出力しないようで、その理由や修正方法がわかりません。どんな助けでも大歓迎です。

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
using namespace std;

#define MAX_STRING_SIZE 1000

string firstName()
{
    string firstName;
    char str[MAX_STRING_SIZE], pick[MAX_STRING_SIZE];
    FILE *fp;
    int readCount = 0;

    fp = fopen("firstnames.txt", "r");
    if (fp)
    {
        if (fgets(pick, MAX_STRING_SIZE, fp) != NULL)
        {
            readCount = 1;
            while (fgets (str, MAX_STRING_SIZE, fp) != NULL)
            {
                if ((rand() % ++readCount) == 0)
                {
                    strcpy(pick, str);
                }
            }
        }
    }
    fclose(fp);
    firstName = *pick;
    return firstName;
}

int main() 
{
    srand(time(NULL));

    int n = 1;
    while (n < 10)
    {
        string fn = firstName();
        cout << fn << endl;
        ++n;
    }

    system("pause");
}
4

2 に答える 2

2
 firstName = *pick;

これが問題だと思います。

pickここでは、本質的に配列の最初の要素へのポインターであるchar*ため、もちろん*pickタイプはchar.. または配列の最初の文字です。

それを見る別の方法は、*pick == *(pick +0) == pick[0]

それを修正するにはいくつかの方法があります。最も簡単なのは、以下を実行することです。

return pick;

コンストラクターは自動的に変換を行います。

于 2013-01-27T14:47:51.103 に答える
0

ファイルの形式を指定しなかったので、固定レコード長と可変レコード長の両方のケースについて説明します。各テキスト行がレコードであると仮定します。

ランダムな名前の読み取り、固定長レコード

これは簡単です。

  1. 必要なレコードのインデックス (ランダム) を決定します。
  2. ファイル位置 = レコード長 * インデックスを計算します。
  3. ファイルをその位置に設定します。
  4. を使用して、ファイルからテキストを読み取りますstd::getline

ランダムな名前の読み取り、可変長レコード

これは、テキスト行の長さが異なることを前提としています。それらは異なるため、数学を使用してファイルの位置を決定することはできません。

ファイルから行をランダムに選択するには、各行をコンテナーに入れるか、行の先頭のファイル オフセットをコンテナーに入れる必要があります。

コンテナーを確立したら、ランダムな名前番号を決定し、それをコンテナーへのインデックスとして使用します。ファイルのオフセットを保存した場合は、ファイルをオフセットに配置し、行を読み取ります。それ以外の場合は、コンテナーからテキストをプルします。

どのコンテナを使用する必要がありますか? 場合によります。テキストの保存は高速ですが、メモリを消費します (基本的にファイルをメモリに保存します)。ファイルの位置を保存するとスペースが少なくなりますが、各行を 2 回読み取ることになります (位置を見つけるために 1 回、データを取得するために 2 回目)。

これらのアルゴリズムの拡張は、ファイルをメモリ マップすることです。これは読者の課題です。

編集 1: 例

include <iostream>
#include <fstream>
#include <vector>
#include <string>

using std::string;
using std::vector;
using std::fstream;

// Create a container for the file positions.
std::vector< std::streampos > file_positions;

// Create a container for the text lines
std::vector< std::string > text_lines;

// Load both containers.
// The number of lines is the size of either vector.
void
Load_Containers(std::ifstream& inp)
{
  std::string    text_line;
  std::streampos file_pos;
  file_pos = inp.tellg();
  while (!std::getline(inp, text_line)
  {
    file_positions.push_back(file_pos);
    file_pos = inp.tellg();
    text_lines.push_back(text_line);
  }
}
于 2013-01-27T17:39:20.223 に答える