C primer plus (第六版)第十一章 编程练习第8题

题目:

8.编写⼀个名为string_in()的函数,接受两个指向字符串的指针作为参数。如果第2个字符串包含在第1个字符串中,该函数将返回第1个字符串开始的地址。例如,string_in("hats", "at")将返回hats中a的地址。否则,该函数返回空指针。在⼀个完整的程序中测试该函数,使⽤⼀个循环给函数提供输⼊值。

思路:

  1. 原书编程练习答案提供的思路是用strncmp()函数,比较2个字符串,从而得出第二个字符串是否包含在第一个字符串中。

  2. 另一个思路是逐个字符进行比较,如果第一个字符相同,再比较第二个字符,以此类推。

  3. 题目要求是在一个完整的程序中测试,使⽤⼀个循环给函数提供输⼊值,与之前题目类似,用while()循环+输入提示提示用户进行循环输入并调用函数测试,直到输入的是空行退出。

程序1(逐个字符比较+AI编写的对应函数):

cpp 复制代码
// 8.编写⼀个名为string_in()的函数,接受两个指向字符串的指针作为参数。
// 如果第2个字符串包含在第1个字符串中,该函数将返回第1个字符串开始的地址。例
// 如,string_in("hats", "at")将返回hats中a的地址。否则,该函数返回空指
// 针。在⼀个完整的程序中测试该函数,使⽤⼀个循环给函数提供输⼊值.
//思路:
// step1:调用字符串输入函数输入字符串1;
// step2:调用字符串输入函数输入字符串2;
// step3:调用字符串搜索函数在字符串1中看能否找到字符串2的字符,找到返回第一个
//        字符的地址,未找到返回NULL;
// step4:循环step1 ~ step3,直到用户按照提示输入回车退出;

#include <stdio.h>
#include <string.h>
#define MAXLEN 50
char * s_gets(char * st, int n);
char * string_in(char * str1, char * str2);

int main()
{
    char str1[MAXLEN];
    char str2[MAXLEN];
    char * check_result;

    puts("Please entry string 1(enter to quit):");
    
    while ( s_gets(str1, MAXLEN) && str1[0] != '\0')  
    {
        puts("Please entry string 2 to check if the string in str1");
        s_gets(str2, MAXLEN);
        // puts(str1);
        // puts(str2);
        check_result = string_in(str1, str2);
        if ( check_result != NULL)
        {
            puts("Find string 2 in string 1.");
            puts(check_result);
        }
        else
            puts("Error.");
        puts("Please entry string 1(enter to quit):");
    }
    puts("Done.");
    return 0;
}

char * string_in(char * str1, char * str2)
{
    if ( str2[0] == '\0' )
        return str1;
    

    for (int i = 0; str1[i] != '\0'; i++) 
    {
    // 找到第一个匹配的字符
    if (str1[i] == str2[0]) 
    {
        int j, k;
        // 检查后续字符是否都匹配
        for (j = i, k = 0; str2[k] != '\0' && str1[j] == str2[k]; j++, k++) {
            // 继续匹配下一个字符
        }
        // 如果子串全部匹配完成,返回起始地址
        if (str2[k] == '\0') {
            return &str1[i];
        }
    }
    }
    return NULL;
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;

    ret_val = fgets(st, n, stdin);
    if(ret_val)
    {
        find = strchr(st, '\n');
        if(find)
            *find = '\0';
        else
            while (getchar() != '\n')
                continue;
    }
    return ret_val;
}

程序2(AI编写的完整程序):

cpp 复制代码
#include <stdio.h>
#define MAX_STR_LEN 100

// 函数声明:检查str2是否包含在str1中,返回起始地址或NULL
char *string_in(const char *str1, const char *str2);
// 辅助函数:安全读取字符串
char *safe_gets(char *str, int n);

int main(void) {
    char str1[MAX_STR_LEN];
    char str2[MAX_STR_LEN];
    char *result;
    char continue_flag;

    printf("=== 字符串包含检查程序 ===\n");
    do {
        // 输入第一个字符串
        printf("\n请输入第一个字符串(作为主串): ");
        safe_gets(str1, MAX_STR_LEN);

        // 输入第二个字符串
        printf("请输入第二个字符串(作为子串): ");
        safe_gets(str2, MAX_STR_LEN);

        // 检查子串是否包含在主串中
        result = string_in(str1, str2);

        // 输出结果
        if (result != NULL) {
            printf("子串 \"%s\" 包含在主串 \"%s\" 中\n", str2, str1);
            printf("起始位置: %s\n", result);
            printf("起始地址: %p\n", (void *)result);
        } else {
            printf("子串 \"%s\" 不包含在主串 \"%s\" 中\n", str2, str1);
        }

        // 询问是否继续
        printf("\n是否继续测试?(y/n): ");
        scanf("%c", &continue_flag);
        // 清除输入缓冲区
        while (getchar() != '\n') continue;

    } while (continue_flag == 'y' || continue_flag == 'Y');

    printf("\n程序结束!\n");
    return 0;
}

// 函数实现:检查str2是否包含在str1中
char *string_in(const char *str1, const char *str2) {
    // 如果子串为空,返回主串的起始地址
    if (str2[0] == '\0') {
        return (char *)str1;
    }

    // 遍历主串
    for (int i = 0; str1[i] != '\0'; i++) {
        // 找到第一个匹配的字符
        if (str1[i] == str2[0]) {
            int j, k;
            // 检查后续字符是否都匹配
            for (j = i, k = 0; str2[k] != '\0' && str1[j] == str2[k]; j++, k++) {
                // 继续匹配下一个字符
            }
            // 如果子串全部匹配完成,返回起始地址
            if (str2[k] == '\0') {
                return (char *)&str1[i];
            }
        }
    }

    // 未找到匹配的子串
    return NULL;
}

// 安全读取字符串,处理换行符
char *safe_gets(char *str, int n) {
    char *result = fgets(str, n, stdin);
    if (result) {
        // 查找换行符并替换为字符串结束符
        int i = 0;
        while (str[i] != '\n' && str[i] != '\0') {
            i++;
        }
        if (str[i] == '\n') {
            str[i] = '\0';
        } else {
            // 清除输入缓冲区中剩余的字符
            while (getchar() != '\n') {
                continue;
            }
        }
    }
    return result;
}

程序3(原书编程练习答案):

cpp 复制代码
#include <stdio.h>
#define LEN 20
char * string_in(const char * s1, const char * s2);
int main()
{
    char orig[LEN] = "transportation";
    char * find;

    puts(orig);
    find = string_in(orig, "port");
    if(find)
        puts(find);
    else
        puts("Not found");
    find = string_in(orig, "part");
    if(find)
        puts(find);
    else
        puts("Not found");

    return 0;
}

#include <string.h>
char * string_in(const char * s1, const char * s2)
{
    int L2 = strlen(s2);
    int tries;          //maximum numbers of comparisons
    int nomatch = 1;    // set to 0 if match is found

    tries = strlen(s1) + 1 - L2;
    if (tries > 0)
        while (( nomatch = strncmp (s1, s2, L2)) && tries--)
            s1++;
        if (nomatch)
            return NULL;
        else
            return (char *) s1;     // cast const 
}
相关推荐
2401_858936881 小时前
【Linux C 编程】标准 IO 详解与实战:从基础接口到文件操作实战
linux·c语言
季明洵3 小时前
C语言实现单链表
c语言·开发语言·数据结构·算法·链表
浅念-4 小时前
C语言编译与链接全流程:从源码到可执行程序的幕后之旅
c语言·开发语言·数据结构·经验分享·笔记·学习·算法
爱吃生蚝的于勒4 小时前
【Linux】进程信号之捕捉(三)
linux·运维·服务器·c语言·数据结构·c++·学习
The森4 小时前
Linux IO 模型纵深解析 01:从 Unix 传统到 Linux 内核的 IO 第一性原理
linux·服务器·c语言·经验分享·笔记·unix
C++ 老炮儿的技术栈5 小时前
Qt 编写 TcpClient 程序 详细步骤
c语言·开发语言·数据库·c++·qt·算法
wangjialelele6 小时前
Linux下的IO操作以及ext系列文件系统
linux·运维·服务器·c语言·c++·个人开发
wengqidaifeng8 小时前
数据结构(三)栈和队列(上)栈:计算机世界的“叠叠乐”
c语言·数据结构·数据库·链表
VekiSon8 小时前
Linux内核驱动——设备树原理与应用
linux·c语言·arm开发·嵌入式硬件
BlackQid9 小时前
深入理解指针Part5——回调函数及应用
c语言