1

我已经写了大约一个星期的 C,所以请耐心等待。我在方法中遇到分段错误错误,assemble_url我不知道为什么。这是我的代码:

/** Includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>

/** Definitions */
#define MAX_OPTIONS 32
#define MAX_ARGS 32

/** Command option */
typedef struct {
    char *argname;
    char *value;
} command_option;

/** Command */
typedef struct {
    command_option options[MAX_OPTIONS];
} command_t;

/**
 * Prints the arguments passed in in a hashmap format (key => value)
 */
void populate_command(command_t *cmd,int argc,char *argv[])
{
    int i,j=0;

    /** Check to see if we have arguments. If argc is equal to 1 than there are no arguments besides the filename */
    if(argc>1)
    {

        /* Start at position 1, since argv[0] is the filename being called */
        for(i=1;i<argc;i++)
        {

            /* Head of argv array */
            char *arg = argv[i];

            /* Create a copy of head for traversal. */
            char *c = arg;

            /* traverse the char array, ensuring we arent dealing with NULL values(c!==NULL) and NULL pointers(*c!=='\0') */
            while(*c != '\0' && c != NULL)
            {

                /* Were only concerned with parsing the flags and obtaining the flag value. */
                if(strchr("-",*c))
                {

                    char *key = c; /* Key */
                    char *value = argv[i+1]; /* Value */

                    /* ensure we have a value existent for key */
                    if(strchr("-",*value))
                    {
                        /** user supplied a key with no value */
                        break;
                    }
                    command_option *option = &cmd->options[j];
                    option->argname = key;
                    option->value   = value;

                    j++;

                    /* Debug dump */
                    printf("arg %d: %s -> %s\n",i,option->argname,option->value);

                }/* end strchr */

                /** Increment the traversal array */
                c++;

            }/* end while loop */

        }/* end forloop */

    }/* endif */

}/** end print_args */

/**
 * Concatenates two strings and returns the resulting concatenated string
 */
char* concatstring(char *s1,char *s2)
{
    /* Allocate memory for *result. We add 1 to account for the extra byte to store the null character. Strlen accounts for all
     non-null bytes, so using strlen(s1) + strlen(s2) + 1 ensures that an overflow wont occur. An overflow occurs when
     the number of bytes being used (in our example, is the addition of strlen for s1 and s2) is more than the number of bytes
     allocated (in our example, the number of bytes allocated to *result)*/
    char *result = malloc(strlen(s1)+strlen(s2)+1);

    /*Copies the C string pointed by source(s1) into the array pointed by destination(result), including the terminating null character. */
    strcpy(result,s1);

    /* appends a copy of the source string(s2) to the destination string(result). The terminating null character in
     destination is overwritten by the first character of source, and a null-character is included at
     the end of the new string formed by the concatenation of both in destination.*/
    strcat(result,s2);

    /* return result */
    return result;

} /** end concatstring */

char* assemble_url(command_t *cmd,char *str)
{
    int i,opt_len = sizeof(&cmd->options);
    for(i=0;i<opt_len;i++)
    {
        command_option *option = &cmd->options[i];
        char *key = option->argname;
        char *value = option->value;
        if(i==0)
        {
            str = concatstring(str,key);
            str = concatstring(str,"=");
            str = concatstring(str,value);
        }
        else
        {
            str = concatstring(str,"&");
            str = concatstring(str,key);
            str = concatstring(str,"=");
            str = concatstring(str,value);
        }
    }
    return str;
}

该程序中发生的情况如下:

1./用户键入程序名称和标志选项,例如: program -test a -test2 b

2./程序解析命令并用选项填充命令结构。每个选项都有一个标志(argname)和与之关联的值(值)

3./ 然后程序尝试使用这些选项键和值创建一个 URL,例如http://url/?test=a&test2=b

该程序可以编译,但我对指针和引用仍然不熟悉(我认为 & 被称为引用),所以也许这就是程序出错的原因。

任何帮助是极大的赞赏!另外,如果您看到任何处理 assemble_url 的问题或更好的方法,也请告诉我(我不认为它的处理方式最好,但就像我说的,我对 C 编程非常陌生)

谢谢!

4

3 回答 3

1

因为您要连接两个以上的字符串,所以最好一次为所有连接分配内存。

#include <stdarg.h>
#include <string>
char* stringBuilder(int count, ...)
{
    va_list ap, vacnt;
    int j;
    int len = 1;
    char* buffer;
    va_start(ap, count); 
#ifdef va_copy
        va_copy(vacnt,ap);
#else
    vacnt = ap;
#endif
    for(j=0; j<count; ++j){
        len+=strlen(va_arg(vacnt, char*)); 
    }
    va_end(vacnt);
    buffer = (char*) malloc(len * sizeof(char));
    buffer[0]=0;
    for (j=0;j<count;++j) {
       strcat (buffer, va_arg(ap, char*));
    }
    va_end(ap);
    return buffer;
 }

您可以这样使用它:

char* x = stringBuilder(4,"hello", " ", "world", "\n");
printf(x);
free(x);

另请注意,键和值都必须为您的应用程序的目的进行 URL 编码

于 2013-04-08T14:22:04.647 回答
1

这个初始化

int opt_len = sizeof(&cmd->options);

会给你一个指针的字节大小&cmd->options。在您尝试做的事情的背景下,这没有任何意义。

如果要确定数组中的元素数(假设它没有衰减为指针),正确的技术是

int opt_len = sizeof cmd->options / sizeof *cmd->options;

在这种情况下opt_len,将使用MAX_OPTIONSvalue 进行初始化(这意味着您可以MAX_OPTIONS在其位置使用)。

于 2012-11-26T08:51:39.053 回答
1

concatstring 导致大量内存泄漏。每次调用都会分配一个新的缓冲区,但您从不费心去释放它们,并且您释放了指针,因此没有机会再次释放该内存。

这不是段错误的原因。

于 2012-11-26T08:53:35.367 回答