malloc + fgets динамическое выделение

Это мой код:

int main(int argc, char *argv[]){
    FILE *fp;
    char *tmp, *tmp2, *user, *pass, *line;
    printf("Inserire utente: "); scanf("%ms", &user); /* scanf %ms alloca dinamicamente la memoria */
    printf("Inserire password: "); scanf("%ms", &pass);
    line = malloc((strlen(user)+strlen(pass)) * sizeof(char)); /* DUBBIOOOOOOOOOO */
    fp = fopen("/home/pol/auth.txt", "r");
    if(fp == NULL){
        printf("Errore apertura file\n");
        return EXIT_FAILURE;
    }
    while(!feof(fp)){
        fgets(line, /* E QUI?? */ , fp);
        tmp = strtok(line, " ");
        tmp2 = strtok(NULL, "\n"); /* con fgets ultimo carattere è \n (se pwd=12 => 12\n) quindi devo tagliare prima di \n */
        if((strcmp(tmp,user) == 0) && (strcmp(tmp2,pass) == 0)){
            printf("USER: %s - PASS: %s\n", tmp, tmp2);
            free(user);
            free(pass);
            return EXIT_SUCCESS;
        }
        else{
            printf("Utente o password errati o non presenti nel DB\n");
            free(user);
            free(pass);
            return EXIT_FAILURE;
        }
    }
    return EXIT_SUCCESS;
}

Я хотел бы знать, если:

  1. правильно писать в fgets значение sizeof(line) или нет. Я сомневаюсь, что line содержит указатель, поэтому он всегда 4 или 8 байт...
  2. line расположен правильно?

person polslinux    schedule 26.06.2012    source источник
comment
Да, но нет, и нет. Чего вы пытаетесь достичь здесь?   -  person Fred Foo    schedule 26.06.2012
comment
На самом деле, нет, да и да? ;) И нет, я тоже не уверен, чего он здесь пытается добиться ;)   -  person paulsm4    schedule 26.06.2012
comment
я хочу динамически выделять символы для пользователя и для прохода. затем я хочу выделить в строку сумму user+pass :)   -  person polslinux    schedule 26.06.2012


Ответы (2)


  1. Нет, sizeof(line) вернет размер указателя. То, что вы действительно хотите сделать, это просто

    size_t size_required = strlen(user) + strlen(pass) + 1; /* Don't forget about \0! */
    

    А затем просто используйте этот размер как размер линии. (Кстати: ваш код не является свободной строкой.)

    Редактировать: На самом деле, поскольку вы в конечном итоге хотите прочитать там имя пользователя + пароль + 2 разделителя токенов, которые ищет strtok, вы хотите добавить дополнительные 3 символа: 1 для завершения \0, 1 для первого разделителя ' ' и 1 для следующего разделителя '\n'. Так что должно быть:

    size_t size_required = strlen(user) + strlen(pass) + 3; /* Don't forget about \0! */
    
  2. Вы должны помнить, что спецификатор m для динамического размещения является нестандартным расширением. Это не будет работать на некоторых системах. И вы должны освобождать user и pass только, если их вызовы scanf возвращают положительное значение (например, если они успешны).

  3. Выделение line неверно: вы выделяете слишком мало одного символа, поэтому завершающий символ \0 не подходит (см. выше). Обратите внимание, что strlen возвращает размер строки исключая завершающий символ \0.

    Кроме того, sizeof(char) бессмысленно. Стандарт гарантирует, что sizeof(char) точно равно 1 (поскольку sizeof на самом деле возвращает не количество байтов, а количество символов, необходимых для покрытия битового представления аргумента).

  4. БОНУС На всякий случай проверьте tmp и tmp2 на наличие NULL. Вызов strcmp для аргумента NULL вызовет ошибку сегментации. Это важно: если прочитанная строка содержит логин+пароль длиннее, чем было указано ранее, разделитель токенов не будет прочитан fgets, а strtok не сможет найти, например, конечный символ '\n' , вернет значение NULL.

person Piotr Kalinowski    schedule 26.06.2012
comment
должен ли ваш код быть +2?? потому что у меня 2 строки, поэтому 2 '\ 0' :) - person polslinux; 27.06.2012
comment
У вас есть 2 строки, но в конечном итоге вы прочитаете там только 1, верно? ;) fgets прочитает не более n-1 символов и добавит последний один завершающий символ. Опять же, вы хотите прочитать его с разделителями токенов, поэтому вам, вероятно, следует использовать +3 (\0 + ' ' + '\n'). Я обновил ответ соответственно. - person Piotr Kalinowski; 27.06.2012

В: Правильно ли записывать в fgets значение sizeof(line)?

A: No :)

Потому что, как вы сказали, это всего 4 (или 8) байт.

Я совсем не уверен, что вы пытаетесь сделать. Возможно, что-то вроде этого?

#define MAXLINE 80

char *user, *pass, line[MAXLINE];
scanf ("%s", line);
user = malloc(strlen(line)+1);
strcpy (user, line);
...
person paulsm4    schedule 26.06.2012
comment
я хочу динамически выделять символы для пользователя и для прохода. затем я хочу выделить в строку сумму user+pass :) - person polslinux; 26.06.2012