我之前已经问过这种形式的问题,但我很难找到适合我情况的问题。
当有人试图习惯C时,我遇到指针问题,特别是字符串。我有少量的错误不断出现,我无法绕过我一直在做错的事情。
我正在编写一个程序,它将读取用户名:密码键/值,然后将它们与给定值进行比较。为此,我使用userpass结构:
typedef struct {
char user[BUF_MAX];
char pass[BUF_MAX];
} userpass;
以下代码:
char *authThread(char *filename, char *request){
List_t logins;
char user[BUF_MAX];
char pass[BUF_MAX];
char *saveptr = NULL;
char *listptr = NULL;
char *username = strtok_r(request, ":", &saveptr);
char *password = strtok_r(NULL, ":", &saveptr);
char *failCode = malloc(sizeof (char)*BUF_MAX);
sprintf(failCode, "0:%s:0", username);
char *successCode = malloc(sizeof (char)*BUF_MAX);
sprintf(successCode, "1:%s:%s", username, ticketSecret);
if (List_init(&logins)){
//Retrieve all the user:pass pairs from the auth file
FILE *fp = fopen(filename, "r");
while(fscanf(fp, "%s:%s", user, pass) != EOF){
userpass new;
//PROBLEM LINES BELOW+++++++++++++++++++++++++++++++++
strcpy(new->user, user);
strcpy(new->pass, pass);
List_add_tail(&logins, &new);
}//while
fclose(fp);
//See if the username/pass combination provided exists in the auth file
for (;;){
userpass *next = NULL;
//PROBLEM LINE BELOW+++++++++++++++++++++++++++++++++
List_next_node(&logins, &listptr, &next);
if (next == NULL) break;
//Match found, return required auth string
if (strcmp(next->user, username) == 0 && strcmp(next->pass, password) == 0){
return successCode;
}//if
}//for
return failCode;
}//if
else{
printf("Error creating auth list\n");
}//else
}//authThread
List_t是一个链表实现。 List_next_node函数的标题是:
int List_next_node ( List_t *list, void **context, void **data );
我已经标记了两行,我在上面得到了一个错误。当我尝试编译时,我得到两个错误。在前两行,我得到:invalid type argument of â->â
。
第二行,我得到:passing argument 2(3) of âList_next_nodeâ from incompatible pointer type
我可以看到这两个问题都是由变量不正确的类型引起的,但我看不出这是怎么回事。在第一种情况下,new->user
应该是char数组,user
应该是。{/ p>
在第二种情况下,List_next_node接受三个参数;指向列表的指针,指向上下文指针的指针和指向数据指针的指针。据我所知,一切都应该是它的类型。我只能想象它是如何使用字符串(即字符数组)在C中工作的一些问题。
答案 0 :(得分:1)
new
在堆栈上本地声明。它不是指针,因此您需要更改
userpass new;
strcpy(new->user, user);
strcpy(new->pass, pass);
到
userpass new;
strcpy(new.user, user);
strcpy(new.pass, pass);
根据List_add_tail
的实施情况(我在你的问题中看不到),这可能不是唯一的问题。 new
返回后List_add_tail
超出范围,因此,除非向列表中添加项目需要副本,否则列表将留下指向可重用的内存的指针。
如果List_add_tail
未在其第二个参数中创建userpass*
的副本,则应将代码更改为
userpass* new = malloc(sizeof(*new));
strcpy(new->user, user);
strcpy(new->pass, pass);
List_add_tail(&logins, &new);
(请注意,在最后一个示例中,new
是指针,因此我们必须使用解除引用运算符->
再次访问其成员。)
答案 1 :(得分:1)
错误1
您已将变量new
定义为userpass结构,但您可以像指针一样访问其内部属性。
userpass new;
...
strcpy(new->user, user); // new->user is equivalent to (*new).user
strcpy(new->pass, pass);
相反,请使用.
运算符:
strcpy(new.user, user);
strcpy(new.pass, pass);
您应该动态分配您的userpass结构,以使它们不会超出范围。
错误2 (这是警告)
您的论据&listptr
的类型为char **
,但该函数期待void **
。您可以强制转换参数以删除警告:
List_next_node(&logins, (void **) &listptr, (void **) &next);
同样,&next
为userpass **
,期待void **