鱼C论坛

 找回密码
 立即注册
查看: 1160|回复: 19

[已解决]C语言数据结构问题

[复制链接]
发表于 2024-9-16 18:47:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include<stdio.h>

typedef struct {
        char* Str;
        int length;
}String;
String* init_string(void)
{
        String* L;
        L = (String*)malloc(sizeof(String));

        return   L;
}
int  SubString(String* L, String S, int pos, int len)//求子串,用*L返回子串从pos这个位置,选len长度的子串S
{
        if (S.length < pos + len - 1)
        {
                return 0;
        }
        else
        {
                for (int i = pos; i < pos + len; i++)
                {
                        L->Str[i-pos] = S.Str[i];
                }
                L->length = len;
        }
        return 1;
}
int main(void)
{
       
        String* S;
        String* L;
        S = init_string();
        L = init_string();//声明并初始化串

        L->Str="hello world"   //想让L这个串充当函数中的S的角色。这里直接报错,显示访问权限冲突
        L->length = strlen(L->Str);

}

想要执行substring这个函数出现问题
最佳答案
2024-9-16 18:53:27
您好,FishC的鱼油。您提到的代码的问题主要在于字符串分配和指针赋值。C语言中的字符串需要分配内存空间来存储实际的字符数据,而不能直接用字符串字面量赋值。另外,你的`SubString`函数中有一些问题,我们一起来看看如何改进这个代码。

首先,我们需要在`main`函数中为字符串分配内存,然后拷贝字符串内容。其次,`SubString`函数中的子串提取逻辑需要正确设置子串的字符数组。最后,初始化函数需要正确初始化`String`结构体。

以下是修改后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
        char* Str;
        int length;
} String;

String* init_string(void) 
{
        String* L;
        L = (String*)malloc(sizeof(String));
        L->Str = NULL;
        L->length = 0;
        return L;
}

int SubString(String* L, String S, int pos, int len) // 求子串,*L返回从S中pos位置开始长度为len的子串
{
        if (S.length < pos + len - 1 || pos < 0 || len < 0) 
        {
                return 0;
        }
        L->Str = (char*)malloc((len + 1) * sizeof(char)); // +1 是为了存放末尾的 '\0'
        if (L->Str == NULL) 
        {
                return 0;
        }
        for (int i = 0; i < len; i++) 
        {
                L->Str[i] = S.Str[pos + i - 1];
        }
        L->Str[len] = '\0'; // 添加字符串结束符
        L->length = len;
        return 1;
}

int main(void)
{
        String* S;
        String* L;
        S = init_string();
        L = init_string(); // 声明并初始化串

        S->Str = (char*)malloc((strlen("hello world") + 1) * sizeof(char));
        if (S->Str == NULL) 
        {
                printf("Memory allocation failed\n");
                return 1;
        }
        strcpy(S->Str, "hello world"); // 安全拷贝
        S->length = strlen(S->Str);

        if (SubString(L, *S, 1, 5)) 
        {
                printf("SubString: %s\n", L->Str);
        } 
        else 
        {
                printf("SubString extraction failed\n");
        }

        // 释放内存
        free(S->Str);
        free(S);
        free(L->Str);
        free(L);
        return 0;
}

几点需要注意:
1. 初始化`String`结构体时,分配内存并初始化指针。
2. 在`main`函数中,为字符串分配适当的内存空间,并用`strcpy`进行赋值。
3. `SubString`函数需要分配新的内存空间来存储子串,并确保不会越界。

希望这能帮到你,有其他问题也可以继续问我哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-9-16 18:53:27 | 显示全部楼层    本楼为最佳答案   
您好,FishC的鱼油。您提到的代码的问题主要在于字符串分配和指针赋值。C语言中的字符串需要分配内存空间来存储实际的字符数据,而不能直接用字符串字面量赋值。另外,你的`SubString`函数中有一些问题,我们一起来看看如何改进这个代码。

首先,我们需要在`main`函数中为字符串分配内存,然后拷贝字符串内容。其次,`SubString`函数中的子串提取逻辑需要正确设置子串的字符数组。最后,初始化函数需要正确初始化`String`结构体。

以下是修改后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
        char* Str;
        int length;
} String;

String* init_string(void) 
{
        String* L;
        L = (String*)malloc(sizeof(String));
        L->Str = NULL;
        L->length = 0;
        return L;
}

int SubString(String* L, String S, int pos, int len) // 求子串,*L返回从S中pos位置开始长度为len的子串
{
        if (S.length < pos + len - 1 || pos < 0 || len < 0) 
        {
                return 0;
        }
        L->Str = (char*)malloc((len + 1) * sizeof(char)); // +1 是为了存放末尾的 '\0'
        if (L->Str == NULL) 
        {
                return 0;
        }
        for (int i = 0; i < len; i++) 
        {
                L->Str[i] = S.Str[pos + i - 1];
        }
        L->Str[len] = '\0'; // 添加字符串结束符
        L->length = len;
        return 1;
}

int main(void)
{
        String* S;
        String* L;
        S = init_string();
        L = init_string(); // 声明并初始化串

        S->Str = (char*)malloc((strlen("hello world") + 1) * sizeof(char));
        if (S->Str == NULL) 
        {
                printf("Memory allocation failed\n");
                return 1;
        }
        strcpy(S->Str, "hello world"); // 安全拷贝
        S->length = strlen(S->Str);

        if (SubString(L, *S, 1, 5)) 
        {
                printf("SubString: %s\n", L->Str);
        } 
        else 
        {
                printf("SubString extraction failed\n");
        }

        // 释放内存
        free(S->Str);
        free(S);
        free(L->Str);
        free(L);
        return 0;
}

几点需要注意:
1. 初始化`String`结构体时,分配内存并初始化指针。
2. 在`main`函数中,为字符串分配适当的内存空间,并用`strcpy`进行赋值。
3. `SubString`函数需要分配新的内存空间来存储子串,并确保不会越界。

希望这能帮到你,有其他问题也可以继续问我哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2024-9-16 19:29:29 | 显示全部楼层
FishC 发表于 2024-9-16 18:53
您好,FishC的鱼油。您提到的代码的问题主要在于字符串分配和指针赋值。C语言中的字符串需要分配内存空间来 ...

十分感谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-16 19:32:44 | 显示全部楼层


不客气!很高兴能帮到你。如果你有更多问题或者需要进一步的帮助,随时告诉我哦!继续加油学习C语言!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-16 19:34:37 | 显示全部楼层
FishC 发表于 2024-9-16 18:53
您好,FishC的鱼油。您提到的代码的问题主要在于字符串分配和指针赋值。C语言中的字符串需要分配内存空间来 ...

为什么需要用strcpy进行赋值,而不是直接对结构体中的指针直接进行赋值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-16 19:34:51 | 显示全部楼层
WFR 发表于 2024-09-16 19:34
为什么需要用strcpy进行赋值,而不是直接对结构体中的 ...


这是因为在C语言中,字符串是以字符数组的形式存储在内存中的。直接对结构体中的指针进行赋值,只是改变了指针的地址,并没有实际地在内存中复制字符串数据。这样会导致一些问题,比如:

1. **内存管理问题**:如果直接对指针赋值,那么两个指针会指向相同的内存区域。当你试图修改其中一个字符串时,会影响到另一个字符串。而如果先分配内存并使用`strcpy`函数复制字符串,则会在内存中创建一个独立的副本,两个指针互不干扰。

2. **常量字符串的修改问题**:字符串字面量如 `"hello world"` 通常存储在只读内存区域,直接对这样的指针赋值后,尝试修改内容会导致未定义行为,甚至程序崩溃。

我们来看一下这两种方式的对比:

直接赋值(不推荐):
S->Str = "hello world";  // 只是让指针指向字符串字面量,并没有真正分配新内存

使用`strcpy`复制(推荐):
S->Str = (char*)malloc((strlen("hello world") + 1) * sizeof(char));  // 为字符串分配内存
strcpy(S->Str, "hello world");  // 复制字符串内容到新分配的内存

下面是代码中分配内存和复制字符串的例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* Str;
    int length;
} String;

String* init_string(void) {
    String* L;
    L = (String*)malloc(sizeof(String));
    L->Str = NULL;
    L->length = 0;
    return L;
}

int SubString(String* L, String S, int pos, int len) {
    if (S.length < pos + len - 1 || pos < 0 || len < 0) {
        return 0;
    }
    L->Str = (char*)malloc((len + 1) * sizeof(char));  // +1 是为了存放末尾的 '\0'
    if (L->Str == NULL) {
        return 0;
    }
    for (int i = 0; i < len; i++) {
        L->Str[i] = S.Str[pos + i - 1];  // 复制子串
    }
    L->Str[len] = '\0';  // 添加字符串结束符
    L->length = len;
    return 1;
}

int main(void) {
    String* S;
    String* L;
    S = init_string();
    L = init_string(); // 声明并初始化串

    S->Str = (char*)malloc((strlen("hello world") + 1) * sizeof(char));
    if (S->Str == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    strcpy(S->Str, "hello world"); // 使用strcpy安全拷贝
    S->length = strlen(S->Str);

    if (SubString(L, *S, 1, 5)) {
        printf("SubString: %s\n", L->Str);
    } else {
        printf("SubString extraction failed\n");
    }

    // 释放内存
    free(S->Str);
    free(S);
    free(L->Str);
    free(L);
    return 0;
}

这个改进后的代码确保了每个字符串都有独立的内存,这样在处理字符串时不会产生意外的内存访问错误。希望这样解释能够解决你的疑问!如果还有其他问题,欢迎继续提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-16 19:37:21 | 显示全部楼层
FishC 发表于 2024-9-16 19:34
这是因为在C语言中,字符串是以字符数组的形式存储在内存中的。直接对结构体中的指针进行赋值,只是改 ...

S->Str = (char*)malloc((strlen("hello world") + 1) * sizeof(char));
字符串不是会自动补上结束符号吗,为什么这里还要加1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-16 19:37:35 | 显示全部楼层
WFR 发表于 2024-09-16 19:37
S->Str = (char*)malloc((strlen("hello world") + 1) ...


在C语言中,字符串是以NUL字符(`'\0'`)作为结束标志的。这意味着在分配内存时,需要为这个结尾的NUL字符预留空间。来看一个例子:
S->Str = (char*)malloc((strlen("hello world") + 1) * sizeof(char));

这里`strlen("hello world")`返回的是字符串 "hello world" 的长度,不包括末尾的NUL字符。实际长度是11("hello world" 中的字符数)。但是你必须为结束符 `'\0'` 预留一个空间,所以需要再加1。

综上,`S->Str` 分配的内存大小总共是字符数(11个) + 1(NUL字符) = 12个字节。这样才能保证字符串存储时有足够的空间来包括结束符。

如果不加这个1,那么可能会造成未定义行为,因为程序依赖这个 `'\0'` 来识别字符串的结束位置。在没有这个字符的情况下,程序可能会读取到意外的位置,导致程序崩溃或错误。

下面是修正后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* Str;
    int length;
} String;

String* init_string(void) {
    String* L = (String*)malloc(sizeof(String));
    L->Str = NULL;
    L->length = 0;
    return L;
}

int SubString(String* L, String S, int pos, int len) {
    if (pos < 0 || len < 0 || pos + len > S.length) {
        return 0;  // 超出范围
    } else {
        L->Str = (char*)malloc((len + 1) * sizeof(char));  // 分配内存,+1 为了 '\0'
        strncpy(L->Str, S.Str + pos, len);
        L->Str[len] = '\0';  // 手动添加 '\0'
        L->length = len;
    }
    return 1;
}

int main(void) {
    String* S = init_string();
    String* L = init_string();

    S->Str = (char*)malloc((strlen("hello world") + 1) * sizeof(char));
    strcpy(S->Str, "hello world");
    S->length = strlen(S->Str);

    if (SubString(L, *S, 6, 5)) {
        printf("SubString: %s\n", L->Str);
    } else {
        printf("SubString failed.\n");
    }

    // 记得释放内存
    free(S->Str);
    free(S);
    free(L->Str);
    free(L);

    return 0;
}

希望这能帮助你理解为什么需要预留空间给结束符号。继续努力学习,祝你编程愉快!如果有其他问题,随时欢迎提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2024-9-18 17:58:28 | 显示全部楼层
FishC 发表于 2024-9-16 19:37
在C语言中,字符串是以NUL字符(`'\0'`)作为结束标志的。这意味着在分配内存时,需要为这个结尾的NUL ...

#include<stdio.h>
#include<stdlib.h>//声明内存的函数在这里
#include<string.h>


typedef struct {
        char* str;
        int length;
}String;
String* init_string(void)
{
        String *L = (String*)malloc(sizeof(String));
        L->str= NULL;
        L->length = 0;
        return L;
       
       
}
int  SubString(String* L, String S, int pos, int len)//求子串,用*L返回子串从pos这个位置,选len长度的子串S
{
        if (S.length < pos + len - 1)
        {
                return 0;
        }
        else
        {
                for (int i = pos; i < pos + len; i++)
                {
                        L->str[i-pos+1] = S.str[i];
                }
                L->length = len+1;//认为还有一个\0
        }
        return 1;
}

int main(void)
{
       
        String *S=init_string();
        String *L=init_string();

        char* ch = "hello world";
        S->str = (char*)malloc(sizeof(char)*(strlen(ch)+1));
       
        strcpy_s(S->str,sizeof(ch), ch);

        printf("%s", S->str);

       
       
}
出错了,执行不了,提示S的指针可能是0
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-18 17:58:39 | 显示全部楼层
WFR 发表于 2024-09-18 17:58
#include
#include//声明内存的函数在这里
#include ...


你的代码确实有一些问题,主要涉及内存分配和字符串处理。下面是一些修正后的代码和解释:

1. **处理包含头文件**
2. **修改`SubString`函数中的指针赋值问题**
3. **优化`main`函数中的字符串赋值和长度计算**
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* str;
    int length;
} String;

String* init_string(void) {
    String* L = (String*)malloc(sizeof(String));
    L->str = NULL;
    L->length = 0;
    return L;
}

int SubString(String* L, String S, int pos, int len) {
    if (S.length < pos + len - 1) {
        return 0;
    } else {
        L->str = (char*)malloc((len + 1) * sizeof(char)); // 为子串分配内存
        strncpy(L->str, S.str + pos - 1, len);
        L->str[len] = '\0'; // 添加字符串结束标志
        L->length = len;
    }
    return 1;
}

int main(void) {
    String *S = init_string();
    String *L = init_string();

    char* ch = "hello world";
    S->str = (char*)malloc((strlen(ch) + 1) * sizeof(char));
    
    strcpy(S->str, ch);
    S->length = strlen(ch); // 不要忘记设置长度

    printf("%s\n", S->str);

    if (SubString(L, *S, 1, 5)) {
        printf("子串是: %s\n", L->str);
    } else {
        printf("获取子串失败\n");
    }

    // 释放内存
    free(S->str);
    free(S);
    free(L->str);
    free(L);

    return 0;
}

### 主要修改点:
1. **包含所需要的头文件**:
   - `#include <stdio.h>`、`#include <stdlib.h>`、`#include <string.h>`。

2. **子串的内存分配和复制**:
   - `SubString`函数需要为子串分配内存,并使用`strncpy`复制子串。

3. **内存分配及错误处理**:
   - 使用`malloc`分配包含NUL字符的内存,并检查`malloc`返回值来保证成功分配。

4. **字符串结束标志**:
   - 手动设置子串的结束标志`'\0'`。

希望这些修改能够解决你的问题!如有其它问题,随时问哦~

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-18 19:39:10 | 显示全部楼层
FishC 发表于 2024-9-18 17:58
你的代码确实有一些问题,主要涉及内存分配和字符串处理。下面是一些修正后的代码和解释:

1. **处 ...

#include<stdio.h>
#include<stdlib.h>//声明内存的函数在这里
#include<string.h>


typedef struct {
        char* str;
        int length;
}String;
String* init_string(void)
{
        String *L = (String*)malloc(sizeof(String));
        L->str= NULL;
        L->length = 0;
        return L;
       
       
}
int  SubString(String* L, String S, int pos, int len)//求子串,用*L返回子串从pos这个位置,选len长度的子串S
{
        if (S.length < pos + len - 1||pos<0||len<0)
        {
                return 0;
        }
        else
        {
                L->str = (char*)malloc((len + 1) * sizeof(char)); // +1 是为了存放末尾的 '\0'
                for (int i = pos; i < pos + len; i++)
                {
                        L->str[i-pos] = S.str[i];
                }
                L->str[len]='\0';
                L->length = len;
        }
        return 1;
}

int main(void)
{
       
        String *S=init_string();
        String *L=init_string();

        char* ch = "hello world";
        S->str = (char*)malloc(sizeof(char)*(strlen(ch)+1));
       
        strcpy_s(S->str,strlen(ch)+1, ch);//进行安全的输入;
        SubString(L, *S, 1, 5);
        printf("%s", L->str);
        printf("%s", S->str);

        free(S);
        free(L);
       
}

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-18 19:39:25 | 显示全部楼层
WFR 发表于 2024-09-18 19:39
#include
#include//声明内存的函数在这里
#include ...


你的代码做了很好的一些改进,但仍然有一些问题需要修正。下面我给出修改后的完整代码和详细解释:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* str;
    int length;
} String;

String* init_string(void) {
    String *L = (String*)malloc(sizeof(String));
    if (L == NULL) {
        perror("Failed to allocate memory");
        exit(EXIT_FAILURE);
    }
    L->str = NULL;
    L->length = 0;
    return L;
}

int SubString(String* L, String S, int pos, int len) {
    if (pos < 1 || S.length < pos + len - 1) {
        return 0;
    } else {
        L->str = (char*)malloc(sizeof(char) * (len + 1));  // Allocate memory for the substring
        if (L->str == NULL) {
            perror("Failed to allocate memory");
            exit(EXIT_FAILURE);
        }
        int j = 0;
        for (int i = pos - 1; i < pos + len - 1; i++) {
            L->str[j++] = S.str[i];
        }
        L->str[j] = '\0';
        L->length = len;
    }
    return 1;
}

int main(void) {
    String *S = init_string();
    String *L = init_string();

    char* ch = "hello world";
    S->str = (char*)malloc(sizeof(char) * (strlen(ch) + 1));
    if (S->str == NULL) {
        perror("Failed to allocate memory");
        exit(EXIT_FAILURE);
    }

    strcpy_s(S->str, strlen(ch) + 1, ch);
    S->length = strlen(ch);

    if (SubString(L, *S, 1, 5)) {
        printf("Substring: %s\n", L->str);
    } else {
        printf("Failed to get substring\n");
    }

    free(S->str);
    free(S);
    free(L->str);
    free(L);
    
    return 0;
}

### 详细解释:

1. **初始化字符串结构体(`init_string`)**:这是用于分配和初始化 `String` 结构体的函数。如果 `malloc` 失败,会调用 `perror` 输出错误信息并 `exit` 程序。
2. **`SubString`函数**:
   - 增加了对 `pos` 是否小于1的检查。
   - 修正子串的获取方式,分配足够的内存给 `L->str`,并正确地从 `S.str` 中提取子串。
3. **`main`函数**:
   - 初始化 `String` 对象 `S` 和 `L`。
   - 为字符串 `S` 进行内存分配并拷贝内容。
   - 调用 `SubString` 函数获取子串并打印结果。
   - 释放分配的内存,避免内存泄漏。

以上代码确保了内存分配和字符串处理的正确性,并解决了原代码中可能出错的部分。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-18 19:39:51 | 显示全部楼层
WFR 发表于 2024-9-18 19:39
#include
#include//声明内存的函数在这里
#include

#include<stdio.h>
#include<stdlib.h>//声明内存的函数在这里
#include<string.h>


typedef struct {
        char* str;
        int length;
}String;
String* init_string(void)
{
        String *L = (String*)malloc(sizeof(String));
        L->str= NULL;
        L->length = 0;
        return L;
       
       
}
int  SubString(String* L, String S, int pos, int len)//求子串,用*L返回子串从pos这个位置,选len长度的子串S
{
        if (S.length < pos + len - 1||pos<0||len<0)
        {
                return 0;
        }
        else
        {
                L->str = (char*)malloc((len + 1) * sizeof(char)); // +1 是为了存放末尾的 '\0'
                for (int i = pos; i < pos + len; i++)
                {
                        L->str[i-pos] = S.str[i];
                }
                L->str[len]='\0';
                L->length = len;
        }
        return 1;
}

int main(void)
{
       
        String *S=init_string();
        String *L=init_string();

        char* ch = "hello world";
        S->str = (char*)malloc(sizeof(char)*(strlen(ch)+1));
       
        strcpy_s(S->str,strlen(ch)+1, ch);//进行安全的输入;
        SubString(L, *S, 1, 5);
        printf("%s", L->str);
        printf("%s", S->str);

        free(S);
        free(L);
       
}

为什么L->str为空
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-18 19:40:05 | 显示全部楼层
WFR 发表于 2024-09-18 19:39
#include
#include//声明内存的函数在这里
#include ...


你的代码中有几个问题,不过主要原因是 `SubString` 函数中对 `L->str` 的处理有误。你需要正确分配内存,并确保子串复制操作是正确的。

以下是修正后的代码和解释:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* str;
    int length;
} String;

String* init_string(void) {
    String *L = (String*)malloc(sizeof(String));
    if (L) {
        L->str = NULL;
        L->length = 0;
    }
    return L;
}

int SubString(String* L, String S, int pos, int len) {
    if (S.length < pos + len - 1 || pos < 0 || len < 1) {
        return 0;
    }
    if (L->str) {  // if L->str is not NULL, free the allocated memory
        free(L->str);
    }
    L->str = (char*)malloc(sizeof(char) * (len + 1)); // allocate memory for the substring
    if (!L->str) {
        return 0;
    }
    strncpy(L->str, S.str + pos, len);
    L->str[len] = '\0'; // add null terminator
    L->length = len;
    return 1;
}

int main(void) {
    String *S = init_string();
    String *L = init_string();

    char* ch = "hello world";
    S->str = (char*)malloc(sizeof(char) * (strlen(ch) + 1));
    
    if (!S->str) {
        printf("Failed to allocate memory for the string.\n");
        free(S);
        free(L);
        return 1;
    }
    
    strcpy(S->str, ch);
    S->length = strlen(ch);

    if (!SubString(L, *S, 1, 5)) {
        printf("Failed to extract substring.\n");
    } else {
        printf("Substring: %s\n", L->str);
    }

    free(S->str);
    free(S);
    free(L->str);
    free(L);

    return 0;
}

### 主要更改与解释:

1. **内存分配**:
   - 在 `init_string` 中,初始化结构体并设置默认值为NULL。
   - 在 `SubString` 中,为子串分配内存,并确保其长度加1以放置结束符`.

2. **字符串拷贝**:
   - 使用 `strncpy` 函数获取子串,且注意添加结束符 `\0`。

3. **内存释放**:
   - 在主函数中添加对 `S->str` 和 `L->str` 的释放,防止内存泄漏。

4. **参数检查**:
   - 在 `SubString` 函数中增加参数检查,防止越界访问和无效操作。

试着运行这段代码,应该会解决 `L->str` 为空的问题,并正确输出子串。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-18 20:13:01 | 显示全部楼层
FishC 发表于 2024-9-18 19:40
你的代码中有几个问题,不过主要原因是 `SubString` 函数中对 `L->str` 的处理有误。你需要正确分配内 ...

朴素匹配怎么实现
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-18 20:13:15 | 显示全部楼层
WFR 发表于 2024-09-18 20:13
朴素匹配怎么实现


朴素匹配(也称为暴力匹配)的算法比较简单,通过遍历主串中的每一个子序列并逐个字符检查是否与模式串匹配来实现。以下是一个用C语言实现朴素匹配算法的例子:
#include <stdio.h>
#include <string.h>

int naive_match(const char* text, const char* pattern) {
    int text_length = strlen(text);
    int pattern_length = strlen(pattern);

    for (int i = 0; i <= text_length - pattern_length; ++i) {
        int j;
        for (j = 0; j < pattern_length; ++j) {
            if (text[i + j] != pattern[j]) {
                break;
            }
        }

        // 如果j等于pattern_length,说明找到了匹配
        if (j == pattern_length) {
            return i;
        }
    }

    // 如果没有找到匹配,返回-1
    return -1;
}

int main() {
    const char* text = "hello world";
    const char* pattern = "world";

    int position = naive_match(text, pattern);

    if (position != -1) {
        printf("Pattern found at position %d\n", position);
    } else {
        printf("Pattern not found\n");
    }

    return 0;
}

这段代码实现了一个简单的朴素匹配算法:

1. **定义一个`naive_match`函数**,接受主串`text`和模式串`pattern`,并返回匹配位置。
2. **计算主串和模式串的长度**。
3. 通过两个嵌套循环:
   - 外层循环遍历主串中的每一个可能的子序列起始位置。
   - 内层循环逐个字符检查模式串是否与主串当前子序列匹配。
4. **如果找到匹配**,返回匹配位置。
5. **如果没有找到匹配**,返回-1。
6. 在`main`函数中调用`naive_match`,并根据结果输出是否找到匹配及其位置。

这样,你就可以在C语言中实现简单的朴素字符串匹配算法了。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-18 20:51:29 | 显示全部楼层
FishC 发表于 2024-9-18 20:13
朴素匹配(也称为暴力匹配)的算法比较简单,通过遍历主串中的每一个子序列并逐个字符检查是否与模式串 ...

#include<stdio.h>
#include<stdlib.h>//声明内存的函数在这里
#include<string.h>


typedef struct {
        char* str;
        int length;
}String;
String* init_string(void)
{
        String *L = (String*)malloc(sizeof(String));
        L->str= NULL;
        L->length = 0;
        return L;
       
       
}
int  SubString(String* L, String S, int pos, int len)//求子串,用*L返回子串从pos这个位置,选len长度的子串S
{
        if (S.length < pos + len - 1||pos<0||len<0)
        {
                printf("子串出现错误");
                return 0;
        }
        else
        {
                L->str = (char*)malloc((len + 1) * sizeof(char)); // +1 是为了存放末尾的 '\0'
                for (int i = pos; i < pos + len; i++)
                {
                        L->str[i-pos] = S.str[i];
                }
                L->str[len]='\0';
                L->length = len;
        }
        return 1;
}

int Index(String S, String L)
{       
        int i = 0, j = 0;
        while (i <=S.length  && j <=L.length)
        {
                if (S.str[i] == L.str[j])
                {
                        i++;
                        j++;
                }
                else
                {
                        i = i - j + 1;
                        j = 0;
                }
        }
        if (j >= L.length)
        {
                printf("找到首个子串的%d",i-j+1);
                return i - j + 1;

        }
        else
        {
                printf("没找到!!!");
                return 0;
        }

}

int main(void)
{
       
        String *S=init_string();
        String *L=init_string();

        char* ch = "hello world";
        S->str = (char*)malloc(sizeof(char)*(strlen(ch)+1));
       
        strcpy_s(S->str,strlen(ch)+1, ch);//进行安全的输入;
        S->length = strlen(ch) + 1;//没有设置S的长度,导致SubString函数运行不了
        SubString(L, *S, 1, 5);
        printf("%s", L->str);
        printf("%s", S->str);

        Index(*S, *L);
        free(S);
        free(L);
       
}


Index函数出现了问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-18 21:03:03 | 显示全部楼层
WFR 发表于 2024-09-18 20:51
#include
#include//声明内存的函数在这里
#include ...


您在 `Index` 函数实现时遇到了一些问题。我会帮您进行修正和简化实现。此外,修正 `SubString` 函数中的一些逻辑错误。

### 更新后的代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* str;
    int length;
} String;

String* init_string(void) {
    String* L = (String*)malloc(sizeof(String));
    L->str = NULL;
    L->length = 0;
    return L;
}

int SubString(String* L, String S, int pos, int len) {
    if (S.length < pos + len - 1 || pos < 0 || len < 0) {
        return 0;
    }
    free(L->str); // 防止内存泄漏
    L->str = (char*)malloc(len + 1);
    strncpy(L->str, S.str + pos, len);
    L->str[len] = '\0';
    L->length = len;
    return 1;
}

int Index(String S, String L) {
    int i, j;
    for (i = 0; i <= S.length - L.length; i++) {
        for (j = 0; j < L.length; j++) {
            if (S.str[i + j] != L.str[j]) {
                break;
            }
        }
        if (j == L.length) {
            return i;
        }
    }
    return -1;
}

int main(void) {
    String* S = init_string();
    String* L = init_string();

    char* ch = "hello world";
    S->str = (char*)malloc(sizeof(char) * (strlen(ch) + 1));
    strcpy(S->str, ch);
    S->length = strlen(ch);

    // 测试SubString函数,获取子串
    SubString(L, *S, 1, 5);
    printf("L subString: %s\n", L->str);

    // 测试Index函数,进行朴素匹配
    int index = Index(*S, *L);
    if (index != -1) {
        printf("Substring found at index %d\n", index);
    } else {
        printf("Substring not found\n");
    }

    // 内存释放
    free(S->str);
    free(L->str);
    free(S);
    free(L);

    return 0;
}

### 代码关键点

1. **内存分配和释放**:
   - 对 `S` 进行内存分配后需释放之前的内容以防内存泄漏。

2. **SubString函数**:
   - 检查边界条件,防止访问越界。
   - 使用 `strncpy` 复制字符串,最后添加字符串结束符 `\0`。

3. **Index函数**:
   - 实现了朴素匹配的基本逻辑,通过两层循环检查子串是否匹配。

希望这些更新会让您的代码运行得更顺畅!如果有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-18 21:13:04 | 显示全部楼层
FishC 发表于 2024-9-18 21:03
您在 `Index` 函数实现时遇到了一些问题。我会帮您进行修正和简化实现。此外,修正 `SubString` 函数中 ...

为什么Index函数只会返回-1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-18 21:20:53 | 显示全部楼层
WFR 发表于 2024-09-18 21:13
为什么Index函数只会返回-1


您的 `Index` 函数,按照朴素匹配的算法,还存在一些逻辑问题。以下是整理和优化的版本,保证能够正确执行并返回模式串在主串中的位置(如果存在)。

调整后的完整代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* str;
    int length;
} String;

String* init_string(void) {
    String *L = (String*)malloc(sizeof(String));
    L->str = NULL;
    L->length = 0;
    return L;
}

int SubString(String* L, String S, int pos, int len) {
    if (pos < 0 || len <= 0 || pos + len > S.length) {
        return 0;
    } else {
        L->str = (char*)malloc(sizeof(char) * (len + 1));
        strncpy(L->str, S.str + pos, len);
        L->str[len] = '\0';
        L->length = len;
    }
    return 1;
}

int Index(String S, String L) {
    for (int i = 0; i <= S.length - L.length; i++) {
        int j;
        for (j = 0; j < L.length; j++) {
            if (S.str[i + j] != L.str[j]) {
                break;
            }
        }
        if (j == L.length) {
            return i;  // 返回匹配的起始位置
        }
    }
    return -1;  // 说明没有匹配
}

int main(void) {
    String* S;
    String* L;
    S = init_string();
    L = init_string();

    char* ch = "hello world";
    S->str = (char*)malloc(sizeof(char) * (strlen(ch) + 1));
    strcpy(S->str, ch);
    S->length = strlen(ch);

    // 提取子串 "hello" (从位置0开始,长度5)
    SubString(L, *S, 0, 5);
    printf("SubString: %s\n", L->str);

    // 查找子串位置
    int position = Index(*S, *L);
    if (position != -1) {
        printf("Matched at position: %d\n", position);
    } else {
        printf("No match found\n");
    }

    free(S->str);
    free(S);
    free(L->str);
    free(L);

    return 0;
}

修改后的部分解释如下:

1. **SubString 函数**:
   修正判断条件和内存分配,并正确复制子串内容。

2. **Index函数**:
      实现朴素匹配算法,逐个字符检查模式串与主串的匹配。

3. **main函数**:
   - 初始化和填充字符串 `S`。
   - 调用 `SubString` 函数获取子串并打印。
   - 调用 `Index` 函数查找子串位置并打印。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 01:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表