代码之家  ›  专栏  ›  技术社区  ›  Roni Gadot

C-调用函数时出现问题

  •  -7
  • Roni Gadot  · 技术社区  · 7 年前

    使用下面的代码,我试图将字符串编码为基数64。我不知道如何调用该方法。

    我正在尝试转换输入字符串 "test" "dGVzdA==" 在base64中。

    我试过使用 strcpy(data,txt) ,但无法确定如何完成方法调用。

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #include <stdint.h>
    #include <stdlib.h>
    
    static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
                                    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
                                    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
                                    'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
                                    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
                                    'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                                    'w', 'x', 'y', 'z', '0', '1', '2', '3',
                                    '4', '5', '6', '7', '8', '9', '+', '/'};
    
    static int mod_table[] = {0, 2, 1};
    
    char *base64_encode(char *data,
                        size_t input_length,
                        size_t *output_length) {
    
        *output_length = 4 * ((input_length + 2) / 3);
    
        char *encoded_data = malloc(*output_length);
        if (encoded_data == NULL) return NULL;
    
        for (int i = 0, j = 0; i < input_length;) {
    
            uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
            uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
            uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
    
            uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
    
            encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
            encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
            encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
            encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
        }
    
        for (int i = 0; i < mod_table[input_length % 3]; i++)
            encoded_data[*output_length - 1 - i] = '=';
    
        return encoded_data;
    }
    
    int main() {
      char txt[] = "test";
      char *data;
      //... Please help 
    }
    

    如何转换 txt ( “测试” )至 “dGVzdA==” 然后打印出来?

    2 回复  |  直到 7 年前
        1
  •  0
  •   Ronan Boiteau    7 年前

    这是一个 main() 这需要 base64_encode() :

    int main(void) {
      char data[] = "test";
      char *encoded_data;
      size_t len;
    
      encoded_data = base64_encode(data, strlen(data), &len);
      printf("%s (%zu) => %s (%zu)", data, strlen(data), encoded_data, len);
    }
    

    解释

    • char data[] 包含要编码的字符串。您需要将其作为参数传递给 base64\u编码()
    • char *encoded_data 是一个指针,用于存储的返回值 base64\u编码() 。您将使用此变量访问解码字符串,因为 base64\u编码() 返回指向存储解码字符串的分配空间的指针。
    • size_t len 是一个用于存储解码字符串大小的变量。您将提供一个指向此变量的指针作为 base64\u编码()
    • strlen(data) ,第二个参数 base64\u编码() ,是的长度 字符数据[]
        2
  •  0
  •   mhawke    7 年前

    你应该读一本关于C编程的书或教程,因为调用函数是一个非常基本的概念。

    要回答您的问题,请传递明文、长度和变量地址以接收结果输出的长度:

    int main() {
      char txt[] = "test";
      char *data;
      size_t output_length;
    
      data = base64_encode(txt, strlen(txt), &output_length);
      printf("%*s\n", output_length, data);
    }
    

    函数返回指向数据的指针。在上面的代码示例中,将分配给 data 。返回字符串的长度将由中的函数设置 output_length 变量

    需要注意的是,返回的字符串是 null终止于 base64_encode() 。如果假设它是以null结尾的字符串,并尝试将其作为一个字符串使用,则这可能会导致代码中出现问题。例如,天真地打印它或试图用 strlen() 可能导致缓冲区溢出,并可能导致程序崩溃。

    可以附加空字符( '\0' )至 数据 然而 base64\u编码() 只为编码字符串分配足够的空间,因此严格来说,附加任何内容都可能访问无效内存,导致崩溃。解决方案包括:

    • 小心处理绳子。使用以下内容打印:

         printf("%*s", output_length, data);
      
    • 分配自己的字符串长度 output_length + 1 ,复制 将字符串编码为新字符串,然后null终止新字符串:

         data = base64_encode(txt, strlen(txt), &output_length);
         char *encoded = malloc(output_length + 1);
         strncpy(encoded, data, output_length);
         encoded[output_length] = '\0';
      

    最后,一定要打电话 free(data) 当您完成base64编码数据时,确保在函数中分配的内存 base64\u编码() 已发布。