- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试将扩展名为 .txt 的文件列表存储到我当前工作目录中的一个数组中。我已经把数组放在一起了,现在我只需要归还它。我是 C 的新手,我不习惯指针的情况。如何返回一个 char 指针数组?我创建了数组,并根据我在目录中找到的文本文件数量对其进行了分配。
当我尝试编译时遇到两个错误,这让我相信我对指针的理解不是我想的那样。我也一直在读到从函数返回时我的数组将被销毁,因为它在堆栈上。我不确定如何解决这个问题。欢迎任何帮助或批评。
// 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;
}
最佳答案
如果您希望 getTxtFilesInDir
返回一个字符串数组,它应该返回 char**
,而不是 char*
。
您也不需要将变量声明为static
。你声明一个变量在作为 static
的函数中,当您希望变量保持不变时函数的所有调用。在这种情况下,这可能不是您想要的做。
在不修改太多初始代码的情况下,您可以先分配内存一个字符串数组,然后在你有一个新条目时调整它的大小。在这个例子我马上就做了,因为 realloc(NULL, somesize)
和执行 malloc(somesize)
。这就是初始化 *tmp = 0
和txtFiles = NULL
,所以这个技巧有效。您还应该传递一个指向存储条目数的 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;
}
这里的重点是 1. 如何使用 realloc
扩展内存。然后它使用 malloc
为字符串分配内存。我在 txtFiles = tmp;
之前这样做,这样我就不必写很多 if(...==NULL)
。如果有事情发生沿途出错,该函数返回它已经拥有的所有文件名存储。
现在在 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;
}
我也想评论一下你原来的复制方式:
strncpy(txtFiles[i], dir->d_name, strlen(dir->d_name));
strncpy
在您想限制要复制的字节数时非常有用。在你的情况你已经分配了足够的内存,所以没有必要。和当你使用 strncpy
时,限制应该绑定(bind)到字节数可用于目的地,而不是源,否则您可能会复制更多比它应该的字节。在你的情况下,你不会得到有效的 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. Warning: If there is no null byte among the firstn
bytes ofsrc
, the string placed in dest will not be null-terminated.
当您使用 strncpy
时,您必须确保副本是有效的字符串自己设置 '\0'
终止字节。因为你分配了strlen(dir->d_name)+1
个字节的字符串:
strncpy(txtFiles[i], dir->d_name, strlen(dir->d_name));
textFiles[i][strlen(dir->d_name)] = 0;
此外,程序的退出值是一个无符号
值,范围从 0 到 255。在 main
中,您应该在出错时返回 1
而不是 -1
。
关于c - 如何将函数中的字符指针数组返回给 main?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48674280/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!