[英]Strings & Pointers
我有一個與字符串和指針有關的問題。 請僅使用C / C ++程序進行解釋。
有一個文件,每行包含一個單詞。 我知道沒有。 文件中的單詞數。 請在小代碼的幫助下說明如何將這些字有效地存儲在RAM中。
是fscanf(fp,"%s",word) & strcpy
,是將單詞存儲在RAM中的唯一方法。沒有其他有效的算法或邏輯可用。
謝謝。
可能最有效的方法是將整個文件讀入一個塊中的內存(使用fread
)。 然后分配一個指針數組,每個單詞一個。 然后遍歷內存中的文件,將\\n
字符更改為\\0
,並將指針存儲在數組中每個\\0
之后的指針。
它之所以有效是因為它僅執行一次I / O操作,兩次內存分配,並在文件中的字符上循環兩次(一次將它們復制到緩沖區,再一次將它們分解為單獨的字符串)。 您描述的算法( fscanf
和strcpy
)將執行許多I / O操作,為每個單詞分配內存,並至少循環遍歷字符3次(一次讀入緩沖區,一次查找要為其分配內存的長度,並一次從緩沖區復制到分配的內存中)。
這是一個沒有錯誤檢查的簡單版本:
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");
}
}
請注意,以上兩個示例假定文件中的最后一個單詞以換行符結尾!
您可以將整個文件讀入一個內存塊,然后遍歷該塊,將每個'\\ r'或'\\ n'替換為0。現在,您只需在該塊中搜索緊隨其后的字符即可恢復所有字符串一個或多個0。 這與您將獲得的空間效率差不多。 現在,如果您還想快速訪問,則可以分配另一個指針塊,並將每個指針塊設置為指向字符串的開頭。 比每個指向單獨分配的String的指針塊還要高效。
如果您希望您的字符串不消耗額外的未使用字節,請執行以下操作:
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);
為什么要strcpy
? 只需將fscanf直接插入目標內存即可。
既然如此,您引用了“僅使用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
,您可以對其進行迭代以查看它們的實際含義。
這是一種快速而骯臟的方法,無需進行錯誤檢查,使用靜態內存和使用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]);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.