Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C运行时错误中的拆分函数_C_Pointers - Fatal编程技术网

C运行时错误中的拆分函数

C运行时错误中的拆分函数,c,pointers,C,Pointers,我在运行C程序时遇到运行时错误, 以下是C源代码(解析略低一点的.h头代码): 提前谢谢,我没有全部编程,只是从一些地方取了一些片段,但大部分是我的编程,谢谢 该函数的目的是,如果作为参数传递的条件为false,它将停止程序。这告诉您,当您运行程序时,idx!=第69行计数-1。我没有花时间检查程序执行时的导入,但显然(?)idx的目的是在那里等于count-1 这有用吗?有很多问题。我忽略了分为两个文件的代码;我将其视为一个单独的文件(请参见问题的注释) 不要使用get()。切勿使用get()

我在运行C程序时遇到运行时错误, 以下是C源代码(解析略低一点的.h头代码):

提前谢谢,我没有全部编程,只是从一些地方取了一些片段,但大部分是我的编程,谢谢

该函数的目的是,如果作为参数传递的条件为false,它将停止程序。这告诉您,当您运行程序时,
idx!=第69行计数-1
。我没有花时间检查程序执行时的导入,但显然(?)
idx
的目的是在那里等于
count-1


这有用吗?

有很多问题。我忽略了分为两个文件的代码;我将其视为一个单独的文件(请参见问题的注释)

  • 不要使用
    get()
    。切勿使用
    get()
    。永远不要使用
    get()
    。我说了三遍;这一定是真的。请注意,
    gets()
    不再是标准的C函数(它已从C11标准ISO/IEC 9899:2011中删除),因为它不能安全使用。改用
    fgets()
    或其他安全函数

  • 您不需要为10个字符的字符串使用动态内存分配;使用局部变量(更简单)

  • 你需要一根更大的绳子——想想4096吧

  • 你不检查你是否有任何数据;始终检查输入函数调用

  • 您没有释放
    main()
    末尾的所有子字符串,从而导致内存泄漏

  • 一个主要问题是
    Split()。
    strtok()
    函数具有破坏性。它还将多个相邻分隔符视为单个分隔符。您的代码无法解释差异

  • 另一个主要问题是根据传递到
    Split()
    函数中的分隔符分析字符串,但使用
    strtok(…,',')
    来实际拆分逗号。这与评论和名字更为一致,但完全误导了你。这就是您的断言被激发的原因

  • 您不需要包含
    ,除非您正在使用它提供的额外设施。你不是,所以你不应该包括它
    完美地声明了
    malloc()
    free()

  • 这个代码对我有用;我已经注释了我所做更改的大部分地方

    #include <assert.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static int altSplitLen(char **array);
    static char **Split(char *a_str, const char a_delim);
    static int SplitLen(char *src, char sep);
    
    int main(void)
    {
        printf("Enter text separated by single spaces:\n");
        char a[4096];       // Simpler
        if (fgets(a, sizeof(a), stdin) != 0)    // Error checked!
        {
            char **aa = Split(a, ' ');
            int k = SplitLen(a, ' ');
            printf("SplitLen() says %d; altSplitLen() says %d\n", k, altSplitLen(aa));
    
            for (int i = 0; i < k; i++)
            {
                printf("%s\n", aa[i]);
            }
    
            /* Workaround for broken SplitLen() */
            {
            puts("Loop to null pointer:");
            char **data = aa;
            while (*data != 0)
                printf("[%s]\n", *data++);
            }
    
            {
            // Fix for major leak!
            char **data = aa;
            while (*data != 0)
                free(*data++);
            }
            free(aa);       // Major leak!
        }
        return 0;
    }
    
    char **Split(char *a_str, const char a_delim)
    {
        char **result    = 0;
        size_t count     = 0;
        char *tmp        = a_str;
        char *last_comma = 0;
    
        /* Count how many elements will be extracted. */
        while (*tmp)
        {
            if (a_delim == *tmp)
            {
                count++;
                last_comma = tmp;
            }
            tmp++;
        }
        /* Add space for trailing token. */
        count += last_comma < (a_str + strlen(a_str) - 1);
    
        /* Add space for terminating null string so caller
           knows where the list of returned strings ends. */
        count++;
        result = malloc(sizeof(char *) * count);
    
        if (result)
        {
            char delim[2] = { a_delim, '\0' };  // Fix for inconsistent splitting
            size_t idx  = 0;
            char *token = strtok(a_str, delim);
    
            while (token)
            {
                assert(idx < count);
                *(result + idx++) = strdup(token);
                token = strtok(0, delim);
            }
            assert(idx == count - 1);
            *(result + idx) = 0;
        }
        return result;
    }
    
    int SplitLen(char *src, char sep)
    {
        int result = 0;
        for (size_t i = 0; i < strlen(src); i++)
        {
            if (src[i] == sep)
            {
                result += 1;
            }
        }
        return result;
    }
    
    static int altSplitLen(char **array)
    {
        int i = 0;
        while (*array++ != 0)
            i++;
        return i;
    }
    

    请注意,
    fgets()
    保留换行符,而
    gets()
    不保留,因此换行符包含在输出中。还要注意
    printf()
    打印数据如何显示字符串的限制;这在很多情况下都非常有用。

    欢迎使用堆栈溢出。请尽快阅读这一页。使用
    malloc()
    分配10个字节非常小(例如,使用4096),并且没有什么意义(局部变量更简单)。然后使用
    gets()
    读取数据是一场灾难-决不,决不,决不,决不使用
    gets()
    !(它不再是标准C11的一部分。)甚至在玩具程序中也没有。你会因为使用断言而得到一些补偿。您需要学习如何使用调试器,或者如何插入打印语句,以便为您提供查看出错原因所需的信息。您听说过调试器吗?这将比发布大量代码还要快,同时,头文件通常不应该包含函数定义;当它们这样做时,它们应该是
    静态内联
    函数。将声明放在头文件(
    parsing.h
    )中,将定义放在单独的源文件(
    parsing.c
    )中,分别编译主程序文件和
    parsing.c
    文件,并将它们链接在一起。虽然在这种情况下您可以不受影响,但您所做的事情是不可伸缩的(只要有多个源文件需要使用这些函数,您就处于失败的境地)。我现在使用的是scanf(),没有错误,但没有显示任何内容。@JonathanLeffler,所以您现在(希望也是这样)理解我的沮丧;-)任何C编译器都不能混淆
    assert
    中的表达式。如果它确实被弄糊涂了,它就不是一个C编译器。括号是不必要的。如果我对断言行进行注释,那么在它打印两个值之后就会出现分段错误,但我隐藏了一点Split()代码,所以我不太清楚它是如何工作的,我希望很快能阅读关于这个主题的教程。谢谢你对这个问题的见解。@JonathanLeffler好的,谢谢!我现在删除了答案的这一部分。非常感谢!,它起作用了,我本可以给你的答案打分,但我只有1分:(.无论如何,谢谢你:):)唯一的问题是你在for循环中使用了decelleration,我的编译器不是C99:)好奇:你的代码在
    char*a=malloc(10)之前有一个
    printf()
    语句,所以我认为它是安全的-似乎您必须使用C99编译器才能使其合法。然而,也许你在Windows上使用MSVC。在这种情况下,你必须移动一些东西,但是变化很小。如果您使用的编译器只支持20多年前的标准,而不是10多年前的标准或几年前的标准,那么有必要指出这一点(或者至少提及这一点)。大多数公司都会设法解决问题,使它们不会过时20年。我使用的是带GCC的linux。或者在“软呢帽”上。所以这很奇怪。
    #include <string.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <assert.h>
    
    char** Split(char* a_str, const char a_delim)
    {
        char** result    = 0;
        int count     = 0;
        char* tmp        = a_str;
        char* last_comma = 0;
        /* Count how many elements will be extracted. */
        while (*tmp)
        {
            if (a_delim == *tmp)
            {
                count++;
                last_comma = tmp;
            }
            tmp++;
        }
        /* Add space for trailing token. */
        count += last_comma < (a_str + strlen(a_str) - 1);
    
        /* Add space for terminating null string so caller
           knows where the list of returned strings ends. */
        count++;
        result = malloc(sizeof(char*) * count);
    
        if (result)
        {
            size_t idx  = 0;
            char* token = strtok(a_str, ",");
    
            while (token)
            {
                assert(idx < count);
                *(result + idx++) = strdup(token);
                token = strtok(0, ",");
            }
            assert(idx == count - 1);
            *(result + idx) = 0;
        }
        return result;
    }
    
    int SplitLen(char *src, char sep)
    {
        int result = 0;
        int i;
        for(i = 0; i<strlen(src); i++)
        {
            if(src[i] == sep)
            {
                result += 1;
            }
        }
        return result;
    }
    
    a.out: parsing.h:69: Split: Assertion `idx == count - 1' failed.
    Aborted
    
    #include <assert.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static int altSplitLen(char **array);
    static char **Split(char *a_str, const char a_delim);
    static int SplitLen(char *src, char sep);
    
    int main(void)
    {
        printf("Enter text separated by single spaces:\n");
        char a[4096];       // Simpler
        if (fgets(a, sizeof(a), stdin) != 0)    // Error checked!
        {
            char **aa = Split(a, ' ');
            int k = SplitLen(a, ' ');
            printf("SplitLen() says %d; altSplitLen() says %d\n", k, altSplitLen(aa));
    
            for (int i = 0; i < k; i++)
            {
                printf("%s\n", aa[i]);
            }
    
            /* Workaround for broken SplitLen() */
            {
            puts("Loop to null pointer:");
            char **data = aa;
            while (*data != 0)
                printf("[%s]\n", *data++);
            }
    
            {
            // Fix for major leak!
            char **data = aa;
            while (*data != 0)
                free(*data++);
            }
            free(aa);       // Major leak!
        }
        return 0;
    }
    
    char **Split(char *a_str, const char a_delim)
    {
        char **result    = 0;
        size_t count     = 0;
        char *tmp        = a_str;
        char *last_comma = 0;
    
        /* Count how many elements will be extracted. */
        while (*tmp)
        {
            if (a_delim == *tmp)
            {
                count++;
                last_comma = tmp;
            }
            tmp++;
        }
        /* Add space for trailing token. */
        count += last_comma < (a_str + strlen(a_str) - 1);
    
        /* Add space for terminating null string so caller
           knows where the list of returned strings ends. */
        count++;
        result = malloc(sizeof(char *) * count);
    
        if (result)
        {
            char delim[2] = { a_delim, '\0' };  // Fix for inconsistent splitting
            size_t idx  = 0;
            char *token = strtok(a_str, delim);
    
            while (token)
            {
                assert(idx < count);
                *(result + idx++) = strdup(token);
                token = strtok(0, delim);
            }
            assert(idx == count - 1);
            *(result + idx) = 0;
        }
        return result;
    }
    
    int SplitLen(char *src, char sep)
    {
        int result = 0;
        for (size_t i = 0; i < strlen(src); i++)
        {
            if (src[i] == sep)
            {
                result += 1;
            }
        }
        return result;
    }
    
    static int altSplitLen(char **array)
    {
        int i = 0;
        while (*array++ != 0)
            i++;
        return i;
    }
    
    $ parsing
    Enter text separated by single spaces:
    a b c d e f gg hhh iii jjjj exculpatory evidence
    SplitLen() says 0; altSplitLen() says 12
    Loop to null pointer:
    [a]
    [b]
    [c]
    [d]
    [e]
    [f]
    [gg]
    [hhh]
    [iii]
    [jjjj]
    [exculpatory]
    [evidence
    ]
    $