gpt4 book ai didi

c - Strtok() 随机返回 NULL

转载 作者:行者123 更新时间:2023-11-30 16:28:56 26 4
gpt4 key购买 nike

我正在尝试创建一个通过发送两种类型的消息与服务器通信的客户端:

  1. 单词QUIT,用于与服务器通信以关闭连接。
  2. 具有以下语法的运算:operator first_operand secondary_operand。例如:+ 3 3- 5 6等(操作数必须为正整数,且只能有2个操作数)。

如果服务器收到一个操作,它会执行该操作并将结果返回给客户端。问题是我发送的第一个操作返回正确的结果,而接下来的操作随机工作(有时它们返回正确的结果,其他时候函数 strtok() 没有获取第二个操作数并且返回NULL...)。

这是客户端的代码,用于处理用户在提示符中编写的消息,并扫描消息以检查操作是否使用正确的语法编写(警告:代码编写为以一种极其不专业和不干净的方式)。

产生问题的代码部分位于while(1)内部。

#define MAXLENGTH 256

int main (int argc, char *argv[]) {
int simpleSocket = 0;
int simplePort = 0;
int returnStatus = 0;
char first[10], second[10];
char* operator;
char buffer[MAXLENGTH] = "";
char message[50];
char terminationCommand[] = "QUIT\n";
char space[2] = " ";
struct sockaddr_in simpleServer;

if (3 != argc) {
fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
exit(1);
}

/* create a streaming socket */
simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (simpleSocket == -1) {
fprintf(stderr, "Could not create a socket!\n");
exit(1);
} else {
fprintf(stderr, "Socket created!\n");
}

/* retrieve the port number for connecting */
simplePort = atoi(argv[2]);

/* setup the address structure */
/* use the IP address sent as an argument for the server address */
//bzero(&simpleServer, sizeof(simpleServer));
memset(&simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family = AF_INET;
//inet_addr(argv[2], &simpleServer.sin_addr.s_addr);
simpleServer.sin_addr.s_addr=inet_addr(argv[1]);
simpleServer.sin_port = htons(simplePort);

/* connect to the address and port with our socket */
returnStatus = connect(simpleSocket, (struct sockaddr *)&simpleServer, sizeof(simpleServer));

if (returnStatus == 0) {
fprintf(stderr, "Connect successful!\n\n");
} else {
fprintf(stderr, "Could not connect to address!\n");
close(simpleSocket);
exit(1);
}

/* get the message from the server */
returnStatus = read(simpleSocket, buffer, sizeof(buffer));

if (returnStatus > 0) {
printf("%s\n", &buffer[3]);
} else {
fprintf(stderr, "Return Status = %d \n", returnStatus);
}

memset(&buffer, '\0', sizeof(buffer));

printf("You can execute 2 commands:\n");
printf("1. Operations ( +, -, *, /, % ) with the following syntax: operator + first operand + second operand.\n");
printf("Example: + 5 2 \n");
printf("2. Termination of the connection with the following syntax: QUIT + press Enter.\n");

while(1) {
printf("\nEnter a command:\n");
fgets(message, 1000, stdin);

// the if with the termination command works fine
if (strcmp(message, terminationCommand) == 0) {
if (send(simpleSocket, message, strlen(message), 0) < 0) {
printf("Send failed.");
return 1;
}

returnStatus = read(simpleSocket, buffer, sizeof(buffer));

if (returnStatus > 0) {
printf("%s\n", &buffer[4]);
} else {
fprintf(stderr, "Return Status = %d \n", returnStatus);
}

close(simpleSocket);
exit(1);
}

operator = strtok(message, space);

if (strcmp(operator, "+") == 0 || strcmp(operator, "-") == 0 || strcmp(operator, "/") == 0 || strcmp(operator, "%") == 0 || strcmp(operator, "*") == 0) {
char *first_operand = strtok(NULL, space);

if (first_operand != NULL) {
if (strcmp(first_operand, "ANS") == 0)
strcpy(first, "ANS");
else
strcpy(first, first_operand);

printf("%s\n", operator);
printf("%s\n", first);

char *second_operand = strtok(NULL, space);

printf("%s\n", second_operand);

if (second_operand != NULL && strtok(NULL, space) == NULL && (atoi(first) > 0 || strcmp(first, "ANS") == 0)) {
if (strcmp(second_operand, "ANS\n") == 0)
strcpy(second, "ANS");
else {
strcpy(second, second_operand);
}

if (atoi(second) > 0 || strcmp(second, "ANS") == 0) {
printf("OK\n");

char operation[] = "";

strcat(operation, operator);
strcat(operation, " ");
strcat(operation, first);
strcat(operation, " ");
strcat(operation, second);

if (send(simpleSocket, operation, strlen(operation), 0) < 0) {
printf("Send failed.");
return 1;
}

returnStatus = read(simpleSocket, buffer, sizeof(buffer));

if (returnStatus > 0) {
printf("%s\n", buffer);
} else {
fprintf(stderr, "Return Status = %d \n", returnStatus);
}
}
}
}
}

// after everything I reset the buffers I use to memorize the message and the elements of the message
memset(&buffer, '\0', sizeof(buffer));
memset(&first, '\0', sizeof(first));
memset(&second, '\0', sizeof(second));
memset(&message, '\0', sizeof(message));
memset(operator, '\0', sizeof(operator));
}
}

有人能告诉我为什么第二个 strtok() 90% 的时候都表现得很奇怪吗?我做错了什么?

最佳答案

您的程序存在多个问题:

您发送换行符终止的消息,并且您假设另一端的读取将准确返回对方发送的字节,这对于 TCP/IP 通信来说是一个错误的假设,仅返回顺序接收的字节数是有保证的,但消息可以在途中分割并以与发送顺序不同的 block 形式接收。您应该将套接字读入缓冲区,并且仅在收到换行符后才处理它。

就您的情况而言,还有另一个更紧迫的问题:您读取数据的缓冲区不是 null 终止的,因此您不应将其传递给标准 C 函数,例如 strtok().

关于c - Strtok() 随机返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52139211/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com