【问题标题】:Manipulating pointers using C使用 C 操作指针
【发布时间】:2011-05-02 10:14:46
【问题描述】:

在使用 C 中的指针时,我遇到了一个非常不一致的结果,我正在使用一个令牌,它是一个字节字符串,我需要创建一个目录路径。 令牌包含日期作为前缀,格式为 20101129(2010-oct-29),然后是 20 字节的字符串,因此令牌看起来像 20101102A2D8B328CX9RDTBDE373,该方法应该返回看起来像 2010/11 的路径/02/A2D8/B328/CX9R/DTBD/E373.

现在使用我在下面提供的代码中使用的方法,返回包含不需要的字符的字符串,而代码看起来不错,下面提供了代码

#include <stdio.h>  
#include <string.h>  
#include <unistd.h>  
#include <stdlib.h> 

#define token "20101102A2D8B328CX9RDTBDE373"
#define SLASH "/"

int main()
{
    char *mainstring = (char*)malloc(strlen(token));
    char *nextstring = (char*)malloc(strlen(token));
    char tokenarr[50] = token;
    char patharr[50];
    char pathmem[50];
    char *fullstring = (char*)malloc(strlen(token));

    char yrstr[4]="";
    char yrmem[4]="";
    char yrarr[4]="";

    char monstr[2]="";
    char monmem[2]="";
    char monarr[2]="";

    char daystr[2]="";
    char daymem[2]="";
    char dayarr[2]="";

    memcpy(mainstring,token,strlen(token));


    memcpy(yrarr,tokenarr,4);
    strncpy(yrstr,mainstring,4);
    memcpy(yrmem,mainstring,4);

    puts(yrarr);
    puts(yrstr);
    puts(yrmem);


    mainstring = mainstring +4;
    memcpy(monarr,tokenarr+4,2);
    strncpy(monstr,mainstring,2); 
    memcpy(monmem,mainstring,2);

    puts(monarr);    
    puts(monstr); 
    puts(monmem);    

    mainstring = mainstring+2;
    memcpy(dayarr,tokenarr+6,2);
    strncpy(daystr,mainstring,2);
    memcpy(daymem, mainstring,2);

    puts(dayarr);
    puts(daystr);
    puts(daymem);

    strcat(patharr,yrarr); strcat(pathmem,yrmem);
    strcat(patharr,"/"); strcat(pathmem,SLASH);
    strcat(patharr,monarr);strcat(pathmem,monmem);
    strcat(patharr,"/"); strcat(pathmem,SLASH);
    strcat(patharr,dayarr); strcat(pathmem,daymem);

    puts(patharr);
    puts(pathmem);

    mainstring = mainstring +2;
    int i;

    for(i=0;i<5;i++)
    {
        memcpy(nextstring,mainstring,4);
        mainstring = mainstring +4;
        printf("The %d th string is:",i+1);        
        puts(nextstring); strcat(fullstring,"/");
        strcat(fullstring, nextstring);

        puts(fullstring);
    }
    strcat(patharr,fullstring); 
    strcat(pathmem,fullstring);
    puts(patharr);
    puts(pathmem);


return 0;

}

代码的结果是:

2010
2010
2010
11
11m��
11
02米
02
02
2010/11/02m
��m�� 2010 /11/02
第一个字符串是:A2D8
/A2D8
第二个字符串是:B328
/A2D8/B328
第三个字符串是:CX9R
/A2D8/B328/CX9R
第 4 个字符串是:DTBD
/A2D8/B328/CX9R/DTBD
第 5 个字符串是:E373
/A2D8/B328/CX9R/DTBD/E373
2010/11/02m /A2D8/B328/CX9R/DTBD/E373
��m�� 2010 /11/02/A2D8/B328/CX9R/DTBD/E373

我的主要问题是,为什么字符会包含在结果字符串中?我做错了什么指针?

【问题讨论】:

  • 只有一个变量指向 malloc() 返回的地址,然后修改该变量,这是一种非常糟糕的风格。为了安全起见,您应该计划在指针上调用 free() 并保持原始值不变。在开头复制主字符串指针,然后对其进行操作。
  • 细节点:20101129 是 2010 年 11 月 29 日。

标签: c memory pointers allocation


【解决方案1】:

strlen返回字符串的长度,不包括NULL终止符;因此memcpy 没有复制它,因此结果字符串不会终止。这同样适用于您的mallocs。

您要么需要使用strlen() + 1,要么使用strcpy()

【讨论】:

  • 使用 strcpy() 而不分配 strlen()+1 会调用未定义的行为 - 写入超出分配空间的末尾。
【解决方案2】:

C 中的字符串以空字符 ('\0') 终止。您使用的各种字符串(例如yrstr)不够大,无法包含此空字符,并且您没有将空字符放入其中。

例如,当你这样做时

strncpy(yrstr,mainstring,4);

没有空字符被添加到字符串中,因为如果目标字符串中没有足够的空间,strncpy 会省略空字符。您需要自己添加空字符,例如这样:

yrstr[4]='\0';

这要求yrstr 足够大以包含至少五个字符。

【讨论】:

  • 感谢您的回复,会通知您更新的变化
  • 还要注意像yrstr[4] 这样的数组需要yrstr[5] 以允许尾随NULL。
【解决方案3】:

如果您的目标是将“20101102A2D8B328CX9RDTBDE373”转换为“2010/11/02/A2D8/B328/CX9R/DTBD/E373”,那么一种方法如下;

// source string YYYYMMDD<20-char token>
char *src = "20101102A2D8B328CX9RDTBDE373";

// destination string, alloc space for source + 7 slashes + 1 null terminator
char *dest = (char *)calloc(1, strlen(src) + 7 + 1);

// now copy elements of src to dest, inserting intermediate slashes
<your code here>

【讨论】:

    【解决方案4】:

    感谢您的投入,结果现在已经是一致的。感谢所有参与并帮助我的人。我正在发布代码,其中包含您的所有输入,以供下一个学习者从中学习。这里是:

    #include <stdio.h>  
    #include <string.h>  
    #include <unistd.h>  
    #include <stdlib.h> 
    
    #define token "20101102A2D8B328CX9RDTBDE373"
    #define SLASH "/"
    
    int main()
    {
        char *mainstring = (char*)malloc(strlen(token));
        char *nextstring = (char*)malloc(strlen(token));
        char tokenarr[50] = token;
        char patharr[50];
        char pathmem[50];
        char *fullstring = (char*)malloc(strlen(token));
        patharr[50]='\0';
    
    
    
        char yrstr[5];
        char monstr[3];    
        char daystr[3];
    
        yrstr[4] ='\0';
        monstr[2]='\0';
        daystr[2]='\0';
    
    
    
        memcpy(mainstring,token,strlen(token)+1);    
        strncpy(yrstr,mainstring,4);
    
    
    
        mainstring = mainstring +4;
    
        strncpy(monstr,mainstring,2); 
    
    
        mainstring = mainstring+2;    
        strncpy(daystr,mainstring,2);
    
        puts(yrstr);    
        puts(monstr); 
        puts(daystr);
    
        mainstring = mainstring +2;
        int i;
    
        for(i=0;i<5;i++)
        {
            memcpy(nextstring,mainstring,4);
            mainstring = mainstring +4;
            printf("The %d th string is:",i+1);        
            puts(nextstring);strcat(fullstring,SLASH);
            strcat(fullstring, nextstring);
    
            puts(fullstring);
        }
    
    return 0;
    
    }
    

    结果是:

    2010
    11
    02
    The 1 th string is:A2D8
    2010/11/02/A2D8
    The 2 th string is:B328
    2010/11/02/A2D8/B328
    The 3 th string is:CX9R
    2010/11/02/A2D8/B328/CX9R
    The 4 th string is:DTBD
    2010/11/02/A2D8/B328/CX9R/DTBD
    The 5 th string is:E373
    2010/11/02/A2D8/B328/CX9R/DTBD/E373
    

    【讨论】:

    • 虽然这段代码看起来运行正常,但其中也有错误。例如,在第 11 行,您为 mainstring 分配了 strlen(token) 字节,但后来在第 31 行,您将 strlen(token) + 1 个字节从 token 复制到 mainstring。
    • 快速跟进:我编译并运行了这段代码,错误确实有影响。运行代码的结果不正确,与你看到的不符。
    • 感谢您关注细节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 2011-04-17
    • 1970-01-01
    • 2015-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多