学生系统结构体+文件读写训练

1.综合代码

#include 
#include 
#include 

typedef struct student {
    int age;
    int grade;
    char name[20];
} stu;

// 1.排序功能
int sort(stu* p, int length) {
    stu temp;
    int i, j;
    for (i = 0; i < length; i++) {
        for (j = 0; j < length - 1 - i; j++) {
            // 1.排序规则:比较成绩,若成绩相同比较名字首字母
            if (p[i + 1].grade > p[i].grade) {
                temp = *(p + i); //*()=[]:——>*(p+i)=p[i]
                p[i] = p[i + 1];
                p[i + 1] = temp;
            } else if (p[i + 1].grade == p[i].grade &&
                       p[i + 1].name[0] > p[i].name[0]) {
                temp = p[i];
                p[i] = p[i + 1];
                p[i + 1] = temp;
            }
        }
    }
    return 1;
}

// 2.将数据加载到文件中
void ToFile(FILE* fp, stu* p, int length) {
    int i, j;

    // 2.追加内容
    for (i = 0; i < length; i++) {
        fprintf(fp, "学生成绩:%d\t学生年龄:%d\t学生姓名:%s\n",
                (p + i)->grade, (p + i)->age, (p + i)->name);
        printf("学生成绩:%d\t学生年龄:%d\t学生姓名:%s\n", (p + i)->grade,
               (p + i)->age, (p + i)->name);
    }
    printf("追加完毕!\n");
}

// 3.寻找指定数据
void search(stu* p, char s_name[], int length) {
    int i;
    for (i = 0; i < length; i++) {
        // 1.根据name名称寻找对应数据
        if (strcmp((*(p+i)).name, s_name)==0) {
            printf("%s的成绩:%d,当前年龄:%d\n", p[i].name, (*(p + i)).grade,
                   (p + i)->age);
        }
    }
}

int main() {
    int i, j;
    FILE* fp;
    // 1.首先给stu声明一个结构体变量
    stu s[3] = {{19, 90, "Fairy"}, {21, 88, "Barry"}, {23, 91, "Fox"}};
    stu* p = s; //补充:s是一个数组,所以不需要用取地址符了&

    int len = sizeof(s) / sizeof(stu);

    // 1.打开文件,这里注意将读取文件放在外面,因为放在函数中,函数外的文件读写操作就会作废
    fp = fopen("Grade.txt", "a");
    if (fp == NULL) {
        printf("OPEN ERROR!");
        exit(0);
    }
    // 2.上传排序前的文件
    fputs("排序前数据\n", fp);
    ToFile(fp, p, len);

    // 4.对数据进行排序
    int success = sort(p, len);
    printf("排序完毕\n");

    // 5.输出排序后的数据
    fputs("排序后的数据\n", fp);
    ToFile(fp, p, len);

    // 6.寻找数据
    char name[20];
    printf("请输入你想要搜索的名字\n");
    scanf("%s", name);
    search(p, name, len);

    return 0;
}

结果:

开始运行...

学生成绩:90     学生年龄:19     学生姓名:Fairy
学生成绩:88     学生年龄:21     学生姓名:Barry
学生成绩:91     学生年龄:23     学生姓名:Fox
追加完毕!
排序完毕
学生成绩:90     学生年龄:19     学生姓名:Fairy
学生成绩:91     学生年龄:23     学生姓名:Fox
学生成绩:88     学生年龄:21     学生姓名:Barry
追加完毕!
请输入你想要搜索的名字
Fox
Fox的成绩:91,当前年龄:23

2.文件操作训练

#include 
#include 


int main() {
    /**
    文件类型:
    (1)文本文件:以字符编码的方式保存。(2)二进制文件:将内存中的数据原封不动的放至文件中,主要以非字符数据为主
    1.fopen("文件名","打开方式:r,w,a"):文件的打开
      r:只读,若文件不存在则打开失败
      w:只写:如果文件不存在则会创建文件,若存在则会清空文件再写(非追加方式)
      a:append:文件不存在会创建文件,若文件存在则会在已有内容的基础上进行追加

    2.fpuc("具体字符","文件指针"):将一个字符输入到文件
    3.fpus("字符串","文件指针"):将文件输入一串字符串
    **/
    int i, j;
    FILE* fp = fopen("P211.txt", "w+");
    char s[10];
    char ch;
    if (fp == NULL) {
        printf("打开文件失败!\n");
        exit(0);
    }
    // 1.输入s的内容(关键函数:(1)puts:将控制台输入的字符串->s数组中)
    // (2)fputc:将单个字符输入到fp文件中
    printf("给文章添加内容(串):\n");
    gets(s);
    for (i = 0; s[i] != '\0'; i++) {
        fputc(s[i], fp);
    }
    // 2.给文章添加单个字符
    printf("给文章添加内容(单个字符):\n");
    scanf("%c", &ch);
    printf("您输入的字符是%c\n", putchar(ch));
    fputc(ch, fp);

    /**
    2.
    fgetc("文件指针"):从文件读出一个字符
    注意:EOF视为文件的结束符
    putchar("字符"):将字符输出的控制台上
    **/
    ch = fgetc(fp);
    while (fp!= EOF) {
        putchar(ch); //2.如果字符不是EOF结束符就将其输出到控制台
        ch = fgetc(fp); //3.从fp所指向的文件中继续获取字符
    }

    /**
    3.
    fprintf(文件指针,格式字符串,输出列表)
    fscanf(文件指针,格式字符串,输出列表)
    **/
    for(i=1;i<=9;i++){
        for(j=1;j<=i;j++){
            fprintf(fp, "%d*%d=%d\t", j,i,j*i);
        }
        fprintf(fp, "\n");
    }
    fclose(fp);
}

3.结构体操作

#include 
#include 
#include 
#define N 2 + 3
#define f(x) x* x
/**
1.编译预处理
1.三种:宏定义,文件包含,条件编译
2.预处理:以#开头,每一行只能写预处理命令
3.不加分号
4.宏定义: #define 宏名 替换文本(不能作表达式运算)
注意宏定义可以定义函数
5.文件包含:#include
<文件名>:查找系统指定目录所包含的文件/"文件名":查找用户目录的指定文件
**/
typedef struct student {
    int age;
    char name[20];
} stu;
/**
2.结构体的性质:
2.1结构体数据类型定义s部分不占内存,变量占内存(先定义类型,再使用变量)
2.2:typedef int IN:目的:起别名,表示给数据类型起别名,名字为IN
2.3:typedef struct s{

}student;中s和student的区别:student是别名,而s是结构体类型的声明,student是为该声明进行简化来的
--------------------
typedef struct和普通struct的区别:
前者是取别名,具体的变量引用还需要在main方法中声明结构体变量;
后者是帮助结构体声明了引用变量 ;
eg.
struct student{
    .....
}stu;
main{
    stu.age即可
}
而typedef struct student{
   .....
}stu;只是充当起别名作用
main{
    还需要定义引用变量
    stu s={xx,"xx"};
}
--------------------
2.4:结构体成员的引用
@1.结构体变量.成员名
@2.结构体指针——>成员名
@3.*(结构体指针).成员名
----------------------
2.5:
在结构体typedef结构体定义中,不能直接对结构体进行初始化赋值——>1.可以将typedef
struct student改为struct student即可
-----------------------
2.6补充sizeof字节数:
struct student {
    int age;
    char name[20];
} stu,*p&stu;中sizeof(p)=?:获取指针变量的大小,与结构体无关
--------------------------
**/
int main() {
    int a, b;
    a = N * N;
    b = N / N;
    // 1.函数宏定义
    a = f(a) + f(b);
    printf("%d\n", a);

    printf("--------结构体-----------\n");

    stu s = {18, "mike"};
    stu* p = &s;
    // 1.结构体变量的引用
    printf("%s年龄:%d\n", p->name, p->age);
    printf("%c是%s的首字母\n", p->name[0], p->name);
    printf("%c是%s的首字母\n", s.name[0], p->name);
    // 2.引用所指向内容的修改(strcpy(目标指针指向的内容,src))
    strcpy(p->name, "Fairy");
    strcpy(s.name, "Fairy同学");
    printf("%s年龄:%d\n", p->name, p->age);
    //3.指针变量的大小:64bit为8,32位为4
    //VC下,int通常占4字节,char1字节,double占8字节,long是4字节,float也是4字节
    printf("%zu",sizeof(p));
    
    return 0;
}

#include 
#include 
#include 

typedef struct Student {
    int no;
    char name[20];
    struct Student* next;
} StudentNode;

// 创建学生节点
StudentNode* createStudentNode(int no, const char* name) {
    StudentNode* node = (StudentNode*)malloc(sizeof(StudentNode));
    node->no = no;
    strcpy(node->name, name);
    node->next = NULL;
    return node;
}

// 插入学生节点
void insertStudentNode(StudentNode** head, int no, const char* name) {
    StudentNode* newNode = createStudentNode(no, name);
    if (*head == NULL) {
        *head = newNode;
    } else {
        StudentNode* temp = *head;
        while (temp->next != NULL) {
            temp = temp->next;
        }
        temp->next = newNode;
    }
}

// 删除学生节点
void deleteStudentNode(StudentNode** head, int no) {
    if (*head == NULL) {
        return;
    }
    StudentNode* temp = *head;
    if (temp->no == no) {
        *head = temp->next;
        free(temp);
        return;
    }
    StudentNode* prev = NULL;
    while (temp != NULL && temp->no != no) {
        prev = temp;
        temp = temp->next;
    }
    if (temp == NULL) {
        return;
    }
    prev->next = temp->next;
    free(temp);
}

// 修改学生节点
void modifyStudentNode(StudentNode* head, int no, const char* name) {
    StudentNode* temp = head;
    while (temp != NULL) {
        if (temp->no == no) {
            strcpy(temp->name, name);
            return;
        }
        temp = temp->next;
    }
}

// 查找学生节点
StudentNode* searchStudentNode(StudentNode* head, int no) {
    StudentNode* temp = head;
    while (temp != NULL) {
        if (temp->no == no) {
            return temp;
        }
        temp = temp->next;
    }
    return NULL;
}

// 打印链表中的学生信息
void printStudentList(StudentNode* head) {
    StudentNode* temp = head;
    while (temp != NULL) {
        printf("No: %d, Name: %s\n", temp->no, temp->name);
        temp = temp->next;
    }
}

// 释放链表内存
void freeStudentList(StudentNode** head) {
    StudentNode* temp = *head;
    while (temp != NULL) {
        StudentNode* nextNode = temp->next;
        free(temp);
        temp = nextNode;
    }
    *head = NULL;
}

int main() {
    StudentNode* head = NULL;

    // 插入学生节点
    insertStudentNode(&head, 1, "Alice");
    insertStudentNode(&head, 2, "Bob");
    insertStudentNode(&head, 3, "Charlie");

    // 打印链表中的学生信息
    printf("Initial student list:\n");
    printStudentList(head);

    // 修改学生节点
    modifyStudentNode(head, 2, "Brian");
    printf("\nAfter modifying student 2:\n");
    printStudentList(head);

    // 删除学生节点
    deleteStudentNode(&head, 1);
    printf("\nAfter deleting student 1:\n");
    printStudentList(head);

    // 查找学生节点
    StudentNode* student = searchStudentNode(head, 3);
    if (student != NULL) {
        printf("\nFound student 3: No=%d, Name=%s\n", student->no, student->name);
    } else {
        printf("\nStudent 3 not found.\n");
    }

    // 释放链表内存
    freeStudentList(&head);

    return 0;
}


strcmp和strcat和strcpy的示例

1注意事项:
对于字符串数组 char str1[5] = “apple”,数组的大小为 5。这是因为在 C 语言中,字符串必须以结束符 \0 结尾,占据一个额外的字节空间。

在这个例子中,虽然字符串 “apple” 本身只包含 5 个字符(a、p、p、l、e),但编译器会自动在字符串的末尾添加一个结束符 \0。因此,实际上占据了 6 个字节的内存空间。

所以,尽管数组 str1 的大小为 5,但是为了容纳字符串 “apple” 及其结束符,编译器会自动将其扩展到 6 个字节的空间,最后一个字节用于存储结束符 \0。

要注意的是,由于数组大小只有 5,而字符串需要的空间至少为 6(包括结束符),所以在这种情况下会发生缓冲区溢出的问题。应该确保数组大小足够容纳字符串及其结束符 \0,以避免潜在的问题。

#include 
#include 

int main() {
    char str1[] = "apple";
    char str2[] = "bababa";
    // 1.strcmp用来对比两个字符串是否相同?0(相同);<0(str1
    printf("-------------strcmp---------\n");
    int res = strcmp(str1, str2);

    if (res == 0) {
        printf("字符串相同\n");
    } else if (res < 0) {
        printf("str1小于str2\n");
    } else {
        printf("str1>str2\n");
    }

    // 2.strcat():用于将字符串进行拼接
    printf("-------------strcat----------\n");
    strcat(str1, str2);
    printf("%s\n", str1);
    //strcat并不会改变字节数,但是会改变长度
    int len=strlen(str1);
    printf("字节数:%zu\t串长度为:%d\n", sizeof(str1),len);

    //3.strcpy作用:将str1复制到str3(第一个参数是接受的,第二个参数是输出的)
    printf("----------strcpy----------\n");
    char str3[2];
    strcpy(str3,str1);
    int length=strlen(str3);
    printf("str3:%s\t长度为%d\t字节数为%zu\n",str3,length,sizeof(str3));

    return 0;
}

你可能感兴趣的:(算法,数据结构)