[英]How to return an array of character pointers from a function back to main?
I'm trying to store a list of files with a .txt extension into an array from my current working directory.我正在尝试将具有 .txt 扩展名的文件列表存储到我当前工作目录中的数组中。 I've gotten as far as getting the array together, now I just need to return it.
我已经把数组放在一起了,现在我只需要返回它。 I'm new to C and I'm not used to the pointer situation.
我是 C 新手,不习惯指针情况。 How can I return an array of char pointers?
如何返回一个字符指针数组? I have the array created, and its allocated based on how many Text files I find in the directory.
我创建了数组,并根据我在目录中找到的文本文件数量进行分配。
I'm getting two errors when I try to compile which leads me to believe that my understanding of pointers is not what I thought it was.当我尝试编译时遇到两个错误,这让我相信我对指针的理解与我想象的不同。 I also have been reading that my array will be destroyed when returning from the function, because it is on the stack.
我也一直读到我的数组在从函数返回时会被销毁,因为它在堆栈上。 I'm not sure how to fix that.
我不知道如何解决这个问题。 Any help or criticism would be welcome.
欢迎任何帮助或批评。
// prototypes
char* getLine();
void replaceWord();
char * getTxtFilesInDir(char*);
bool isTxt(char *);
int main(int argc, char **argv) {
// Check to see if correct number of arguments is given
if (argc < 4) {
printf("ERROR: Not enough parameters supplied. Please supply a find,"
"replace, and prefix parameter and try again.\n");
return -1;
}
// Initialize variables
char *find, *replace, *prefix;
find=argv[1];
replace=argv[2];
prefix=argv[3];
char cd[1024];
// Get the Current working directory to grab files
if (getcwd(cd, sizeof(cd)) != NULL) {
printf("Current working dir is: %s\n", cd);
} else {
perror("getcwd() error");
}
// Get the values of the arguments
printf("Value of find: %s\nValue of replace: %s\nValue of prefix: %s\n",
find, replace, prefix);
// create an array of the files that are valid
char* files = getTxtFilesInDir(cd);
return 0;
}
char* getTxtFilesInDir(char* directory) {
DIR *d;
struct dirent *dir;
d = opendir(directory);
int n=0, i=0;
// get the number of text files in the directory
if (d) {
while((dir = readdir(d)) != NULL) {
if (isTxt(dir->d_name)) {
n++;
}
}
}
rewinddir(d);
// Create the array of text files depending on the size
static char* txtFiles[n];
// add the text files to the array
if (d) {
printf("Found: \n");
while ((dir = readdir(d)) != NULL)
{
if (isTxt(dir->d_name)) {
printf("%s\n", dir->d_name);
txtFiles[i]= (char*) malloc (strlen(dir->d_name)+1);
strncpy(txtFiles[i], dir->d_name, strlen(dir->d_name));
i++;
}
}
closedir(d);
}
return txtFiles;
}
bool isTxt(char *file) {
size_t len = strlen(file);
return len > 4 && strcmp(file + len -4, ".txt") == 0;
}
If you want that getTxtFilesInDir
returns an array of strings, it should return a char**
, not a char*
.如果您希望
getTxtFilesInDir
返回一个字符串数组,它应该返回一个char**
,而不是一个char*
。
Also you don't need to declare the variable as static
.此外,您不需要将变量声明为
static
。 You declare a variable in a function as static
, when you want that the variable remains the same for all calls of the function.当您希望该变量对于函数的所有调用保持相同时,您可以将函数中的变量声明为
static
。 In this case this is probably not what you want to do.在这种情况下,这可能不是您想要做的。
Without modifying too much of your initial code, you can first allocate memory for an arrray of strings, and then resize it when you've got a new entry.无需修改太多初始代码,您可以先为一组字符串分配内存,然后在有新条目时调整其大小。 In this example I do that at once, because
realloc(NULL, somesize)
is the same as doing malloc(somesize)
.在本例中,我立即执行此操作,因为
realloc(NULL, somesize)
与执行malloc(somesize)
。 That's why it's important to initialize *tmp = 0
and txtFiles = NULL
, so this trick works.这就是为什么初始化
*tmp = 0
和txtFiles = NULL
很重要,所以这个技巧有效。 You should also pass a pointer to an size_t
where you store the number of entries:您还应该传递一个指向
size_t
的指针,您可以在其中存储条目数:
char **getTxtFilesInDir(const char* directory, size_t *len) {
if(directory == NULL || len == NULL)
return NULL;
...
*len = 0;
char **txtFiles = NULL, **tmp;
char *str;
if (d) {
printf("Found: \n");
while ((dir = readdir(d)) != NULL)
{
if (isTxt(dir->d_name))
{
tmp = realloc(txtFiles, (len+1) * sizeof *textFiles);
if(tmp == NULL)
return txtFiles; // return what you've got so far
str = malloc(strlen(dir->d_name) + 1);
if(str == NULL)
{
if(txtFiles == NULL) // first time, free everything
{
free(tmp);
return NULL;
}
return tmp; // return all you've got so far
}
strcpy(str, dir->d_name); // no need of strcnpy, you've allocated
// enough memory
txtFiles = tmp;
txtFiles[(*len)++] = tmp;
}
}
closedir(d);
return txtFiles;
}
The important bits here is 1. how you expand the memory with realloc
.这里的重要部分是 1. 如何使用
realloc
扩展内存。 Then it allocates memory for the string using malloc
.然后它使用
malloc
为字符串分配内存。 I do that before txtFiles = tmp;
我在
txtFiles = tmp;
之前这样做了, so that I don't have to write to many if(...==NULL)
. ,这样我就不必写很多
if(...==NULL)
。 If something goes wrong along the way, the function returns all the file names it already has stored.如果在此过程中出现问题,该函数将返回它已经存储的所有文件名。
Now in main
you do:现在
main
你做:
int main(int argc, char **argv)
{
...
size_t len = 0;
char **files = getTxtFilesInDir(cd, &len);
if(file == NULL)
{
fprintf(stderr, "No files found\n");
return 1;
}
for(size_t i = 0; i < len; ++i)
printf("file: %s\n", files[i]);
// freeing memory
for(size_t i = 0; i < len; ++i)
free(files[i]);
free(files);
return 0;
}
I also want to comment on your orginal way of copying:我还想评论一下您的原始复制方式:
strncpy(txtFiles[i], dir->d_name, strlen(dir->d_name));
strncpy
is great when you want to limit the number of bytes to be copied.当您想限制要复制的字节数时,
strncpy
非常strncpy
。 In your case you've already allocated enough memory, so there is no need to.在您的情况下,您已经分配了足够的内存,因此无需分配。 And when you use
strncpy
, the limit should be bound to the number of bytes available to the destination, not the source, otherwise you might copy more bytes than it should.并且当您使用
strncpy
,限制应绑定到目标可用的字节数,而不是源可用的字节数,否则您复制的字节数可能会多于应有的字节数。 In your case you won't get a valid c-string, because you are limiting to copy to the lenth of dir->d_name
, so the '\\0'
-terminating won't be copied.在您的情况下,您将无法获得有效的 c 字符串,因为您只能复制到
dir->d_name
的长度,因此不会复制'\\0'
终止。
man strcpy
男人
#include <string.h> char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n);
[...]
[...]
The
strncpy()
function is similar, except that at mostn
bytes ofsrc
are copied.strncpy()
函数类似,除了最多复制src
n
个字节。 Warning: If there is no null byte among the firstn
bytes ofsrc
, the string placed in dest will not be null-terminated.警告:如果
src
的前n
个字节中没有空字节,则放置在 dest 中的字符串不会以空值结尾。
When you use strncpy
you must make sure that the copy is a valid string by setting the '\\0'
-terminating byte yourself.当您使用
strncpy
您必须通过自己设置'\\0'
终止字节来确保副本是有效的字符串。 Because you've allocated strlen(dir->d_name)+1
bytes for the string:因为您已经为字符串分配了
strlen(dir->d_name)+1
个字节:
strncpy(txtFiles[i], dir->d_name, strlen(dir->d_name));
textFiles[i][strlen(dir->d_name)] = 0;
Also the exit value of a program is a unsigned
value, it goes from 0 to 255. In main
you should return 1
instead of -1
on error.此外,程序的退出值是一个
unsigned
值,它从 0 到 255。在main
您应该在出错时返回1
而不是-1
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.