2013-09-27 40 views
1

我有一個有點古怪的問題與C.字符串元素不保留指定的值

我有一個.c文件實施的結構,另一個使用它。有問題的結構是關於學生的基本信息(姓名和成績)。實現文件具有的功能

  • 初始化
  • 讀名
  • 讀年級
  • 釋放內存(刪除實例)

主文件去如下:

int main (void){ 
    char inBuff[30]; 
    char* name = NULL; 
    int grade; 
    Student Stu; 

    printf("main: Please enter the name\n"); 
    fgets(inBuff, 30, stdin); 
    name = malloc((sizeof(char)+1)*strlen(inBuff)); 
    strncpy (name, inBuff, 20); 

    printf("main: Please enter the grade\n"); 
    scanf("%d", &grade); 

    InitializeStudent (name, grade, &Stu); 

    /*value testing*/ 
    printf("main: %s\n", Stu.name); 
    printf("main: %d\n", Stu.grade); 

    printf ("main: The student's name is %s\n", NameOfStudent(Stu)); 
    printf ("main: The student's grade is %d\n", GradeOfStudent(Stu)); 

    FreeStudent(&Stu); 
    free (name); 
    return 0; 
} 

printf() st InitializeStudent()函數中的函數似乎顯示正確賦值的值。然而,無論輸入如何,Stu.nameNameOfStudent(Stu)都返回ASCII,並且Stu.GradeGradeOfStudent(Stu)返回2675716(其似乎是存儲器地址)。

值得注意的是,它已經被指定NameOfStudent()GradeOfStudent()是通過按值,而不是使用一個指針(即,應使該結構的副本,並在傳遞給功能)和具有char*和事實int分別返回類型,而InitializeStudent()傳遞一個指針並且是一個void函數。

而且可能重要的是,學生的姓名字段作爲

char name[20]; 

而不是

char* name; 

Student結構定義如下初始化:

#define MAXNAMESIZE 20 
typedef struct { 
    char name[MAXNAMESIZE]; 
    int grade; 
} Student; 

的要求,初始化學生的代碼如下

void InitializeStudent (char *name, int grade, Student *S) { 
    printf ("InitializeStudent: entered initialization\n"); 
    int i = 0; 
    S = malloc (sizeof(Student)); 
    for (i = 0; i< strlen(name); i++) 
     if (name[i] == '\n') 
      name[i] = '\0'; 
    strncpy(S->name, name, 20); 
    S->grade = grade; 

    printf ("InitializeStudent: %s\n", S->name); 
    printf ("InitializeStudent: %d\n", S->grade); 
} 
+0

請考慮縮進你的代碼,並添加的聲明'struct Student'。編輯:對,我注意到代碼是縮進,除非你使用製表符。對於SO,最好在發佈之前將縮進轉換爲編輯器中的空格。 – millimoose

+2

也可能重要的是提供給我們'NameOfStudent'和'GradeOfStudent'的實現。 –

+3

請顯示'InitializeStudent(name,grade,&Stu)'的代碼' – StarPilot

回答

2

的問題是,你分配在InitializeStudent功能Student結構,當你一個指針傳遞給一個已分配的結構。

而且因爲參數是通過值(即複製)傳遞給函數的,所以指針S是一個副本,所以當你分配給它時,你只能分配給你函數中的本地副本。這就是爲什麼在main功能結構沒有初始化,因爲你只初始化您在InitializeStudent功能分配結構,而不是一個你通過。

最後,要小心strncpy彷彿源字符串長於你傳遞給它的長度,那麼函數將會而不是添加字符串終止符。


哦,對了,還有去除fgets換行的一個簡單的方法:只要「刪除」的最後一個字符:

/* If `name` is not a `NULL` pointer, and the length is larger than zero 
* and the last character is a newline... 
*/ 
if (name != NULL && strlen(name) > 0 && name[strlen(name) - 1] == '\n') 
    name[strlen(name) - 1] = '\0'; 
+0

我第一次申報時分配了結構嗎?否則,唯一的分配是輸入中使用的字符串「名稱」。另外,就我所知,傳遞一個指向函數的指針是C模仿傳遞引用的方式,並且使用 - >應該允許我初始化原始結構體? –

+0

@ user2824330是的,聲明爲非指針的所有內容都已分配。不管它是本地類型(比如'int')還是結構都沒關係。 –

+0

好吧,刪除InitializeStudent中的malloc似乎工作。 –