Строки и указатели - PullRequest
       5

Строки и указатели

0 голосов
/ 16 марта 2011

У меня есть вопрос, связанный со строками и указателями.Пожалуйста, объясните только с программами C / C ++ ....

Существует файл, который содержит 1 слово в каждой строке.Я знал, что нет.слов, которые есть в файле.Пожалуйста, объясните с помощью небольшого кода, как я могу эффективно хранить эти слова в оперативной памяти.

Является fscanf(fp,"%s",word) & strcpy , единственным способом хранения слов в оперативной памяти ... другого эффективного алгоритма или логики нет.

Ответы [ 6 ]

3 голосов
/ 16 марта 2011

Вероятно, наиболее эффективный способ сделать это - прочитать весь файл в память за один блок (используйте fread). Затем выделите массив указателей, по одному на каждое слово. Затем просмотрите файл в памяти, изменив символы \n на \0 и сохранив указатель на символ после каждого \0 в вашем массиве.

Он эффективен, потому что он выполняет только одну операцию ввода-вывода, два выделения памяти и дважды перебирает символы в файле (один раз, чтобы скопировать их в буфер, и еще раз, чтобы разбить их на отдельные строки). Алгоритм, который вы описываете (fscanf и strcpy), будет выполнять много операций ввода-вывода, выделять память для каждого слова и циклически перебирать символы не менее трех раз (один раз для чтения в буфер, один раз для определения длины до выделить память и один раз скопировать из буфера в выделенную память).

Вот простая версия без проверки ошибок:

char* buffer; // pointer to memory that will store the file
char** words; // pointer to memory that will store the word pointers

// pass in FILE, length of file, and number of words
void readfile(FILE *file, int len, int wordcnt)
{
    // allocate memory for the whole file
    buffer = (char*) malloc(sizeof(char) * len);
    // read in the file as a single block
    fread(buffer, 1, size, file);

    // allocate memory for the word list
    words = (char**) malloc(sizeof(char*) * wordcnt);
    int found = 1, // flag indicating if we found a word
                   // (starts at 1 because the file begins with a word)
        curword = 0; // index of current word in the word list

    // create a pointer to the beginning of the buffer
    // and advance it until we hit the end of the buffer
    for (char* ptr = buffer; ptr < buffer + len; ptr++)
    {
        // if ptr points to the beginning of a word, add it to our list
        if (found)
            words[curword++] = ptr;
        // see if the current char in the buffer is a newline
        found = *ptr == '\n';
        // if we just found a newline, convert it to a NUL
        if (found)
            *ptr = '\0';
    }
}

Вот немного более простая версия с использованием strtok:

char* buffer;
char** words;

void readfile(FILE *file, int len, int wordcnt)
{
    buffer = (char*) malloc(sizeof(char) * len);
    fread(buffer, 1, size, file);
    buffer[len] = '\0';

    words = (char**) malloc(sizeof(char*) * wordcnt);
    int curword = 0;
    char* ptr = strtok(buffer, "\n");
    while (ptr != NULL)
    {
        words[curword++] = ptr;
        ptr = strtok(NULL, "\n");
    }
}

Обратите внимание, что в приведенных выше двух примерах предполагается, что последнее слово в файле заканчивается новой строкой!

1 голос
/ 16 марта 2011

Вы можете прочитать весь файл в блок памяти, затем пройтись по блоку, заменив каждый '\ r' или '\ n' на 0. Теперь вы можете восстановить все строки, просто выполнив поиск в блоке символы, следующие сразу за одним или несколькими нулями. Это примерно так же эффективно, как вы собираетесь получить. Теперь, если вам также нужен быстрый доступ, вы можете выделить другой блок указателей и установить каждый из них так, чтобы он указывал на начало строки. Все еще более эффективно, чем блок указателей, каждый из которых указывает на отдельно выделенную строку.

0 голосов
/ 16 марта 2011

Вот быстрый и грязный способ сделать это, не проверяя ошибки, используя static mem и fgets.

#define MAX_NUM_WORDS   10
#define MAX_LEN 128

void get_words(char *p_file, char *words)
{
  FILE *f;

  f = fopen(p_file, "r");
  while (fgets(words, MAX_LEN, f))
    words += MAX_LEN+1;

  fclose(f); 
}

main()
{
  char word_array[MAX_NUM_WORDS][MAX_LEN+1];
  int i;

  get_words("words.txt", word_array);

  for (i=0; i<MAX_NUM_WORDS; i++)
    printf("Word: %s", word_array[i]);
}
0 голосов
/ 16 марта 2011

С тех пор, как вы процитировали - «Пожалуйста, объясните только с помощью программ на C / C ++ ....» легко использовать вектор, содержащий строку - std::vector< std::string >

std::string word;

std::vector < std::string > readWords ;  // A vector to hold the read words.

ifstream myfile ("fileToRead.txt");
if (myfile.is_open())
{
    while ( myfile.good() )
    {
       getline (myfile,word);  // This gets you the first word get copied to line.
       readWords.push_back(word) ; // Each read word is being copied to the vector
    }
    myfile.close();
}

Все прочитанные слова копируются в вектор readWords, вы можете просмотреть его, чтобы увидеть, что они на самом деле.

0 голосов
/ 16 марта 2011

Почему strcpy? Просто fscanf прямо в целевую память.

0 голосов
/ 16 марта 2011

Если вы хотите, чтобы ваши строки не использовали лишние неиспользуемые байты, сделайте следующее:

char * * array=new char*[COUNT_OF_WORDS];


fscanf(fp,"%s",word);
int len=strlen(word);
array[i]=new char[len+1];
strcpy(array[i],word);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...