线性表的顺序存储与链式存储实现

要求:

  • 逐行读取指定文件中的数据,解析后保存在顺序表中。其中,文件中每行数据格式为“学号,姓名,年 龄”,比如“10225048,张三,24”(提示:采用顺序表结构时,顺序表中每个表元素包含三类信息:学号,姓名,和年龄;采用单链表结构时,单链表中每个结点的数据域包含三类信息:学号,姓名,和年龄),
  • 根据键盘输入进行相关操作,比如,若键盘输入为“P3”,则打印出第3项信息(注意:采用顺序表结构时,第3项数据对应下标为2的表元素;采用单链表结构时,第3项数据对应链表中第3个结点的信息;);若键盘输入为“D3”,则删除第3个表元素;若键盘输入为“I3,10225038,张四,24”,则在第3项前插入一个学生的信息(10225038,张四,24)。

实现代码:

  • 头文件
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <conio.h>

#define LIST_INCREASEMENT 10
#define ORIGINA_DATA_NUM 8
#define SIZE 256

typedef struct
{
    char id[SIZE] = { 0 };
    char name[SIZE] = { 0 };
    char age[SIZE] = { 0 };
}student;

typedef struct
{
    student *element;
    int list_curr_length;
    int list_size;
}SqList;

typedef struct LNode
{
    student *data;
    struct LNode *next;
}LinkNode;

int SqListMain(void);
int LinkedListMain(void);
void SqListInstr(void);
void DisplaySqList(SqList *L);
void InitSqList(SqList *&L);
void SqListEmpty(SqList *L);
void SqListLength(SqList *L);
void DestroySqList(SqList *&L);
bool SqListInsert(SqList *&L, int i, student e);
bool SqListDelete(SqList *&L, int i);
bool SqListGetInsert(SqList *&L);
bool PrintSqList(SqList *L, int i);

int LinkedListMain(void);
void LinListLength(LinkNode *L);
void LinListInstr(void);
void InitLinList(LinkNode *&L);
void DisplayLinList(LinkNode *L);
void DestroyLinList(LinkNode *&L);
void EmptyLinList(LinkNode *L);
bool LinListGetInsert(LinkNode *&L);
bool LinListDelete(LinkNode *&L, int i);
bool LinListInsert(LinkNode *&L, int i, student e);
  • Sequence List 实现:
#include "head.h"

SqList *L;

bool flag_1 = false;

void InitSqList(SqList *&L)
{
    L = (SqList *)malloc(sizeof(SqList));
    L->element = (student *)malloc(sizeof(student) * 100);
    L->list_size = 100;
    L->list_curr_length = 0;
}

void DestroySqList(SqList *&L)
{
    free(L);
}

void SqListEmpty(SqList *L)
{
    if (L->list_curr_length == 0)
        printf("\n顺序表为空。\n\n");
    else
        printf("\n顺序表不为空。\n\n");
    return;
}

void SqListLength(SqList *L)
{
    printf("\n顺序表长度为:%d\n\n", L->list_curr_length);
    return;
}

void DisplaySqList(SqList *L)
{
    if (!L->list_curr_length)
    {
        printf("列表为空,无法打印。\n");
        return ;
    }
    printf("----------------------------\n\n");
    for (int i = 0; i < L->list_curr_length; i++)
        printf("%s, %s, %s\n", L->element[i].id, L->element[i].name, L->element[i].age);
    printf("----------------------------\n");
    return;
}

bool PrintSqList(SqList *L, int i)
{
    if (i < 1 || i > L->list_curr_length)
    {
        printf("输入有误,当前顺序表长度为%d,请重新输入。\n", L->list_curr_length);
        return false;
    }
    i--;
    printf("\n%s, %s, %s\n", L->element[i].id, L->element[i].name, L->element[i].age);
    printf("\n");
    return true;
}

/*
bool SqListGetElem(SqList *L, int i)
{
    if (i < 1 || i > L->list_curr_length)
    {
        printf("输入有误,当前顺序表长度为%d,请重新输入。\n", L->list_curr_length);
        return false;
    }
    i--;
    printf("\n%s, %s, %s\n", L->element[i].id, L->element[i].name, L->element[i].age);
    printf("\n");
    return true;
}
*/

/*
int SqListLocateElem(SqList *L, student e)
{
    int i = 0;
    while (i < L->list_curr_length && L->element[i].id != e.id)
        i++;
    if (i >= L->list_curr_length)
        return 0;
    else
        return i + 1;
}
*/

bool SqListInsert(SqList *&L, int i, student e)
{
    int j;
    if (i < 1 || i > L->list_curr_length + 1)
    {
        printf("输入有误,当前顺序表长度为%d,请重新输入。\n", L->list_curr_length);
        return false;
    }
    i--;
    if (L->list_curr_length >= L->list_size)
    {
        student *new_element;
        new_element = (student *)realloc(L->element, L->list_size + LIST_INCREASEMENT);
        L->element = new_element;
        L->list_size += LIST_INCREASEMENT;
    }
    for (j = L->list_curr_length; j > i; j--)
    {
        strcpy(L->element[j].age, L->element[j - 1].age);
        strcpy(L->element[j].id, L->element[j - 1].id);
        strcpy(L->element[j].name, L->element[j - 1].name);
    }
    strcpy(L->element[i].id, e.id);
    strcpy(L->element[i].name, e.name);
    strcpy(L->element[i].age, strcat(e.age, "\n"));

    /*
    memcpy(L->element[i].id, e.id, strlen(e.id) + 1);
    memcpy(L->element[i].name, e.name, strlen(e.name) + 1);
    memcpy(L->element[i].age, e.age, strlen(e.age) + 1);
    */

    L->list_curr_length++;
    if (flag_1)
    {
        printf("成功插入节点,当前节点列表为:\n\n");
        DisplaySqList(L);
    }
    return true;
}

bool SqListDelete(SqList *&L, int i)
{
    int j;
    if (i < 1 || i > L->list_curr_length)
    {
        printf("输入有误,当前顺序表长度为%d,请重新输入。\n", L->list_curr_length);
        return false;
    }
    i--;
    for (j = i; j < L->list_curr_length - 1; j++)
    {
        strcpy(L->element[j].age, L->element[j + 1].age);
        strcpy(L->element[j].id, L->element[j + 1].id);
        strcpy(L->element[j].name, L->element[j + 1].name);
    }
    L->list_curr_length--;
    printf("成功删除节点,当前节点列表为:\n\n");
    DisplaySqList(L);
    return true;
}

void SqListInstr(void)
{
    printf("\n操作说明:\n");
    printf("----------------------------\n\n");
    printf("  QQ:    退出\n\n");
    printf("  TT:    打印操作说明\n\n");
    printf("  RR:    删除整个列表\n\n");
    printf("  EE:    判断列表是否为空\n\n");
    printf("  LL:    返回列表长度\n\n");
    printf("  SS:    打印完整列表\n\n");
    printf("  NN:    重新初始化列表\n\n");
    printf("I+数字:  插入新节点\n\n");
    printf("P+数字:  打印单个节点\n\n");
    printf("D+数字:  删除单个节点\n\n");
    printf("----------------------------\n\n");
    return;
}

bool SqListGetInsert(SqList *&L)
{
    FILE *fp = NULL;
    student insert_elem;
    char e_oneline[1024], *temp;
    if ((fp = fopen("data.txt", "r")) == NULL)
    {
        printf("error!\n");
        return false;
    }
    int i = 1;
    while (!feof(fp) && i < ORIGINA_DATA_NUM + 1)
    {
        fgets(e_oneline, 1024, fp);
        strcpy(insert_elem.id, strtok(e_oneline, ","));
        strcpy(insert_elem.name, strtok(NULL, ","));
        strcpy(insert_elem.age, strtok(NULL, ","));

        /*
        memcpy(insert_elem.id, temp, strlen(temp) + 1);
        memcpy(insert_elem.name, temp, strlen(temp) + 1);
        memcpy(insert_elem.age, temp, strlen(temp) + 1);
        */

        SqListInsert(L, i, insert_elem);
        i++;
    }
    fclose(fp);
    printf("\n初始化成功,当前节点列表为:\n\n");
    DisplaySqList(L);
    flag_1 = true;
    return true;
}

int SqListMain(void)
{
    student insert_elem;
    int input_t;
    char input_o;
    SqListInstr();
    InitSqList(L);
    SqListGetInsert(L);
    printf("请输入指令:");
    scanf(" %c%d", &input_o, &input_t);
    if (input_o == 'I')
    {
        printf("\n请输入待插入项: ");
        scanf("%s %s %s", insert_elem.id, insert_elem.name, insert_elem.age);
        // printf("%s, %s, %s, %c, %d\n", insert_elem.id, insert_elem.name, insert_elem.age, input_o, input_t);
    }
    while (input_o != 'Q')
    {
        switch (input_o)
        {
        case 'P':
            PrintSqList(L, input_t);
            break;
        case 'D':
            SqListDelete(L, input_t);
            break;
        case 'I':
            SqListInsert(L, input_t, insert_elem);
            break;
        case 'R':
            DestroySqList(L);
            break;
        case 'E':
            SqListEmpty(L);
            break;
        case 'L':
            SqListLength(L);
            break;
        case 'S':
            DisplaySqList(L);
            break;
        case 'T':
            SqListInstr();
            break;
        case 'N':
            InitSqList(L);
            flag_1 = false;
            SqListGetInsert(L);
            flag_1 = true;
            break;
        default:
            printf("指令有误,请重新输入。\n");
            break;
        }
        printf("请输入指令:");
        scanf(" %c%d", &input_o, &input_t);
        if (input_o == 'I')
        {
            printf("\n请输入待插入项: ");
            scanf("%s %s %s", insert_elem.id, insert_elem.name, insert_elem.age);
            // printf("%s, %s, %s, %c, %d\n", insert_elem.id, insert_elem.name, insert_elem.age, input_o, input_t);
        }
    }
    return 0;
}
  • Linked List 实现:
#include "head.h"

LinkNode *L;

bool flag_2 = false;

void InitLinList(LinkNode *&L)
{
    L = (LinkNode *)malloc(sizeof(LinkNode));
    L->data = (student *)malloc(sizeof(student));
    L->next = NULL;
}

void DestroyLinList(LinkNode *&L)
{
    LinkNode *pre = L, *p = pre->next;
    while (p != NULL)
    {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre);  //此时p为NULL,pre指向尾结点,释放它
}

void EmptyLinList(LinkNode *L)
{
    if (!L->next)
        printf("\n顺序表为空。\n\n");
    else
        printf("\n顺序表不为空。\n\n");
    return;
}

void LinListLength(LinkNode *L)
{
    LinkNode *p = L; int i = 0;
    while (p->next != NULL)
    {
        i++;
        p = p->next;
    }
    printf("\n链表长度为:%d\n\n", i);
    return;
}

bool LinListDelete(LinkNode *&L, int i)
{
    int j = 0;
    LinkNode *p = L, *q;
    if (i <= 0) return false;       //i错误返回假
    while (j < i - 1 && p != NULL)  //查找第i-1个结点
    {
        j++;
        p = p->next;
    }
    if (p == NULL)              //未找到位序为i-1的结点
        return false;
    else                        //找到位序为i-1的结点p
    {
        q = p->next;                //q指向要删除的结点
        if (q == NULL)
            return false;       //若不存在第i个结点,返回false
        p->next = q->next;      //从单链表中删除q结点
        free(q);                //释放q结点
        
    }
    printf("\n成功删除节点,当前节点列表为:\n\n");
    DisplayLinList(L);
    return true;
}

bool LinListGetInsert(LinkNode *&L)
{
    FILE *fp = NULL;
    student insert_elem;
    char e_oneline[1024], *temp;
    if ((fp = fopen("data.txt", "r")) == NULL)
    {
        printf("error!\n");
        return false;
    }
    int i = 1;
    while (!feof(fp) && i < ORIGINA_DATA_NUM + 1)
    {
        fgets(e_oneline, 1024, fp);
        strcpy(insert_elem.id, strtok(e_oneline, ","));
        strcpy(insert_elem.name, strtok(NULL, ","));
        strcpy(insert_elem.age, strtok(NULL, ","));

        /*
        memcpy(insert_elem.id, temp, strlen(temp) + 1);
        memcpy(insert_elem.name, temp, strlen(temp) + 1);
        memcpy(insert_elem.age, temp, strlen(temp) + 1);
        */

        LinListInsert(L, i, insert_elem);
        i++;
    }
    fclose(fp);
    printf("\n初始化成功,当前节点列表为:\n\n");
    DisplayLinList(L);
    flag_2 = true;
    return true;
}

void DisplayLinList(LinkNode *L)
{
    LinkNode *p = L->next;
    printf("----------------------------\n\n");
    while (p != NULL)
    {
        printf("%s, %s, %s\n", p->data->id, p->data->name, p->data->age);
        p = p->next;
    }
    printf("----------------------------\n\n");
}

void LinListInstr(void)
{
    printf("\n操作说明:\n");
    printf("----------------------------\n\n");
    printf("  QQ:    退出\n\n");
    printf("  TT:    打印操作说明\n\n");
    printf("  RR:    删除整个列表\n\n");
    printf("  EE:    判断列表是否为空\n\n");
    printf("  LL:    返回列表长度\n\n");
    printf("  SS:    打印完整列表\n\n");
    printf("  NN:    重新初始化列表\n\n");
    printf("I+数字:  插入新节点\n\n");
    printf("P+数字:  打印单个节点\n\n");
    printf("D+数字:  删除单个节点\n\n");
    printf("----------------------------\n\n");
    return;
}

bool LinListInsert(LinkNode *&L, int i, student e)
{
    int j = 0;
    LinkNode *p = L, *s;
    if (i <= 0)
        return false;           //i错误返回假
    while (j < i - 1 && p != NULL)      //查找第i-1个结点p
    {
        j++;
        p = p->next;
    }
    if (p == NULL)                  //未找到位序为i-1的结点
        return false;
    else                            //找到位序为i-1的结点*p
    {
        s = (LinkNode *)malloc(sizeof(LinkNode));//创建新结点*s
        s->data = (student *)malloc(sizeof(student));
        strcpy(s->data->id, e.id);
        strcpy(s->data->name, e.name);
        strcpy(s->data->age, strcat(e.age, "\n"));
        s->next = p->next;          //将s结点插入到结点p之后
        p->next = s;
        return true;
    }
    if (flag_2)
    {
        printf("成功插入节点,当前节点列表为:\n\n");
        DisplayLinList(L);
    }
}

bool PrintLinList(LinkNode *L, int i)
{
    int j = 0;
    LinkNode *p = L->next;
    if (i <= 0)
        return false;           //i错误返回假
    while (j < i - 1 && p != NULL)      //查找第i-1个结点p
    {
        j++;
        p = p->next;
    }
    if (p == NULL)                  //未找到位序为i-1的结点
        return false;
    else                            //找到位序为i-1的结点*p
    {
        printf("\n%s, %s, %s\n", p->data->id, p->data->name, p->data->age);
        return true;
    }
}

int LinkedListMain(void)
{
    student insert_elem;
    int input_t;
    char input_o;
    LinListInstr();
    InitLinList(L);
    LinListGetInsert(L);
    printf("\n请输入指令:");
    scanf(" %c%d", &input_o, &input_t);
    if (input_o == 'I')
    {
        printf("\n请输入待插入项: ");
        scanf("%s %s %s", insert_elem.id, insert_elem.name, insert_elem.age);
        // printf("%s, %s, %s, %c, %d\n", insert_elem.id, insert_elem.name, insert_elem.age, input_o, input_t);
    }
    while (input_o != 'Q')
    {
        switch (input_o)
        {
        case 'P':
            PrintLinList(L, input_t);
            break;
        case 'D':
            LinListDelete(L, input_t);
            break;
        case 'I':
            LinListInsert(L, input_t, insert_elem);
            break;
        case 'R':
            DestroyLinList(L);
            break;
        case 'E':
            EmptyLinList(L);
            break;
        case 'L':
            LinListLength(L);
            break;
        case 'S':
            DisplayLinList(L);
            break;
        case 'T':
            LinListInstr();
            break;
        case 'N':
            InitLinList(L);
            flag_2 = false;
            LinListGetInsert(L);
            flag_2 = true;
            break;
        default:
            printf("指令有误,请重新输入。\n");
            break;
        }
        printf("\n请输入指令:");
        scanf(" %c%d", &input_o, &input_t);
        if (input_o == 'I')
        {
            printf("\n请输入待插入项: ");
            scanf("%s %s %s", insert_elem.id, insert_elem.name, insert_elem.age);
            // printf("%s, %s, %s, %c, %d\n", insert_elem.id, insert_elem.name, insert_elem.age, input_o, input_t);
        }
    }
    return 0;
}
  • main() 函数:
#include "head.h"

void main(void)
{
    char choice;
    printf("请选择存储模式(S/L/Q):");
    scanf("%c", &choice);
    while (choice != 'Q')
    {
        switch (choice)
        {
        case 'S':
            SqListMain();
            break;
        case 'L':
            LinkedListMain();
            break;
        default:
            printf("输入有误,请重新输入: \n");
            break;
        }
        printf("请选择存储模式(S/L/Q):");
        scanf("%c", &choice);
    }
    return;
}

data.txt 文件:

10225048,张三,24
10225132,李四,22
10225027,王五,24
10225213,赵六,25
10225197,欧阳奋强,23
10225059,孙八,24
10225083,余久,23
10225112,张唯一,24

总结:

  • fscanf()函数的使用
    原型:int fscanf(FILE*stream,constchar*format,[argument...]);
    头文件:<stdio.h>
    功能:从一个流中执行格式化输入,fscanf遇到空格和换行时结束。这与fgets有区别,fgets遇到空格不结束。
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main()
    {
       char str1[10], str2[10], str3[10];
       int year;
       FILE * fp;
    
       fp = fopen ("file.txt", "w+");
       fputs("We are in 2014", fp);
       
       rewind(fp);
       fscanf(fp, "%s %s %s %d", str1, str2, str3, &year);
       
       printf("Read String1 |%s|\n", str1 );
       printf("Read String2 |%s|\n", str2 );
       printf("Read String3 |%s|\n", str3 );
       printf("Read Integer |%d|\n", year );
    
       fclose(fp);
       
       return(0);
    }
    
  • fgets()函数的使用
    原型:char *fgets(char *buf, int bufsize, FILE *stream);
    头文件:<string.h>
    功能:从文件流读取一行,送到缓冲区。
    fgets(e_oneline, 1024, fp);
  • strcpy()函数的使用
    原型:char *strcpy(char* dest, const char *src);
    头文件:<string.h> <stdio.h>
    功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间。
    strcpy(insert_elem.id, strtok(e_oneline, ","));
    strcpy(insert_elem.name, strtok(NULL, ","));
    strcpy(insert_elem.age, strtok(NULL, ","));
    
  • strtok()函数的使用
    原型:char *strtok(char s[], const char *delim);
    头文件:<string.h>
    功能:分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。
    strcpy(insert_elem.id, strtok(e_oneline, ","));
    strcpy(insert_elem.name, strtok(NULL, ","));
    strcpy(insert_elem.age, strtok(NULL, ","));
    
  • memcpy()函数的使用
    原型:void *memcpy(void *dest, const void *src, size_t n);
    头文件:c:<string.h>; c++:<cstring>
    功能:从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
    memcpy(insert_elem.id, temp, strlen(temp) + 1);
    memcpy(insert_elem.name, temp, strlen(temp) + 1);
    memcpy(insert_elem.age, temp, strlen(temp) + 1);
    
  • strcat()函数的使用
    原型:extern char *strcat(char *dest, const char *src);
    头文件:c: <string.h>;c++: <cstring>
    功能:把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除dest原来末尾的“\0”)。要保证dest足够长,以容纳被复制进来的src,src中原有的字符不变,返回指向dest的指针。
    strcpy(L->element[i].age, strcat(e.age, "\n"));
  • feof()函数和文件的使用
    原型:int feof(FILE *stream);
    头文件:<stdio.h>
    功能:检测流上的文件结束符, 如果文件结束,则返回非0值,否则返回0值,文件结束符只能被clearerr()清除。
    bool SqListGetInsert(SqList *&L)
    {
        FILE *fp = NULL;
        student insert_elem;
        char e_oneline[1024], *temp;
        if ((fp = fopen("data.txt", "r")) == NULL)
        {
          printf("error!\n");
          return false;
        }
        int i = 1;
        while (!feof(fp) && i < ORIGINA_DATA_NUM + 1)
        {
            fgets(e_oneline, 1024, fp);
            strcpy(insert_elem.id, strtok(e_oneline, ","));
            strcpy(insert_elem.name, strtok(NULL, ","));
            strcpy(insert_elem.age, strtok(NULL, ","));
    
            /*
            memcpy(insert_elem.id, temp, strlen(temp) + 1);
            memcpy(insert_elem.name, temp, strlen(temp) + 1);
            memcpy(insert_elem.age, temp, strlen(temp) + 1);
            */
    
            SqListInsert(L, i, insert_elem);
            i++;
        }
        fclose(fp);
        printf("\n初始化成功,当前节点列表为:\n\n");
        DisplaySqList(L);
        flag_1 = true;
        return true;
    }
    
  • 实验过程中出现的错误
    将 strcpy(L->element[i].id, e.id); 写为 L->element[i].id = e.id;
    L->element[i].id = e.id;
    L->element[i].name = e.name;
    L->element[i].age =e.age;
    
    错误原因:L->element[i].id 为一个已经定义好的数组,无法再为其重新定义,只可以为其赋值。
    正确代码如下:
    strcpy(L->element[i].id, e.id);
    strcpy(L->element[i].name, e.name);
    strcpy(L->element[i].age, strcat(e.age, "\n"));
    
    没有为结构体内部的结构体型变量分配空间:
    void InitLinList(LinkNode *&L)
    {
        L = (LinkNode *)malloc(sizeof(LinkNode));
        L->next = NULL;
    }
    
    错误原因:L->data时student型的结构体变量,虽然结构体student在定义时已经为id, name, age分配了空间,但是L->data仍然没有分配空间,需要为其重新分配。
    正确代码如下:
    void InitLinList(LinkNode *&L)
    {
        L = (LinkNode *)malloc(sizeof(LinkNode));
        L->data = (student *)malloc(sizeof(student));
        L->next = NULL;
    }
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容