If语句不循环
If statement not looping
我昨天有这个工作,由于某种原因它已经停止了,我要做的是当用户键入命令"ADD"后跟名字,姓氏和电话号码时,它将其附加到文件中。工作的是,在命令执行后,它会让我再次输入"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);
}
}
我不能提供一个有效的解决方案,没有大规模重写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是一个流,recv会给你它拥有的任何数据,不超过给定缓冲区的大小。如果它什么都没有,它就会等待有东西到来。
这意味着您可能在一个接收器中获得多个消息,或者只有几个字节。由于消息可能在中间被切断,因此在buf中甚至可能没有终止null,从而变为:
stringstream stream (buf);
变成了一个神秘的抓包。你不会知道里面有什么。由于OP没有检查和处理recv的返回,因此它们可能会一遍又一遍地重新处理buf的最后内容,因为recv返回的是错误代码而不是数据。
stream>> cmd;
和它的其他流读可能成功也可能不成功,因为它们没有经过测试,OP永远不会知道。一旦一个操作失败,其余的读取操作也将失败,因为流的错误状态没有被清除。
这些:cmd.copy (command, 8);
将不会正确终止null。它们没有向char数组中写入足够远的内容,无法按照初始化的方式重写最后一个元素中的null,因此后面的fprintfs将继续存在,但不能打印正确的结果。
因此,考虑到上面的雷区,输出不正确并不奇怪,也不值得尝试提供解决方案。
在继续这个程序之前,OP需要对套接字编程和标准流做一些阅读和练习。
- 当调用switch语句中的函数时(即使函数不包含循环),似乎是永不结束的循环的问题
- 如果 else 语句不断循环
- do while 循环中的 if 语句以 yes 或 no 结尾
- 带有开关语句的 do-while 循环 -- 无穷循环错误
- 如果语句不会在 do - while 循环中运行
- 有没有办法在循环中的条件至少满足一次时运行语句?
- 什么可以用来替换代码中的循环和 if 语句?
- C++ 访问 if 语句(如果它们在 for 循环中)
- for 循环后的分号是什么意思?为什么第一个循环语句中有 j++
- 这段代码如何在没有任何循环语句或'goto'或递归的情况下循环?
- 终端不阅读循环语句
- 我的值不断增加,而不是在循环语句中重置
- 此 for 循环语句的正确语法
- 神秘的 for 循环语句
- do 循环语句导致无限循环
- 嵌套循环语句结果不正确
- 在 FOR 循环语句的条件部分中使用声明
- 构造长循环语句是一种好的做法吗
- 在条件C++循环语句中向SQLite3表中插入条目
- 循环语句警告的冒泡排序算法