使用这个C代码,我想用readdir
函数返回的每个不同文本文件中解析的单词填充一个动态char数组。
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
char *getWord(FILE *fp){
char word[100];
int ch, i=0;
while(EOF!=(ch=fgetc(fp)) && !isalpha(ch))
;//skip
if(ch == EOF)
return NULL;
do{
word[i++] = tolower(ch);
}while(EOF!=(ch=fgetc(fp)) && isalpha(ch));
word[i]=' ';
return strdup(word);
}
int readWords(const char * fn,char ** arr){
char *word;
FILE * fp;
int size=0;
//read first time to get the number of words
fp=fopen(fn,"r");
while(word=getWord(fp)){
size++;
}
fclose(fp);
printf("size:%dn",size);
arr = (char **) malloc (size * sizeof (char *));
//reopen to insert in dynamic array
fp=fopen(fn,"r");
for (int i = 0; i < size; i++){
arr[i] = (char *) malloc (100 * sizeof (char));
word=getWord(fp);
// printf("%s",word);
strcpy(arr[i],word);
}
fclose(fp);
return size;
}
int main(int narg, char *arg[] )
{
struct dirent *de; // Pointer for directory entry
char absdir[256];
char absfn[256];
FILE * F;
int s;
// opendir() returns a pointer of DIR type.
DIR *dr = opendir(arg[1]);
strcpy(absdir,arg[1]);
strcat(absdir,"/");
if (dr == NULL) // opendir returns NULL if couldn't open directory
{
printf("Could not open current directory" );
return 0;
}
while ((de = readdir(dr)) != NULL){
if (de->d_type!=4){ // is file?
strcpy(absfn,absdir);
strcat(absfn,de->d_name);
printf("abs_fn:%s n",absfn);
char** arr_words;
s=readWords(absfn,&arr_words);
printf("%s number of words:%dn", absfn,s);
for (int i=0;i<s;i++)
printf("word %d:%sn",i,arr_words[i]);
//free 2D array
for(int i=0;i<s;i++)
free(arr_words[i]);
free(arr_words);
}
}
closedir(dr);
return 0;
}
使用getWord
可以很好地解析单词,但我找不到在参数中填充char **arr passed
并在主函数中稍后使用它的解决方案。我想用以下形式动态地分配char **arr_words
arr_words[0]=First word of file text
arr_words[1]=Second word
arr_words[s-1]=Last Word
Readword
函数返回在每个文件中读取的字数。
你的bug是这里描述的一个更高级的问题:动态内存访问只能在函数
内部工作arr
是一个局部变量。它是指向指针数组中的第一个指针的指针。为了将它返回给main(现在抓紧了),你的函数需要将一个指向指针的指针传递给指针数组…
中的第一个指针。或者在普通C语言中,可怕的三星编程,char***
。但这实际上是它的一种有效用法,大约是存在的三层间接性的唯一有效用法。
或者,您可以只使用char**
的返回,而跳过这个额外的间接级别,这可能更具可读性。
使用哪种形式有点主观,但您需要将函数更改为以下形式之一:
int readWords(const char * fn, char*** arr)
{
...
*arr = malloc (size * sizeof (char *))
...
}
或
char** readWords(const char * fn, int* wordsRead)
{
...
arr = malloc (size * sizeof (char *));
...
*wordsRead = size;
return arr;
}
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
char *getWord(FILE *fp){
char word[100];
int ch, i=0;
while(EOF!=(ch=fgetc(fp)) && !isalpha(ch))
;//skip
if(ch == EOF)
return NULL;
do{
word[i++] = tolower(ch);
}while(EOF!=(ch=fgetc(fp)) && isalpha(ch));
word[i]=' ';
return strdup(word);
}
char** readWords(const char * fn,int *wordsRead){
char *word;
char**arr;
FILE * fp;
int size=0;
//read first time to get the number of words
fp=fopen(fn,"r");
while(word=getWord(fp)){
size++;
}
fclose(fp);
printf("size:%dn",size);
arr = malloc (size * sizeof (char *));
//reopen to insert in dynamic array
fp=fopen(fn,"r");
for (int i = 0; i < size; i++){
arr[i] = (char *) malloc (100 * sizeof (char));
word=getWord(fp);
// printf("%s",word);
strcpy(arr[i],word);
}
fclose(fp);
*wordsRead = size;
return arr;
}
int main(int narg, char *arg[] )
{
struct dirent *de; // Pointer for directory entry
char absdir[256];
char absfn[256];
FILE * F;
int s;
int wordsRead;
char buffer[100];
// opendir() returns a pointer of DIR type.
DIR *dr = opendir(arg[1]);
strcpy(absdir,arg[1]);
strcat(absdir,"/");
if (dr == NULL) // opendir returns NULL if couldn't open directory
{
printf("Could not open current directory" );
return 0;
}
while ((de = readdir(dr)) != NULL){
if (de->d_type!=4){ // is file?
strcpy(absfn,absdir);
strcat(absfn,de->d_name);
printf("abs_fn:%s n",absfn);
char **arr_words;
arr_words=readWords(absfn,&wordsRead);
printf("%s number of words:%dn", absfn,wordsRead);
for (int i=0;i<wordsRead;i++){
printf("word %d:%sn",i,arr_words[i]);
}
//free array of pointers
for(int i=0;i<s;i++)
free(arr_words[i]);
free(arr_words);
}
}
closedir(dr);
return 0;
}