gpt4 book ai didi

c 编程 - 从 ‘void*’ 到“record_s*”的无效转换

转载 作者:行者123 更新时间:2023-11-30 16:23:57 25 4
gpt4 key购买 nike

我从 StackOverflow 获得了代码。我在 GCC 下用 raspbian 编译我的代码。我的文件的扩展名是cpp。当我编译代码时,出现以下错误: 我提到,如果有任何有用的代码可以以最快和最正确的方式列出给定路径和给定深度中的所有文件和目录,我将不胜感激。我认为这段代码可以以正确且快速的方式索引文件和文件夹。当您回答这个问题时,请提供完整的代码和 raspbian 的编译命令。

 error: invalid conversion from ‘void*’ to ‘record_s* {aka main(int, const char**)::record_s*}’ [-fpermissive]
pos = malloc(sizeof(*pos) + strlen(argv[1]) + 2);
~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cpp_list_directory.cpp:125:55: error: ‘struct dirent’ has no member named ‘d_namlen’; did you mean ‘d_name’?
item = malloc(sizeof(*item) + pos->len + entry->d_namlen + 2);
^~~~~~~~
cpp_list_directory.cpp:127:37: error: ‘struct dirent’ has no member named ‘d_namlen’; did you mean ‘d_name’?
item->len = pos->len + entry->d_namlen;
^~~~~~~~
cpp_list_directory.cpp:129:59: error: ‘struct dirent’ has no member named ‘d_namlen’; did you mean ‘d_name’?
memcpy(item->name + pos->len, entry->d_name, entry->d_namlen);

我的代码是:

#include <dirent.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

int main(int argc, char const *argv[]) {
/* print use instruction unless a folder name was given */
if (argc < 2)
fprintf(stderr,
"\nuse:\n"
" %s <directory>\n"
"for example:\n"
" %s ./\n\n",
argv[0], argv[0]),
exit(0);

/*************** a small linked list macro implementation ***************/

typedef struct list_s {
struct list_s *next;
struct list_s *prev;
} list_s;

#define LIST_INIT(name) \
{ .next = &name, .prev = &name }

#define LIST_PUSH(dest, node) \
do { \
(node)->next = (dest)->next; \
(node)->prev = (dest); \
(node)->next->prev = (node); \
(dest)->next = (node); \
} while (0);

#define LIST_POP(list, var) \
if ((list)->next == (list)) { \
var = NULL; \
} else { \
var = (list)->next; \
(list)->next = var->next; \
var->next->prev = var->prev; \
}

/*************** a record (file / folder) item type ***************/

typedef struct record_s {
/* this is a flat processing queue. */
list_s queue;
/* this will list all queued and processed folders (cyclic protection) */
list_s folders;
/* this will list all the completed items (siblings and such) */
list_s list;
/* unique ID */
ino_t ino;
/* name length */
size_t len;
/* name string */
char name[];
} record_s;

/* take a list_s pointer and convert it to the record_s pointer */
#define NODE2RECORD(node, list_name) \
((record_s *)(((uintptr_t)(node)) - \
((uintptr_t) & ((record_s *)0)->list_name)))

/* initializes a new record */
#define RECORD_INIT(name) \
(record_s){.queue = LIST_INIT((name).queue), \
.folders = LIST_INIT((name).folders), \
.list = LIST_INIT((name).list)}

/*************** the actual code ***************/

record_s records = RECORD_INIT(records);
record_s *pos, *item;
list_s *tmp;
DIR *dir;
struct dirent *entry;

/* initialize the root folder record and add it to the queue */
pos = malloc(sizeof(*pos) + strlen(argv[1]) + 2);
*pos = RECORD_INIT(*pos);
pos->len = strlen(argv[1]);
memcpy(pos->name, argv[1], pos->len);
if (pos->name[pos->len - 1] != '/')
pos->name[pos->len++] = '/';
pos->name[pos->len] = 0;
/* push to queue, but also push to list (first item processed) */
LIST_PUSH(&records.queue, &pos->queue);
LIST_PUSH(&records.list, &pos->list);

/* as long as the queue has items to be processed, do so */
while (records.queue.next != &records.queue) {
/* pop queued item */
LIST_POP(&records.queue, tmp);
/* collect record to process */
pos = NODE2RECORD(tmp, queue);
/* add record to the processed folder list */
LIST_PUSH(&records.folders, &pos->folders);

/* process the folder and add all folder data to current list */
dir = opendir(pos->name);
if (!dir)
continue;

while ((entry = readdir(dir)) != NULL) {

/* create new item, copying it's path data and unique ID */
item = malloc(sizeof(*item) + pos->len + entry->d_namlen + 2);
*item = RECORD_INIT(*item);
item->len = pos->len + entry->d_namlen;
memcpy(item->name, pos->name, pos->len);
memcpy(item->name + pos->len, entry->d_name, entry->d_namlen);
item->name[item->len] = 0;
item->ino = entry->d_ino;
/* add item to the list, right after the `pos` item */
LIST_PUSH(&pos->list, &item->list);

/* unless it's a folder, we're done. */
if (entry->d_type != DT_DIR)
continue;

/* test for '.' and '..' */
if (entry->d_name[0] == '.' &&
(entry->d_name[1] == 0 ||
(entry->d_name[1] == '.' && entry->d_name[2] == 0)))
continue;

/* add folder marker */
item->name[item->len++] = '/';
item->name[item->len] = 0;

/* test for cyclic processing */
list_s *t = records.folders.next;
while (t != &records.folders) {
if (NODE2RECORD(t, folders)->ino == item->ino) {
/* we already processed this folder! */
break; /* this breaks from the small loop... */
}
t = t->next;
}
if (t != &records.folders)
continue; /* if we broke from the small loop, entry is done */

/* item is a new folder, add to queue */
LIST_PUSH(&records.queue, &item->queue);
}
closedir(dir);
}

/*************** Printing the results and cleaning up ***************/
while (records.list.next != &records.list) {
/* pop list item */
LIST_POP(&records.list, tmp);
/* collect record to process */
pos = NODE2RECORD(tmp, list);
/* prepare for next iteration */
LIST_POP(&records.list, tmp);
fwrite(pos->name, pos->len, 1, stderr);
fwrite("\n", 1, 1, stderr);
free(pos);
}
return 0;
}

我使用以下命令在 gcc 中编译代码:

g++ -Wall cpp_list_directory.cpp -o cpp_list_directory

最佳答案

编译器告诉您(在您的平台上)字段:d_namelen未在struct dirent中实现

这是struct dirent的定义

struct dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[1];
};

但是您的代码可以通过以下方式获取文件名的长度:

DIR *directoryEntry;
size_t length = strlen( directoryEntry->d_name );

有关 void* 等的消息是由于您使用 C++ 造成的。 (那么为什么问题上的 c 标签而不是 c++

关于c 编程 - 从 ‘void*’ 到“record_s*”的无效转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53777254/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com