gpt4 book ai didi

c - 字符串连接保持目标长度

转载 作者:行者123 更新时间:2023-11-30 19:34:05 25 4
gpt4 key购买 nike

我有一个用 C 语言编写的基本服务器客户端程序,但我遇到了有关字符串和连接的问题。基本上我有一些字符串(在下面的示例中只有 2 个),我必须将它们放入缓冲区中,缓冲区的大小由以下因素决定:

  total # of registered people * 33

示例中的两个字符串的长度都远小于缓冲区的长度。我想在连接后获得这样的东西:

            [0]            [32]
people_list=Mark Amy\0;

其中 Mark(第二个​​插入)位于缓冲区 (people_list) 的开头,而 Amy 距 Mark 开头 32 个字符(我希望我已经说清楚了)。

这是因为客户端代码是给我的,我无法修改它。客户端代码获取缓冲区并读取第一个元素,然后跳转 32 个字符并再次读取。我从客户端的 printf 得到的输出是这样的:

connected to server
Registered people:
Mark

虽然我想要这样:

connected to server
Registered people:
Mark
Amy

通信是通过套接字实现的,我已经检查过,但如果您希望提出一些更改建议,我将不胜感激。

服务器代码:

#include <stdio.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#define LENGTH 32

struct person {
char name[LENGTH+1];
struct person *next;
struct person *prev;

};
struct person *p_head = NULL;

void addPerson(char* name_p){
struct person *new = (struct person*) malloc(sizeof(struct person));
strcpy(new->name, name_p);
new->name[LENGTH]='\0';
new->next=p_head;
new->prev=NULL;
p_head=new;

}

int main(){

int fd_ser;
int fd_c;
int N=100;
char buf[N];
int times=0;
char* path="tmp/sock";

struct sockaddr_un sa;

unlink(path);
sa.sun_family=AF_UNIX;
strncpy(sa.sun_path,(char*) path, sizeof(sa.sun_path));

if((fd_ser=socket(AF_UNIX,SOCK_STREAM,0))<0){ //socket
perror((const char*) (size_t) errno);
exit(EXIT_FAILURE);
}


if ( bind(fd_ser,(struct sockaddr *)&sa, sizeof(sa))<0){
perror("bind\n");
}

listen(fd_ser,10); //listen


struct sockaddr_un addr;
int addr_size= sizeof(struct sockaddr_un);

fd_c=0;
while( (fd_c=accept(fd_ser,(struct sockaddr*) &addr, (socklen_t*)&addr_size))<0){
printf("waiting for connections...\n");
sleep(2);
}


//initialize list of people
char* Amy="Amy";
char* Mark="Mark";

addPerson(Amy);
addPerson(Mark);

//now concat the name strings in a buffer to be sent to the client

char* people_list;
unsigned int list_len;
int value;

struct person* ptr=(struct person*) malloc(sizeof(struct person));
ptr=p_head;
int offset=0;
int i=0;

while(ptr!=NULL){
i++;
people_list=realloc(people_list,i*LENGTH); //every single name has to be LENGTH characters
strcpy(&people_list[offset],ptr->name);
ptr=ptr->next;
offset=offset+LENGTH;
}
people_list[i*LENGTH]='\0';
list_len=(i*LENGTH)+1;

value=write(fd_c, &(list_len), sizeof(unsigned int));
if(value==-1){
perror("write length");
return -1;
}

int toWrite=list_len;
char *toRead=people_list;
while(toWrite>0){
value=write(fd_c, toRead, toWrite);
if(value==-1){
perror("write data");
return -1;
}
toWrite=toWrite-value;
toRead=toRead+value;
if(toRead<=people_list + list_len) break;
}

close(fd_c);
close(fd_ser);

return 0;
}

客户端代码:

#include <stdio.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <assert.h>
#include <errno.h>
#define MAX_LENGTH 2048
#define LENGTH 32

int main(){

int fd_cli;
char* path="tmp/sock";
struct sockaddr_un sa;
sa.sun_family=AF_UNIX;
strncpy(sa.sun_path,(char*) path, sizeof(sa.sun_path));

if( (fd_cli = socket(AF_UNIX, SOCK_STREAM, 0))==-1){
perror((const char*) (size_t) errno);
return -1;
}

while( (connect(fd_cli,(struct sockaddr*)&sa, sizeof(struct sockaddr_un))) == -1 ) {
if ( errno == ENOENT ) { sleep(1); }
else perror("connect:");
errno=0;
sleep(1);
}

printf("connected to server\n");

int value;

unsigned int len_data;

value=read(fd_cli,&(len_data),sizeof(unsigned int));
if(value==-1){
perror("read length");
return -1;
}
char* buffer=malloc(len_data*sizeof(char));

int toRead=len_data;
char *toWrite=buffer;
while(toRead>0){
value=read(fd_cli, toWrite, toRead);
if(value==-1){
perror("read buffer");
return -1;
}
toRead=toRead-value;
toWrite=toWrite+value;
if(toWrite<=buffer + len_data) break;
}


int people_n = len_data / (LENGTH+1);
assert(people_n > 0); //proceeds only if there is at least one person registered

printf("Registered people:\n");

for(int i=0,p=0;i<people_n; ++i, p+=(LENGTH+1)) {
printf(" %s\n", &buffer[p]);
}

close(fd_cli);

return 0;

}

我真的希望我已经清楚地解释了这个问题!感谢您的帮助!

最佳答案

由于这一行,它只打印第一个用户(Mark):

int people_n = len_data / (LENGTH+1);

在此示例中,len_data = 65LENGTH = 32。因此,当您将 1 添加到 LENGTH 时,它将返回 1(65/33 = 1.96 => 您得到 1)。然后它只打印第一个用户。

考虑使用Valgrind。它将帮助您检查内存的使用情况。

关于c - 字符串连接保持目标长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44345070/

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