Reputation: 275
I know questions of this form have been asked before, but I'm having difficulty finding one that suits my situation.
As someone trying to get used to C, I'm having issues with pointers, specifically Strings. I have a small number of errors that keep cropping up, and I can't wrap my head around what I keep doing wrong.
I'm writing a program that will read username:password key/values and then compare them against given values. For that, I use a userpass struct:
typedef struct {
char user[BUF_MAX];
char pass[BUF_MAX];
} userpass;
And the following code:
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 is a linked list implementation. The header of the List_next_node function is this:
int List_next_node ( List_t *list, void **context, void **data );
I've labelled the two lines where I get an error above. When I try to compile, I get two errors. On the first two lines, I get: invalid type argument of â->â
.
One the second line, I get: passing argument 2(3) of âList_next_nodeâ from incompatible pointer type
I can see that both of these issues are caused by variables not being the correct type, but I can't see how that's possible. In the first case, new->user
should be a char array, as should user
.
In the second case, List_next_node accepts three parameters; a pointer to a list, a pointer to a context pointer, and a pointer to a data pointer. As far as I can tell, everything is the type it should be. I can only imagine it's some problem with how Strings (i.e. char arrays) work in C.
Upvotes: 0
Views: 573
Reputation: 1284
Error 1
You have defined the variable new
as a userpass structure yet you access its internal attributes like a pointer.
userpass new;
...
strcpy(new->user, user); // new->user is equivalent to (*new).user
strcpy(new->pass, pass);
Instead, use the .
operator:
strcpy(new.user, user);
strcpy(new.pass, pass);
You should dynamically allocate your userpass structures so that they do not go out of scope.
Error 2 (It's a warning)
Your argument &listptr
is of type char **
yet the function is expecting void **
. You can cast the argument to remove the warning:
List_next_node(&logins, (void **) &listptr, (void **) &next);
Similarly, &next
is userpass **
and it is expecting void **
Upvotes: 1
Reputation: 42175
new
is declared locally on the stack. It is not a pointer so you need to change
userpass new;
strcpy(new->user, user);
strcpy(new->pass, pass);
to
userpass new;
strcpy(new.user, user);
strcpy(new.pass, pass);
Depending on the implementation of List_add_tail
(I can't see it in your question), this may not be the only problem. new
goes out of scope after List_add_tail
returns so, unless adding an item to the list takes a copy, the list will be left with a pointer to memory that is liable to be reused.
If List_add_tail
doesn't create a copy of the userpass*
in its second argument, you should change your code to something like
userpass* new = malloc(sizeof(*new));
strcpy(new->user, user);
strcpy(new->pass, pass);
List_add_tail(&logins, &new);
(Note that in this last example, new
is a pointer so we have to use the dereference operator ->
to access its members again.)
Upvotes: 1