C和指针_编程练习_第4章_第5题

/*
        编写一个函数, 从标准输入一行一行地读取文本, 并完成如下任务:
        如果文件中有两行或者多行相邻的文本内容相同, 那么就打印出其中一行, 其余的行不打印.你可以假设文件中的文本行在长度上不超过128个字符(127个字符加上用于终结文本行的环行符).
        考虑如下输入文件:
        This is the frist line.
        Another line.
        And another.
        And another.
        And another.
        Still more.
        Almost done now --
        Almost done now --
        Another line.
        Still more.
        Finished!
        假定所有的行在尾部没有任何空白(它们在视觉上不可见, 但却可能使邻近两行在内容上不同), 根据这个输入文件, 程序应该产生下列输出:
        And another.
        Almost done now --
        所有内容相同的相邻文本行只有一行被打印. 注意"Another line."和"Still more."并未被打印, 因为文件中它们虽然各占两行, 但相同文本行的位置并不相邻.
        提示:
        是由fgets函数读取输入行, 使用strcpy函数来复制它们. 有一个叫做strcmp的函数接受两个字符串参数并对他们进行比较. 如果两者相等, 函数返回0, 如果不等, 函数返回非0值.

*/

typedef struct tagLINE
{
        char *str;
        struct tagLINE *next;
}LINE;

void SaveStr( LINE *output, char *str );
void ShowStr( LINE *output );
void end(LINE *output);

#define MAX 128
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( void )
{
        LINE * const output = (LINE*) malloc( sizeof( LINE ) );    //output是链表的头指针
        if( output == NULL )
        {    
                printf( "内存申请失败!\n" );
                exit( 0 );
        }
        output->str = "输出:\n";
        output->next = NULL;

        char *buf = (char*) malloc( sizeof( char ) * MAX );    //存放当前输入文本行
        if( buf == NULL )
        {
                printf( "内存申请失败!\n" );
                exit( 0 );
        }

        char ( *str )[MAX] = ( char(*)[MAX] ) malloc( sizeof( char ) * MAX * 3 );    //str[3][MAX], 存放文本行
        if( str == NULL )
        {
                printf( "内存申请失败!\n" );
                exit( 0 );
        }

        //将str中的3个字符串初始化为空字符串
        str[0][0] = '\0';    //存放的字符串非空时, 送入output最终打印出来
        str[1][0] = '\0';    //存放相邻两行内容相同的文本行
        str[2][0] = '\0';    //存放上一次输入文本行

        while( fgets( buf, MAX, stdin ) != NULL )
        {
                if( strcmp( str[2], buf ) != 0 )    //如果当前文本行与上一行不同
                {
                        strcpy( str[0], str[1] );
                        str[1][0] = '\0';
                        strcpy( str[2], buf );
                }

                else    //如果当前文本行与上一行相同
                {
                        if( strcmp( str[1], str[2] ) != 0 )    //如果上一行(当前文本行)与上一个相同文本行不同
                        {
                                strcpy( str[0], str[1] );
                                strcpy( str[1], str[2] );
                        }
                }

                if( str[0][0] != '\0' )
                {
                        SaveStr( output, str[0] );    //把字符串str[0]存入链表
                        str[0][0] = '\0';
                }

                if( buf[0] == '\n' )    //用户输入空文本行(只有一个回车), 表示输入结束
                {
                        break;
                }
        }

        ShowStr( output );    //打印链表
        end( output );    //释放之前申请的动态内存
        free( buf );
        free( str );

        return 0;
}

void SaveStr( LINE *output, char *str )
{
        LINE *p = (LINE*) malloc( sizeof( LINE ) );    //为新节点分配动态内存
        if( p == NULL )
        {
                printf( "内存申请失败!\n" );
                exit( 0 );
        }

        p->str = (char*) malloc( strlen( str ) + 1 );    //根据要存储字符串长度申请一块最小的动态内存
        if( p->str == NULL )
        {
                printf( "内存申请失败!\n" );
                exit( 0 );
        }
        strcpy( p->str, str );    //复制字符串到新节点

        p->next = NULL;    //存储的字符串都是从尾部插入链表, 所以申请动态内存成功后直接把新节点的next置空

        while(output->next !=NULL)    //遍历到链表尾节点
        {
                output = output->next;
        }
        output->next = p;    //在链表尾部插入新节点

        return;
}


void ShowStr( LINE *output )
{
        for( ;output != NULL; output = output->next )
        {
                printf( "%s", output->str );    //fgets函数会在字符串末尾加上'\0', 假设每行输入不超过MAX, 那么最后一个有效字符一定是用户输入的'\n', 所以printf不需要再加换行符.
        }

        return;
}


void end( LINE *output )
{
        LINE *delete = output;    //delete用于释放节点占用的动态内存
        for( output = output->next; output != NULL; output = output->next )
        {
                free( output->str );    //释放节点里面str指向的动态内存
                free( delete );    //释放节点占用的动态内存
                delete = output;  //delete永远滞后output一个节点
        }
        free( delete );    //因为delete永远滞后output一个节点, 所以上面循环结束时, 还有最后一个节点占用的动态内存没有释放

        return;
}

程序输出结果:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值