2015-12-17 42 views
0

我是一名C初學者,已經搜索了所有問題並嘗試了相關答案,但似乎沒有任何工作。 它讀取姓名和UUN,然後說分段錯誤:11並退出。 請幫忙!分段錯誤:使用scanf時爲11。不會讀過UUN?

typedef struct { 
char *name; 
char *surname; 
char *UUN; 
char *department; 
char gender; 
int age; 
} student_t; 


int main(void) { 
int i, len; 
student_t student_t[6]; 

student_t[0].name = "John"; 
student_t[0].surname = "Bishop"; 
student_t[0].UUN = "s1234"; 
student_t[0].department = "Inf"; 
student_t[0].gender = 'm'; 
student_t[0].age = 18; 

student_t[1].name = "Lady"; 
student_t[1].surname = "Cook"; 
student_t[1].UUN = "s2345"; 
student_t[1].department = "Eng"; 
student_t[1].gender = 'f'; 
student_t[1].age = 21; 

student_t[2].name = "James"; 
student_t[2].surname = "Jackson"; 
student_t[2].UUN = "s3456"; 
student_t[2].department = "Eng"; 
student_t[2].gender = 'm'; 
student_t[2].age = 17; 

for (i = 3; i < 6; i++) { 
    printf("Enter your name: "); 
    scanf(" %s", student_t[i].name); 
    printf("Enter your surname: "); 
    scanf(" %s", student_t[i].surname); 
    printf("Enter your UUN: "); 
    scanf(" %s", student_t[i].UUN); 
    printf("Enter your department: "); 
    scanf(" %s", student_t[i].department); 
    printf("Enter your gender: "); 
    scanf(" %c", &student_t[i].gender); 
    printf("Enter your age: "); 
    scanf(" %d", &student_t[i].age); 
} 

return EXIT_SUCCESS; 
} 
+1

你從來沒有爲字符串分配內存,所以你通過未初始化的指針寫入內存。 – Barmar

+1

..以及:'for(i = 4; i <= 6; i ++)'以及所有的[1],[2],[3]都表明OP不知道數組索引從0開始,所以'student_t student_t [6];',索引0,1,2,3,4,5都是有效的。 6不是。 –

+1

即使第一個塊由於加載指向字符串文字的指針而運行正常,將前三個視爲與最後三個不同也是不好的主意。 OP應該爲這兩個塊的數據分配空間和strcpy。 –

回答

1

你的主要問題是在這樣做的讀入未初始化的指針,例如環:

的scanf( 「%S」,student_t [I]。名稱);

一個可能的修復可能會沿着這些路線走:

段錯誤的事件,(你不要回避)的
char tmp[256]; 
if (scanf(" %255s", tmp) != 1) { /* handle error */ } 
student_t[i].name = strdup(tmp); 

一個額外的常見來源,就是這種線:

student_t[1].name = "Lady"; 

它將字段'name'設置爲指向一個文字字符串(這裏的「Lady」),它很可能位於只讀存儲器中。然後,如果你以後學嘗試閱讀到相同的位置:

scanf(" %s", student_t[i].name); 

它會試圖掃描到哪裏是指針指向的數據寫入(成只讀存儲器)。這是未定義的行爲,也會導致段錯誤事件。即使原始值(「Lady」)恰好位於讀寫內存中,它對於「Lady」來說可能只是足夠大 - 不能保證它可以保存更長的字符串(例如「Christopher」 )。

與scanf函數的您的其他用途,該行確實有一對夫婦的其他問題:

  1. 您應經常檢查返回值(不是參數值),以確保手術成功。 (在這種情況下,如果返回值不等於1,則失敗)
  2. 格式說明符:'%s'不限制輸入的字符數。這可能導致輸入緩衝區溢出,這是未定義的行爲,導致段錯誤事件。

建議使用:

char buffer[256]; 
... 
printf("Enter your name: "); 
if (1 != scanf(" %255s", buffer)) 
{ 
    perror(" scanf for name failed"); 
    cleanup(); // free all memory allocations 
    exit(1); 
} 
// implied else, scanf successful 
student_t[i].name = strdup(buffer); 

爲了使cleanup()容易得多,建議改變線路是這樣的:因爲內存strdup()分配

student_t[2].name = "James"; 

student_t[2].name = strdup("James"); 

應回去吧與free()聯繫在一起,而文字值(如「Lady」)不能。

+0

'student_t [i] .name'不會寫字符串文字,因爲'i'永遠不會將該指針的值指向字符串字面值 –

+0

謝謝,我重新編輯以希望更清晰地顯示出來 –

+0

@JohnHascall,this聲明:*因爲使用strdup()分配的內存應該以free()返回給系統,而文字值(如「Lady」)不能。*不完全正確。在字段上使用strdup()的原因是因爲'cleanup()'只能循環;通過數組'student_t []'沒有任何關於字符串文字(只讀存儲器)結束的地方以及'堆'中數據的指針開始 – user3629249