【问题标题】:Concatenate multiple char* in a row using strcat使用 strcat 在一行中连接多个 char*
【发布时间】:2018-12-14 10:27:47
【问题描述】:

我目前正在尝试使用strcat 在我的服务器程序中连续连接多个“字符串”。 相关部分代码如下: 我成功拿到了客户端发来的年月日文件名,因为打印的很好。

我的字符串初始化如下:

    char username[MAX_USERNAME_SIZE];
    char filename[MAX_FILENAME_SIZE];
    char path[MAX_FILEPATH_SIZE];
    char buff[BUFFSIZE];
    char year[4], month[2], day[2];
    ...
    if ((numbytes = recv(new_fd, &username, MAX_USERNAME_SIZE, 0)) == -1)
    {
        perror("Serveur: recv username");
        return EXIT_FAILURE;
        }
        username[numbytes] = '\0';
        printf("Serveur: username: %s\n", username); 
        /* create user's repository if it doesn't exist yet*/

        // 3) get date from client
        if ((numbytes = recv(new_fd, year, 4, 0)) == -1)
        {
            perror("Serveur: recv year");
            return EXIT_FAILURE;
        }
        year[numbytes] = '\0';
        printf("year: %s\n", year);
        if ((numbytes = recv(new_fd, month, 2, 0)) == -1)
        {
            perror("Serveur: recv month");
            return EXIT_FAILURE;
        }
        month[numbytes] = '\0';
        printf("month: %s\n", month);
        if ((numbytes = recv(new_fd, day, 2, 0)) == -1)
        {
            perror("Serveur: recv day");
            return EXIT_FAILURE;
        }
        day[numbytes] = '\0';
        printf("day: %s\n", day);
        // get filename from client
        if ((numbytes = recv(new_fd, filename, MAX_FILENAME_SIZE, 0)) == -1)
        {
            perror("Serveur: recv filename");
            return EXIT_FAILURE;
        }
        filename[numbytes] = '\0';
        printf("Serveur: filename: %s\n", filename);

但是当我尝试正确连接所有字符串时遇到问题。

        // create user repository
        strcpy(path, argv[1]);
        printf("Serveur: Path: %s\n", path);
        strcat(path, "/");
        printf("Serveur: Path: %s\n", path);

        strcat(path, username);
        strcat(path, "/");
        printf("Serveur: Path: %s\n, username:%s\n", path, username);
        my_mkdir(path, MODE);

        strcat(path, year);
        strcat(path, "/");
        printf("Serveur: Path: %s\n, year: %s\n", path, year);
        my_mkdir(path, MODE);

        strcat(path, month);
        strcat(path, "/");
        printf("Serveur: Path: %s\n, month: %s\n", path, month);
        my_mkdir(path, MODE);

        strcat(path, day);
        strcat(path, "/");
        printf("Serveur: Path: %s\n, day: %s\n", path, day);
        my_mkdir(path, MODE);

        strcat(path, filename);
}

在我这样做之后,用户名、年份和月份的打印效果令人惊讶。 这是我执行代码时的输出(我确定文件名是可以的,因为我从客户端检索的文件保存在正确的名称下):

Serveur: connection recieved from client 127.0.0.1
Serveur: username: student
year: 95
month: 5
day: 11
Serveur: filename: tux.png
Serveur: Path: ./Test0/Test1
Serveur: Path: ./Test0/Test1/
Serveur: Path: ./Test0/Test1//
, username:
Serveur: Path: ./Test0/Test1///
, year: 
Serveur: Path: ./Test0/Test1////
, month: 
Serveur: Path: ./Test0/Test1////11/
, day: 11

我真的很想清楚我错在哪里。提前致谢

【问题讨论】:

  • 您最喜欢的调试器将在这里为您提供帮助。如果你提供一个minimal reproducible example(这意味着一个没有recv 东西的带有测试数据的独立程序),我们可以提供帮助,但是这样做,你可能会自己发现错误。
  • 你没有告诉我们path是如何定义的,所以那里很容易出现问题
  • 该错误存在于您未发布的某些代码中。两个代码块之间执行什么代码?顺便说一句:recv(new_fd, &username,... 我猜你不知道&
  • 你的缓冲区是如何定义的? char username[??....
  • @ChrisTurner 当我在客户端和服务器程序中将年、月和日的大小分别更改为 5、3、3 并删除每个“var[numbytes] =”时,我达到了预期的结果\0' ´(其中 var = {年、月或日})在服务器程序中。但是,我仍然不明白为什么。这也意味着我正在从客户端向服务器发送“\0”。这不是多余的吗?

标签: c strcat


【解决方案1】:

问题是您没有为字符串提供足够的空间。你仍然没有准确地展示它们是如何声明的,但是有足够的例子来证明这个问题,比如这个。

char year[4]

上面只能容纳 3 个字符 - 第 4 个是存储 \0 终止字符的空间。

在这里,您告诉您的代码从套接字读取 4 个字节,它会这样做,然后 numbytes 将等于 4...

    if ((numbytes = recv(new_fd, year, 4, 0)) == -1)

...然后您使用numbytes 添加 NUL 终止符...

    year[numbytes] = '\0';

...但是year[4] 超出了数组的范围,这会导致未定义的行为。 year 可能看起来有一个有效的年份,但随后您的代码的其余部分发生了并且发生了奇怪的事情,因为您对所有其他字符串也犯了同样的错误。

要容纳 4 个字符加上 NUL,您需要声明 year 至少 5 个,像这样...

char year[5]

...但是您的计算机内存不足以至于您需要如此节俭吗?最好给它比它需要的更多,或者将它读入一个有足够空间的缓冲区,并分配足够的内存来创建正确大小的字符串,如果空间非常宝贵,就像这个例子所示。

char *year;
char buffer[100];
if ((numbytes = recv(new_fd, buffer, 4, 0)) == -1)
{
    perror("Serveur: recv year");
    return EXIT_FAILURE;
}
buffer[numbytes] = '\0';
year=malloc(numbytes+1);
strcpy(year,buffer);

【讨论】:

    【解决方案2】:

    显示显示用户名、年、月和日的内存分配的代码。确保它们没有重叠或共享。

    试试

    sprintf(path,"%s/%s/%s/%s/%s/",argv[1],username,year,month,day);
    

    或者换个样子,

     strcpy(path, argv[1]);
     printf("Serveur: Path: %s\n", path);
     strcat(path, "/");
     printf("Serveur: Path: %s\n", path);
    
    
     if ((numbytes = recv(new_fd, &username, MAX_USERNAME_SIZE, 0)) == -1){
            perror("Serveur: recv username");
            return EXIT_FAILURE;
     }
     username[numbytes] = '\0';
     printf("Serveur: username: %s\n", username); 
     strcat(path, username);
     strcat(path, "/");
     printf("Serveur: Path: %s\n, username:%s\n", path, username);
     my_mkdir(path, MODE);    
    
     /* create user's repository if it doesn't exist yet*/
    
     // 3) get date from client
     if ((numbytes = recv(new_fd, year, 4, 0)) == -1){
         perror("Serveur: recv year");
         return EXIT_FAILURE;
     }
     year[numbytes] = '\0';
     printf("year: %s\n", year);
     strcat(path, year);
     strcat(path, "/");
     printf("Serveur: Path: %s\n, year: %s\n", path, year);
     my_mkdir(path, MODE);
    
     if ((numbytes = recv(new_fd, month, 2, 0)) == -1){
         perror("Serveur: recv month");
         return EXIT_FAILURE;
     }
     month[numbytes] = '\0';
     printf("month: %s\n", month);
    
     strcat(path, month);
     strcat(path, "/");
     printf("Serveur: Path: %s\n, month: %s\n", path, month);
     my_mkdir(path, MODE);
    
    
     if ((numbytes = recv(new_fd, day, 2, 0)) == -1){
         perror("Serveur: recv day");
         return EXIT_FAILURE;
     }
     day[numbytes] = '\0';
     printf("day: %s\n", day);
    
     strcat(path, day);
     strcat(path, "/");
     printf("Serveur: Path: %s\n, day: %s\n", path, day);
     my_mkdir(path, MODE);
    
     // get filename from client
     if ((numbytes = recv(new_fd, filename, MAX_FILENAME_SIZE, 0)) == -1){
         perror("Serveur: recv filename");
         return EXIT_FAILURE;
     }
     filename[numbytes] = '\0';
     printf("Serveur: filename: %s\n", filename);
     strcat(path, filename);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多