0

我知道以前有人问过这种形式的问题,但我很难找到适合我情况的问题。

作为试图习惯 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.

第二种情况,List_next_node接受三个参数;指向列表的指针、指向上下文指针的指针和指向数据指针的指针。据我所知,一切都是它应该的类型。我只能想象字符串(即字符数组)在 C 中的工作方式存在一些问题。

4

2 回答 2

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是一个指针,因此我们必须使用取消引用运算符->再次访问其成员。)

于 2013-06-11T00:01:35.370 回答
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);

您应该动态分配您的用户密码结构,以便它们不会超出范围。

错误 2(这是一个警告)

你的论点&listptr是类型char **,但函数是期待的void **。您可以强制转换参数以删除警告:

 List_next_node(&logins, (void **) &listptr, (void **) &next);

同样,&nextisuserpass **和 it 期待void **

于 2013-06-11T00:12:00.077 回答