strcpy()和char

时间:2016-11-15 16:16:18

标签: c string struct

我想将一个字符串存储到结构内的char数组中,当我访问char数组时,我希望结果与全局变量errCode中的值一起显示。当我访问结构的errDesc成员时,我希望结果为“错误检测到错误代码0xA0B0C0D0”,但由于使用strcpy复制字符串,因此我得到一个结果“错误代码%08lx检测到错误”。这是一个复制我的问题的示例代码:

int errCode = 0xA0B0C0D0;

void function(errpacket* ptr, int a, char* errString, ...);

typedef struct{
    int err;
    char errDesc;
}errpacket;

int main(){
    errpacket* a;
    void function(a, 10, "Error detected with error code %08lx", errCode);

    return 0;
}

void function(errpacket* ptr, int a, char* errString, ...){
    ptr->err = a;
    strcpy(&ptr->errDesc, errString);
}

如果我的实施不正确,请建议我做一些我想做的事情。另请指出上述代码中的错误。

4 个答案:

答案 0 :(得分:1)

  1. 在声明typedef

  2. 之前,您必须errpacket结构function(...)
  3. 函数a中的变量main()只是一个指针。如果您尝试写入未初始化的指针,则会在函数内部出现分段错误。

  4. 成员errDesc只能保存一个字符,而不是字符串或字符数组。

    试试这个......

    int errCode = 0xA0B0C0D0;
    
    typedef struct {
        int err;
        char* errDesc;   
    } errpacket;
    
    void function (errpacket* ptr, int a, char* errString, ...);
    
    int main () {
        errpacket a;
        function(&a, 10, "Error detected with error code %08lx", errCode);
        return 0;
    }
    
    void function (errpacket* ptr, int a, char* errString, ...) {
        ptr->err = a;
        ptr->errDesc = strdup( errString);
    }
    

答案 1 :(得分:0)

您不能使用单个char变量来保存整个字符串。

可以做的是将errDesc声明为固定长度的数组(如果知道错误描述可以包含的最大字符数),或指针使用malloc动态分配,然后使用free释放。

数组案例:

#define MAX_ERR_STRING_SIZE 500

typedef struct 
{
    int err;
    char errDesc[MAX_ERR_STRING_SIZE];
} errpacket;

// You can now use strcpy() to copy to errpacket::errDesc assuming none of the error strings exceed MAX_ERR_STRING_SIZE

动态记忆:

typedef struct 
{
    int err;
    char *errDesc;
} errpacket;

// Take note of the new parameter: int errStringLength, 
void function(errpacket* ptr, int a, char* errString, int errStringLength, ...){
    ptr->err = a;
    ptr->errDesc = malloc((errStringLength + 1) * sizeof(char));
    if(ptr->errDesc == NULL)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    strcpy(&ptr->errDesc, errString);
}

使用完ptr后,您需要致电free(ptr->errDesc);取消分配字符串。

答案 2 :(得分:0)

尝试此修复:

#include <stdarg.h> //to be added for vsprintf use

int errCode = 0xA0B0C0D0;

void function(errpacket* ptr, int a, char* errString, ...);

typedef struct{
    int err;
    char *errDesc;
}errpacket;

int main(){
    errpacket a; //you need allocate memory if you use a pointer here
    void function(&a, 10, "Error detected with error code %08lx", errCode);

    return 0;
}

void function(errpacket* ptr, int a, char* errString, ...){
    ptr->err = a;
    ptr->errDesc = malloc(strlen(errString)+1);
    memset(ptr->errDesc, 0, strlen(errString)+1);
    /*if(ptr->errDesc != NULL)
    {
        strcpy(ptr->errDesc, errString);
    }*/
   // use like following if you want use a formatted string
   if(ptr->errDesc != NULL)
   {
        va_list args;
        va_start (args, errString);
        vsprintf (ptr->errDesc, errString, args);
        va_end (args);
   }
}

答案 3 :(得分:0)

我认为你真的不想要一个带有变量参数的函数,比如printf。下面的解决方案只是期望你最终使用的参数。请注意,我不使用用户提供的格式字符串;这被认为是一种安全风险。我还使用snprintf(而不是简单的sprintf)来防止错误消息长于结构中的数组大小。数组大小是一个定义,因此可以轻松更改。

具体修正:

  • 正确的声明顺序(在使用之前定义结构类型)
  • 定义一个实际的错误包对象(而不只是一个未初始化的指针)
  • 在错误包中提供消息的实际内存
  • 提供错误包的打印功能
  • 不要让用户代码指定printf格式;打印用户提供的带有长度受保护的%s格式说明符的字符串。
  • 不要使用变量参数函数(无论如何都不评估其多余的参数);只需明确声明所需的参数。

#include<stdio.h>

int errCode = 0xA0B0C0D0;

#define MAX_ERRDESC_LEN 80 // avoid literals

typedef struct{
    int err;
    char errDesc[MAX_ERRDESC_LEN]; // provide actual space for the message
}errpacket;

void printErrPack(FILE *f, errpacket *ep){
    fprintf(f, "Error packet:\n");
    fprintf(f, "     err  = 0x%x:\n", ep->err);
    fprintf(f, "     desc = ->%s<-\n", ep->errDesc);
}

// Standard function with fixed argument count and types
void function(errpacket* ptr, int errNo, char* errString, int errCodeArg){
    ptr->err = errNo;

    // snprintf "prints" into a string
    snprintf(   ptr->errDesc,    // print destination
                MAX_ERRDESC_LEN, // max length, no buffer overflow
                "%s with error code %x", // do not use user string as format
                errString,       // user supplied string, printed via %s
                errCodeArg  );
}

int main(){
    errpacket a; // define an actual object, not a pointer

    // pass the address of the object a
    function(&a, 0xdead, "Error detected ", errCode);

    printErrPack(stdout, &a);
    return 0;
}