2012-06-26 49 views
1

這是文件auth.txt(用戶名密碼)
保羅1234
盧卡0000
馬爾西1000

這是我的代碼:ç查找字符串轉換成文件

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

void onexit(char *u, char *p, char *l, FILE *f, int flag); 

int main(int argc, char *argv[]){ 

    FILE *fp; 
    char *tmp, *tmp2, *user, *pass, *line; 

    printf("Inserire utente: "); 
    if(scanf("%ms", &user) == EOF){ 
     perror("scanf"); 
     return EXIT_FAILURE; 
    } 

    printf("Inserire password: "); 
    if(scanf("%ms", &pass) == EOF){ 
     perror("scanf"); 
     onexit(user, NULL, NULL, NULL, 1); 
     return EXIT_FAILURE; 
    } 

    size_t max_length = strlen(user) + strlen(pass) + 3; 
    line = malloc(max_length); 
    if(line == NULL){ 
     perror("malloc"); 
     onexit(user, pass, NULL, NULL, 2); 
     return EXIT_FAILURE; 
    } 

    fp = fopen("/home/pol/auth.txt", "r"); 
    if(fp == NULL){ 
     printf("Errore apertura file\n"); 
     onexit(user, pass, line, NULL, 3); 
     return EXIT_FAILURE; 
    } 

    while(!feof(fp)){ 
     if(fgets(line, max_length , fp) == NULL){ 
      perror("fgets"); 
      onexit(user, pass, line, fp, 4); 
      return EXIT_FAILURE; 
     } 
     tmp = strtok(line, " "); 
     if(tmp == NULL){ 
      perror("strtok"); 
      onexit(user, pass, line, fp, 4); 
      return EXIT_FAILURE; 
     } 

     tmp2 = strtok(NULL, "\n"); 
     if(tmp2 == NULL){ 
      perror("strtok"); 
      onexit(user, pass, line, fp, 4); 
      return EXIT_FAILURE; 
     } 
     if((strcmp(tmp,user) == 0) && (strcmp(tmp2,pass) == 0)){ 
      printf("USER: %s - PASS: %s\n", tmp, tmp2); 
      onexit(user, pass, line, fp, 4); 
      return EXIT_SUCCESS; 
     } 
     else{ 
       continue; 
     } 
    } 
    printf("no such user or pwd into DB\n"); 
    onexit(user, pass, line, fp, 4); 
    return EXIT_FAILURE; 
} 

void onexit(char *u, char *p, char *l, FILE *f, int flag){ 
    if(flag == 1){ 
     free(u); 
    } 
    if(flag == 2){ 
     free(u); 
     free(p); 
    } 
    if(flag == 3){ 
     free(u); 
     free(p); 
     free(l); 
    } 
    if(flag == 4){ 
     free(u); 
     free(p); 
     free(l); 
     fclose(f); 
    } 
} 

編輯:另一個問題!
如果我想測試luca0000我得到:

別名選擇utente:盧卡
別名選擇密碼:0000
strtok的:成功

和程序停止。 它只適用於第一和第三輸入,但不適用於第二!
爲什麼?

+0

用另一個建議編輯了我的答案;我們最終會得到這個! –

+0

我是否應該對我的最新編輯進行評論,以便讓您注意到?無論如何,我相信你現在應該能夠接受這個問題的答案,並且可以用它來完成。如果還有其他問題出現,請提出一個新問題。 – MvG

+0

完成:)再次感謝! – polslinux

回答

3

它看起來像你的while循環只會經歷一次迭代:

while(!feof(fp)){ 
    // ... 
    if((strcmp(tmp,user) == 0) && (strcmp(tmp2,pass) == 0)){ // if match, exit 
    printf("USER: %s - PASS: %s\n", tmp, tmp2); 
    onexit(user, pass, line, fp, 4); 
    return EXIT_SUCCESS; 
    } 
    else{              // else exit 
    printf("no such user or pwd into DB\n"); 
    onexit(user, pass, line, fp, 4); 
    return EXIT_FAILURE; 
    } 
} 

...這似乎有點滑稽。如果您閱讀的第一行不匹配,您是否真的想退出?


編輯:

另一個問題:你需要爲userpass分配空間,你把他們先往scanf

char *user; 
scanf("%ms", &user); // error 

取而代之的是,你可以嘗試例如:

char user[100]; 
scanf("%ms", &user); // now user actually has some space to store data 

(在你的版本,scanf會嘗試將數據寫入到該user點,但user只是在內存中指出,在一個隨機位置,所以誰知道會發生什麼位置。)

哎呦,正如@MvG指出的那樣,這很好。我不熟悉「%ms」POSIX擴展名。


編輯2

說你輸入用戶名和uu密碼pp。由於這樣的:

size_t max_length = strlen(user) + strlen(pass) + 3; 

...你會設置max_length2 + 2 + 3,或7fgets將讀取數據,直到遇到最多max_length-1個字符或換行符。這意味着當您進入while循環時,您只會嘗試每次迭代讀取最多7-16字符,這似乎不正確。

例如,如果你的密碼文件包含:

paolo 1234 
luca 0000 
marci 1000 

...然後line將獲得以下值:

  1. "paolo "(後面有個空格)
  2. "1234"
  3. "luca 0"
  4. "000"
  5. "marci "(同樣,後面有個空格)
  6. "1000"

而是對當前用戶名和密碼,您已經閱讀基礎max_length的,讓max_length龐大的固定值(如100 )。

+0

哈哈,你是對的xD我寫了其他{繼續;}現在它工作XD – polslinux

+0

'%ms'中的'm'已經處理分配。這是[POSIX擴展名](http://pubs.opengroup.org/onlinepubs/9699919799/functions/scanf.html)。上面的程序沒有調用free,所以有內存泄漏,但是如果db很小並且程序在一次請求後終止,那麼在那裏我沒有問題。請注意,對於'%ms',你傳遞一個指針變量的地址(即'char **'值),而對於'%s',你需要傳遞一個數組的地址(即'char *'值) 。 – MvG

+0

所以沒有必要做'char用戶[100]'對嗎?所以我必須糾正到'scanf(「%s」,用戶)'? – polslinux

1

您的錯誤處理程序在while循環中。如果用戶不是該文件中的第一個,則立即中止。尤爲明顯這樣寫:

… 
     if((strcmp(tmp,user) == 0) && (strcmp(tmp2,pass) == 0)){ 
      printf("USER: %s - PASS: %s\n", tmp, tmp2); 
      onexit(user, pass, line, fp, 4); 
      return EXIT_SUCCESS; 
     } 
    } 
    printf("no such user or pwd into DB\n"); 
    onexit(user, pass, line, fp, 4); 
    return EXIT_FAILURE; 
} 

編輯:

我能重現strtok: Success問題時,有在數據庫中沒有之間的空間中的條目。在循環進行到目前爲止,這可能甚至是文件末尾的空行。在這種情況下,第一個strtok將返回整個字符串,第二個strtok將返回NULL,從而表示沒有更多的標記。由於這不是錯誤消息,因此錯誤狀態爲零,對應於「錯誤消息」Success

我想你的情況,問題在於不同的記錄長度。您通過輸入的長度來測量行讀取緩衝區的長度,但有些記錄更長。在這種情況下,你閱讀一行的一部分並將其正確分割,並在下一次運行中閱讀該行的其餘部分,並最終顯示出沒有空格的行,包括上面描述的行爲。

+0

感謝我糾正了我的代碼!但我有另一個問題在第一篇文章中解釋:) – polslinux

+0

我不明白!我的db文件最後沒有空行,auth.txt中的所有條目在USER PASS之間有1個空格。我也注意到,如果我只有4項只有第一和第三個工作,但第二個和第四個不是O.o – polslinux