Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.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_Loops_Pointers_For Loop - Fatal编程技术网

循环的C参考

循环的C参考,c,loops,pointers,for-loop,C,Loops,Pointers,For Loop,我的C代码有问题 int split(char* source, char*** target, char* splitChar) { int i; int currentLength; int splitCharPosition; char* currentSubstring = source; int splitCount = charcount(source, splitChar) + 1; *target = (char**) mallo

我的C代码有问题

int split(char* source, char*** target, char* splitChar) {
    int i;
    int currentLength;
    int splitCharPosition;
    char* currentSubstring = source;
    int splitCount = charcount(source, splitChar) + 1;

    *target = (char**) malloc(splitCount * sizeof(char**));
    for(i=0;i<splitCount;i++) {
        splitCharPosition = indexOf(currentSubstring, splitChar);
        substring(currentSubstring, target[i], 0, splitCharPosition);
        currentLength = strlen(currentSubstring);
        substring(currentSubstring, &currentSubstring, splitCharPosition + 1, curr  entLength-splitCharPosition);
    }
    return splitCount;
}
编辑2:

int charcount(char* source, const char* countChar) {
int i;
int count = 0;
for(i=0;source[i];i++) {
    if(source[i] == countChar[0]) {
        count++;
    }
}
return count;
}
编辑3:

char* substring(char* source, char** target, int start, int length) {
    *target = (char*) malloc(length + 1);
    strncpy(*target, source + start, length);
    target[length] = '\0';
    return *target;
}
编辑4: 我只是注意到如果我加上

char* sndfpgjps = splitChar;

对于我的split()代码,它不会删除引用。有人知道为什么吗?

看看您的调试器是否也支持数据断点,即,如果内存中的某个位置被修改,就会中断。然后将一个放在splitChar的实际地址,另一个放在它指向的地址。(因为您没有指定指针是null还是指向nil。)查看它在哪里中断。这可能是一个完全无关的地方;这表示缓冲区溢出


此外,您至少可以使splitChar成为指向常量的指针。你其实不想修改它,对吧?更好的办法是,将其设置为字符,而不是指针,因为其名称表明只有一个字符可以拆分,而不是字符串。

子字符串的第一次调用看起来不正确:

substring(currentSubstring, target[i], 0, splitCharPosition);
我猜想它应该是如下所示,其中它对分配的实际内存进行了索引:

substring(currentSubstring, &((*target)[i]), 0, splitCharPosition);

首先需要获取目标指向的值(
*target
),然后从中索引并传递该数组位置的地址。

我不知道子字符串是什么,也不知道它有什么签名,但在行中

substring(currentSubstring, target[i], 0, splitCharPosition);
仅为i==0定义了目标[i]。我相信你想写作

substring(currentSubstring, (*target)[i], 0, splitCharPosition);
这一行:-

    substring(currentSubstring, &currentSubstring, splitCharPosition + 1, curr  entLength-splitCharPosition);
。。。将导致内存泄漏,并且效率极低。旧的子字符串悬空。永远也不会自由

最好是写

currentSubString += splitCharPosition + 1;
我不认为这是个问题,但这是个问题


另外,当您使用C库函数时,比如
strlen()
,为什么不使用
strtok
,或者更好的是,
strtok\u r

我对代码有一些保留,但这在
valgrind
下可以正常工作(没有泄漏,没有滥用)。除了常量字符串被标记为常量之外,我基本上没有改变子函数。
split()
中的代码已简化。正如我在评论中所指出的,我建议编写main
split()
函数,这样您就有了一个本地
char**string\u列表您分配和填充的代码。然后,当您准备返回时,分配
*target=string\u list。这将使你更容易理解正在发生的事情。三重间接是讨厌的。您可以在这里证明这一点(仅此而已),但要尽可能减少使用三点指针的时间。修订采用了这一战略

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern int split(const char *source, char ***target, const char *splitStr);

static int
indexOf(const char *source, const char *template)
{
    int i;
    int j;
    int index;
    for (i = 0; source[i]; i++)
    {
        index = i;
        for (j = 0; template[j]; j++)
        {
            if (source[i + j] != template[j])
            {
                index = -1;
                break;
            }
        }
        if (index != -1)
            return index;
    }
    return -1;
}

static int
charcount(const char *source, const char *countChar)
{
    int count = 0;
    for (int i = 0; source[i]; i++)
    {
        if (source[i] == countChar[0])
            count++;
    }
    return count;
}

static char *
substring(const char *source, int start, int length)
{
    char *target = (char *)malloc(length + 1);
    if (target != 0)
    {
        memmove(target, source + start, length);
        target[length] = '\0';
    }
    return target;
}

int
split(const char *source, char ***target, const char *splitStr)
{
    int    splitCount = charcount(source, splitStr) + 1;
    char **result = (char **)malloc(splitCount * sizeof(*result));

    if (result == 0)
        return -1;

    int    splitLength = strlen(splitStr);
    char **next = result;
    const char *currentSubstring = source;

    for (int i = 0; i < splitCount; i++)
    {
        int splitCharPosition = indexOf(currentSubstring, splitStr);
        if (splitCharPosition < 0)
            break;
        *next++ = substring(currentSubstring, 0, splitCharPosition);
        currentSubstring += splitCharPosition + splitLength;
    }
    *next++ = substring(currentSubstring, 0, strlen(currentSubstring));
    *target = result;
    return (next - result);     /* Actual number of strings */
}

static void print_list(int nstrings, char **strings)
{
    for (int i = 0; i < nstrings; i++)
    {
        if (strings[i] != 0)
            printf("%d: <<%s>>\n", i, strings[i]);
    }
}

static void free_list(int nstrings, char **strings)
{
    for (int i = 0; i < nstrings; i++)
        free(strings[i]);
    free(strings);
}

int main(void)
{
    const char source[] = "This is a string; it is really!";
    char **strings;
    int nstrings;

    nstrings = split(source, &strings, " ");
    printf("Splitting: <<%s>> on <<%s>>\n", source, " ");
    print_list(nstrings, strings);
    free_list(nstrings, strings);

    nstrings = split(source, &strings, "is");
    printf("Splitting: <<%s>> on <<%s>>\n", source, "is");
    print_list(nstrings, strings);
    free_list(nstrings, strings);

    return 0;
}
然后,您可以将指向其中一个的指针传递到
split()
,并传递到诸如
free\u list()
print\u list()
等实用程序函数中。然后,
free_list()
函数将修改结构,以便在释放结构指向的数据后,两个元素都归零

我还想使用不同的
indexOf()
实现:


在这里发布您的问题之前,您提到您使用了调试器,因此您获得了一张赞成票。这可能只是我的问题,但我觉得这段代码对于它试图实现的目标来说过于复杂。您触摸splitChar的唯一位置是在
indexOf()
中,所以请先查看(或显示函数)
splitChar
也被传递到
charcount()
,所以也给我们展示一下这个函数。
char***target
在我看来是一个非常糟糕的气味。用const尝试过,但仍然不起作用。名称可能选错了,我还想在字符串上拆分。你是对的。这就是我想做的。但不幸的是,这并不能解决我的问题。这是对一个问题的正确诊断。我建议编写main
split()
函数,这样您就有了一个本地
char**string\u列表您分配和填充的代码。然后,当您准备返回时,分配
*target=string\u list。这将使你更容易理解正在发生的事情。三重间接是讨厌的。您可以在这里证明这一点(仅此而已),但要尽可能减少使用三点指针的时间,如图所示。您是对的。这就是我想做的。但不幸的是,这并不能解决我的问题。是否有一个C库函数可以在字符串上拆分给定的字符串?标准C库中没有一个函数可以根据您想要的分隔符字符串拆分字符串。最接近的方法是
strtok()
函数,但它会在单个字符的任意选择上进行拆分,而不是在字符串上进行拆分(还有许多其他问题-如果可以,请避免
strtok()
;如果不能,请使用
strtok\u r()
strtok\u s()
)。一个原因是标准C库几乎在所有地方都避免了内存分配(当然除了
malloc()
realloc()
calloc()
free()
)。TR 24731-2将改变这一点;它没有被采纳到C2011中。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern int split(const char *source, char ***target, const char *splitStr);

static int
indexOf(const char *source, const char *template)
{
    int i;
    int j;
    int index;
    for (i = 0; source[i]; i++)
    {
        index = i;
        for (j = 0; template[j]; j++)
        {
            if (source[i + j] != template[j])
            {
                index = -1;
                break;
            }
        }
        if (index != -1)
            return index;
    }
    return -1;
}

static int
charcount(const char *source, const char *countChar)
{
    int count = 0;
    for (int i = 0; source[i]; i++)
    {
        if (source[i] == countChar[0])
            count++;
    }
    return count;
}

static char *
substring(const char *source, int start, int length)
{
    char *target = (char *)malloc(length + 1);
    if (target != 0)
    {
        memmove(target, source + start, length);
        target[length] = '\0';
    }
    return target;
}

int
split(const char *source, char ***target, const char *splitStr)
{
    int    splitCount = charcount(source, splitStr) + 1;
    char **result = (char **)malloc(splitCount * sizeof(*result));

    if (result == 0)
        return -1;

    int    splitLength = strlen(splitStr);
    char **next = result;
    const char *currentSubstring = source;

    for (int i = 0; i < splitCount; i++)
    {
        int splitCharPosition = indexOf(currentSubstring, splitStr);
        if (splitCharPosition < 0)
            break;
        *next++ = substring(currentSubstring, 0, splitCharPosition);
        currentSubstring += splitCharPosition + splitLength;
    }
    *next++ = substring(currentSubstring, 0, strlen(currentSubstring));
    *target = result;
    return (next - result);     /* Actual number of strings */
}

static void print_list(int nstrings, char **strings)
{
    for (int i = 0; i < nstrings; i++)
    {
        if (strings[i] != 0)
            printf("%d: <<%s>>\n", i, strings[i]);
    }
}

static void free_list(int nstrings, char **strings)
{
    for (int i = 0; i < nstrings; i++)
        free(strings[i]);
    free(strings);
}

int main(void)
{
    const char source[] = "This is a string; it is really!";
    char **strings;
    int nstrings;

    nstrings = split(source, &strings, " ");
    printf("Splitting: <<%s>> on <<%s>>\n", source, " ");
    print_list(nstrings, strings);
    free_list(nstrings, strings);

    nstrings = split(source, &strings, "is");
    printf("Splitting: <<%s>> on <<%s>>\n", source, "is");
    print_list(nstrings, strings);
    free_list(nstrings, strings);

    return 0;
}
typedef struct StringList
{
    size_t     nstrings;
    char     **strings;
} StringList;
int indexOf(const char *haystack, const char *needle)
{
    const char *pos = strstr(haystack, needle);
    if (pos != 0)
        return (pos - haystack);
    return -1;
}