2015-10-07 144 views
-2

我昨天有這個工作,並由於某種原因它已經停止,我想要做的是當用戶鍵入命令「添加」後面跟着名字,姓氏和電話號碼它追加對一個文件。什麼工作是在命令執行後讓我再次輸入「ADD」fname,lname,phone,然後遞增計數器將它全部寫入文件,它會讓我這樣做直到我手動終止程序,並且每個條目將在文本文件中。現在它將不止一次接受該命令,但是它只會將文件寫入我輸入的第一個條目。如果陳述不循環

是否有人能夠發現我失蹤的內容?

"server.c" [dos] 200L, 5323Cc 
/* 
* server.c 
*/ 

#include <stdio.h> 
#include <iostream> 
#include <strings.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <cstring> 
#include <cstdlib> 
#include <string> 
#include <sstream> 

using namespace std; 

#define SERVER_PORT 1617 
#define MAX_PENDING 5 
#define MAX_LINE 512 

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

struct sockaddr_in sin; 
socklen_t addrlen; 


char buf[MAX_LINE]; 
int len; 
int s; 
int new_s; 
int r = 1000; 
int result; 
char message; 
FILE *file_ptr; 
string cmd, fn, ln, ph; 
string add = "ADD"; 
string del = "DELETE"; 
string list = "LIST"; 
string quite = "QUIT"; 
string shutdown = "SHUTDOWN"; 



/* build address data structure */ 
bzero ((char *) &sin, sizeof (sin)); 
sin.sin_family = AF_INET; 
sin.sin_addr.s_addr = INADDR_ANY; 
sin.sin_port = htons (SERVER_PORT); 

/* setup passive open */ 
if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) 
{ 
    perror ("socket"); 
    exit (1); 
} 

if ((bind (s, (struct sockaddr *) &sin, sizeof (sin))) < 0) 
{ 
    perror ("bind"); 
    exit (1); 
} 

listen (s, MAX_PENDING); 

addrlen = sizeof (sin); 
cout << "The server is up, waiting for connection" << endl; 


    /* wait for connection, then receive and print text */ 
while (1) 
{ 
    if ((new_s = accept (s, (struct sockaddr *) &sin, &addrlen)) < 0) 
    { 
     perror ("accept"); 
     exit (1); 
    } 
    cout << "new connection from " << inet_ntoa (sin.sin_addr) << endl; 

    while (len = recv (new_s, buf, sizeof (buf), 0)) 
    { 
     /*send (new_s, buf, strlen(buf) + 1, 0); original send to echo in client */ 

    /* create string stream from contents of buffer */ 
     stringstream stream (buf); 

    /* read user input from string stream into strings for user input */ 
     stream >> cmd; 
     stream >> fn; 
     stream >> ln; 
     stream >> ph; 



    /* create character arrays and copy strings into character arrays */ 
     char command[9] = "  "; 
     char fname[9] = "  "; 
     char lname[9] = "  "; 
     char phone[13] = "   "; 

     cmd.copy (command, 8); 
     fn.copy (fname, 8); 
     ln.copy (lname, 8); 
     ph.copy (phone, 12); 




/* determine if valid command received */ 
     /* Adds whatever follows the word "ADD" to the text file" */ 
     if (cmd.compare (add) == 0){ 
    { 
      file_ptr = fopen ("file1.txt", "a+"); 
      fprintf (file_ptr, "%d" "%s" "%s" "%s" "%s", r, " ", fname, 
        lname, phone); 
      fprintf (file_ptr, "\n"); 
      fclose(file_ptr); 
      ++r; 
     } 
    } 
/* LIST user input */ 
     else if (cmd.compare (list) == 0) 
     { 
      file_ptr = fopen ("file1.txt", "r"); 

      size_t count; 
      while ((count = fread (buf, 1, sizeof buf, file_ptr)) > 0) 
      { 
       send (new_s, buf, count, 0); 
       fclose (file_ptr); 
      } 
     } 

     else if (cmd.compare (del) == 0)  /*Delete user input */ 
     { 
      { 
      FILE *fp1, *fp2; 
      /*consider 40 character string to store filename */ 
      char filename[40]; 
      char c; 
      int del_line, temp = 1; 
      fp1 = fopen ("file1.txt", "r"); 
      c = getc (fp1); 
      while (c != EOF) 
       { 
       printf ("%c", c); 
       /*print current character and read next character */ 
       c = getc (fp1); 
       } 
      rewind (fp1); 
      printf (" \n Enter line number of the line to be deleted:"); 
      /*accept number from user. */ 
      scanf ("%d", &del_line); 


      fp2 = fopen ("copy.c", "w"); 
      c = getc (fp1); 
      while (c != EOF) 
       { 
       c = getc (fp1); 
       if (c == '\n') 
        temp++; 


       if (temp != del_line) 
        { 
        /*copy all lines in file copy.c */ 
        putc (c, fp2); 
        } 
       } 

      fclose (fp1); 
      fclose (fp2); 
      /*remove original file */ 
      remove ("file1.txt"); 
      /*rename the file copy.c to original name */ 
      rename ("copy.c", "file1.txt"); 
      printf 
       ("\n The contents of file after being modified are as follows:\n"); 
      fp1 = fopen ("file1.txt", "r"); 
      c = getc (fp1); 
      while (c != EOF) 
       { 
       printf ("%c", c); 
       c = getc (fp1); 
       } 
      fclose (fp1); 

      } 
     } 
     else 
     { 
      cout << "Invalid Command" << endl; 
     } 

    } 
    close (new_s); 
} 
} 
+4

'if'語句不應該循環。 – owacoder

+0

在哪一種編程語言if語句用於循環? – haccks

+0

也許有一個外部循環,但是'if(cmd.compare(add)== 0)'做了什麼? 「添加」與數據有什麼關係? –

回答

0

,因爲這個節目是太破,我不能提供無OP的代碼重寫批發一個有效的解決方案。相反,這裏有一些筆記:

while (len = recv (new_s, buf, sizeof (buf), 0)) 

將分配recv返回代碼爲len,然後測試len。如果len爲0,則退出循環。如果len是任何其他值,包括recv的錯誤返回值-1,則循環繼續。

套接字錯誤的移交是功能上等同於該程序:

#include <iostream> 

int main() 
{ 
    int test; 
    while (test = -1) 
    { 
     std::cout << "loop de "; 
    } 
} 

這是不好的。

由於TCP/IP是流媒體協議,因此TCP/IP不能提供乾淨的包。這在別處被毆打致死,所以我不打算覆蓋它或尋找鏈接。谷歌在這方面做得很好。

因爲TCP/IP是一個流,recv會給你它所擁有的任何數據,直到給定緩衝區的大小。如果它什麼都沒有,它會等待某件事到來。

這意味着您可能會在一個recv中收到幾條消息,或者只有幾個字節。由於消息可能會在中途被切斷,有可能根本就不在BUF終止空果然這樣的:

stringstream stream (buf); 

成一個謎抓鬥袋。你將不知道什麼是流內。由於OP沒有檢查和處理recv的返回,他們可能會重複處理buf的最後一個內容,因爲recv返回了一個錯誤代碼並且沒有數據。

stream >> cmd;

而其同流讀取可能成功也可能不成功,因爲他們沒有測試,OP永遠不會知道。一旦失敗,其餘的讀取將失敗,因爲流的錯誤狀態不會被清除。

這些:

cmd.copy (command, 8); 

不會空正確終止。它們寫入char數組的時間不足以寫入到最後一個元素中的null,因爲它們被初始化,所以後面的fprintfs將存活,但不會打印正確的結果。

因此,鑑於上述雷區,輸出不正確並不令人意外,不值得嘗試提供解決方案。

在繼續使用該程序之前,OP需要對套接字編程和標準數據流進行一些閱讀和練習。