从函数返回的char *数组打印不正确的值(可能是内存管理)

时间:2018-06-21 21:10:09

标签: c arrays pointers memory-management char

我正在研究一个函数,该函数将逐行接收文件,并逐行读取,从文件中删除所有非十六进制的内容,并返回非十六进制的自由行。当我遍历文件的每一行时,我看到的是期望值,并且该函数仅获取十六进制值,这正是我想要的。

但是,当我在主屏幕上打印strippedLine时,在开头出现了一些意外字符,并且丢失了数据的最后一个字节。 (我对c和内存管理非常陌生)。

这是我主要的代码:

char currentLine[100];
char *strippedLine = NULL;

FILE *file = fopen("filename.txt", "r");

// Works as expected getting each line from file.
while(fgets(currentLine, sizeof(currentLine), file) != NULL)
{   
    // Change from original question
    //strippedLine = (char *)malloc(1 + strlen(currentLine));
    strippedLine = malloc(1 + strlen(currentLine));

    // Change from original question
    //strcpy(strippedLine, StripNonHex(currentLine));
    strippedLine = StripNonHex(currentLine);


    printf("%s", strippedLine);

}

这是我想返回一个删除了所有十六进制的char数组的函数:

char *StripNonHex(char *line)
{
    char *nl = NULL;
    char *token = NULL;                        
    int convs = 0;
    unsigned ch = '\0';
    int hexLine = 0;
    char *strippedLine = (char *) malloc(sizeof(char) * 256);
    int counter = 0;

    // Remove new-line char
    if (nl)                                                                  
    {                                                                                                              
        *nl = '\0';                              
    }                                                                                                                                      
    // Split each line into space-delimited tokens
    token = strtok(line, " ");

    convs = sscanf(token, "%x", &ch);

    // Works as expected seeing each space delimited hex value of file.
    while(token)
    {
        convs = sscanf(token, "%x", &ch);
        if (convs == 1 && strlen(token) == 2)
        {
            hexLine = 1;
            strippedLine[counter] = token;
        }
        counter += strlen(token);
        token = strtok(NULL, " ");
        // Removed from original question
        //counter++;
    }

    // Removed from original question
    //strippedLine[counter + 1] = '\0';

    return strippedLine;
}

很抱歉缺少输入和输出。在下面

输入

A5 12 00 24 00 01 22 00 3F 11    

输出

≡¡║A5120024000122003F

由于@Barmar的建议,此输出更加接近。它只是丢失了最后一个字节,并且在开头有一些意外的字符。

我已经更新了我的问题,以使我现在所拥有的更加有意义。


counter += strlen(token);移到if语句中是我的最后一个问题。无论是否找到所需的内容,我都会无意中移动指针。

1 个答案:

答案 0 :(得分:1)

您没有将total_deleted = 0 Record.where(...).includes(...).find_in_batches(batch_size: 100) do |group| Record.transaction do group.each do |record| record.destroy end total_deleted += group.size percentage = (total_deleted.to_f / total.to_f * 100).round self.update_attribute(:details, "Deleted #{total_deleted} of #{total} (#{percentage}%)") end end 复制到token中。

strippedLine

strippedLine[counter] = token; 中的指针转换为token,这是实现定义的转换,最有可能只是采用地址的低8位,并将转换后的值存储到{{ 1}}。正确的方法是:

char

然后,您需要将strippedLine[counter]增加令牌的长度:

strcpy(&strippedLine[counter], token);

如果要将十六进制值扫描到counter中,则需要使用:

counter += strlen(token);

由于unsigned char复制了空终止符,因此您最后不需要sscanf(token, "%hhx", &ch);

由于strippedLine[counter + 1] = '\0';返回了新分配的字符串,因此无需在结果上使用strcpy()。只需直接为其分配StripNonHex()即可,而不是分配另一个字符串。

strcpy()

然后,您就可以在使用完行之后使用strippedLine

char *strippedLine = StripNonHex(currentLine); 在分配其free(strippedLine)变量时应使用StripNonHex(),而不是硬编码大小strlen()

strippedLine