Вероятно, наиболее эффективный способ сделать это - прочитать весь файл в память за один блок (используйте 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");
}
}
Обратите внимание, что в приведенных выше двух примерах предполагается, что последнее слово в файле заканчивается новой строкой!