【问题标题】:Weird characters in string with C (Structs, pointers, and strings)使用 C 语言的字符串中的奇怪字符(结构、指针和字符串)
【发布时间】:2021-07-01 04:31:05
【问题描述】:

您好,我正在创建一个包含学生信息的链接列表。

但是,当显示 student 结构的字符串变量时,它显示的字符不是它应该显示的字符串。这是我的代码中的 sn-p(我删掉了与我的问题无关的代码):

# include <stdio.h>
# include <stdlib.h>

struct Student {
    int student_number[2];
    char *last;
    char *first;
    char *course; 
    int year;
    int age;
    char sex; 
    int grade;
    struct Student * next;
};

typedef struct Student Student;

struct SLList {
    Student * head;
    Student * tail;
    int size;
};

typedef struct SLList SLList;

void initList(SLList * list){
    list->head = 0;
    list->tail = 0;
    list->size = 0;
}

Student * getStudent(SLList * list, int index) {
    Student * current = list->head;
    for (int i = 0; i < index; i ++) {
        current = current->next;
    }
    return current;
}

Student * createStudent(int * number, char *last, char *first, char * course, int year, int age, char sex, int grade){
    Student * student = (Student *) malloc(sizeof(Student));
    student->student_number[0] = number[0];
    student->student_number[1] = number[1];
    student->last = last;
    student->first = first;
    student->course = course;
    student->year = year;
    student->age = age;
    student->sex = sex;
    student->grade = grade;
    student->next = 0;

    return student;
}

void enrolStudent(SLList * list, int index){
    Student * student;
    int i, found = 1;
    int student_number[2];
    char last[15];
    char first[15];
    char course[15];
    int year;
    int age;
    char sex;
    int grade;

    printf("Student Number: ");
    scanf("%i-%i", &student_number[0], &student_number[1]);

    printf("Last Name: ");
    scanf("%s", last);

    printf("First Name: ");
    scanf("%s", first);

    printf("Course: ");
    scanf("%s", course);

    printf("Year: ");
    scanf("%i", &year);

    printf("Age: ");
    scanf("%i", &age);

    printf("Sex [M or F]: ");
    scanf(" %c", &sex);

    printf("Final Grade: ");
    scanf("%i", &grade);

    Student * toInsert = createStudent(student_number, last, first, course, year, age, sex, grade);

    if (index == 0){
        toInsert->next = list->head;
        list->head = toInsert;
    }
    if (index == list->size){
        if (list->tail != 0) {
            list->tail->next = toInsert;
        }
        list->tail = toInsert;
    }
    list->size ++;

    return;

}

void showStudents(SLList * list, int index) {
    Student * student = getStudent(list, index);

    printf("\n");
    printf("Student Number: %i-%i\n", student->student_number[0], student->student_number[1]);
    printf("Last Name: %s\n", student->last);
    printf("First Name: %s\n", student->first); //! error in printing strings 
    printf("Course: %s\n", student->course);
    printf("Year Level: %i\n", student->year);
    printf("Age: %i\n", student->age);
    printf("Sex: %c\n", student->sex);
    printf("Final Grade: %i\n", student->grade);
    printf("\n");
}


int main(){
    int choice = 0;
    int rtn = 0;

    SLList students;
    initList(&students);

    printf("What do you want to do?\n");
    printf("1. Enrol a student\n");
    [...]
    printf("4. Display all student/s\n");


    for(;;){
        printf("\nEnter a number: ");
        rtn = scanf("%d", &choice);

        if (choice == 1) {
            enrolStudent(&students, students.size);
        } else if (choice == 4) {
            int i;
            for (i = 0; i < students.size; i ++){
                showStudents(&students, i);
            }
            printf("Displaying %i of %i student(s)\n", i, students.size);
        }
        [...]
}

我相信我需要为struct的char *变量分配内存,但我不知道应该怎么做。

希望能得到一些帮助。谢谢!

【问题讨论】:

  • 没有什么奇怪的,你没有在 enrolStudents 中复制字符串。

标签: c pointers struct malloc


【解决方案1】:

您将局部变量地址传递给 createStudent 并简单地将其分配给错误的内部指针。

您可以使用类似strdup 的调用方式,如下所示

student->last = strdup(last);
student->first = strdup(first);
student->course = stddup(course);

或者给lastfirstcourse分配空间并复制字符串

【讨论】:

    【解决方案2】:

    您的假设是正确的:您将指向堆栈对象的指针分配给列表元素。因此,在程序进一步执行的过程中,内容很可能会被覆盖,这会在进一步的输出中为您提供奇怪的字符。

    正确的方法是在createStudent 期间为字符串分配内存,这是通过最小字符串长度的malloccalloc 完成的。而且你的函数中已经有一个例子,所以我有点惊讶你说你不知道该怎么做。另一种可能性是为此目的调用strdup,它基本上完全结合了分配和字符串复制。

    哦,还有一句话:请从你职业生涯的一开始就养成一种习惯,那就是你自己清理。含义:无论你分配什么,在使用后释放它。在您的情况下:如果您有一个 createStudent 函数,请创建一个 destroyStudent 函数。如果您在某处有一个链表,请在退出程序之前释放它。早点养成这个习惯可以避免将来出现内存泄漏。

    【讨论】:

    • 啊,是的,我对它有点困惑,因为我在 createStudent 函数中使用了malloc,但它仍然会产生奇怪的字符。我必须在 enrolStudent 函数中使用 malloc 才能使用超出其范围的字符串。而且我确实有一个免费的功能。指针和malloc 还是新手,但我正在学习!感谢您的帮助!
    • @KyleAngeloGonzales 在 enrolStudent 中包含堆栈对象没有任何问题。但是你必须正确地创造和摧毁你的学生。由于字符串与学生组合在一起,因此我不会在创建 Student 对象时将它们分配到其他地方。
    猜你喜欢
    • 2015-08-06
    • 2011-03-08
    • 2021-12-13
    • 2020-10-30
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    相关资源
    最近更新 更多