2017-08-29 89 views
-4
#include <stdio.h> 
#include <string.h> 

int main() 
{ 
    int i; 
    char a[10]; 
    for(i=0;i<10;i++) 
    { 
     scanf("%s",a);// >how this line is working in memory. 
    } 
    return 0; 
} 

在上面的代碼中,我想知道字符串是如何保存在內存中的,因爲我已經將它初始化爲一維字符數組,但是該數組是作爲字符串列表還是單個字符串?爲什麼?1D數組是作爲字符串列表還是單個字符串工作?

+1

你認爲循環有什麼意義嗎?你一遍又一遍地覆蓋同一個位置。 –

+1

一旦數組以空值終止,它就成爲一個字符串。對於一個未初始化的自動'char'數組,它永遠不能被稱爲一個字符串。 –

+0

當你在調試器中觀察'a'時,你會發現什麼? – KevinDTimm

回答

2
char a[10]; 

您已經爲a分配了10個字節的堆棧。但現在,它包含垃圾,因爲你從來沒有給它一個價值。

Scanf不知道這一點。它所做的只是將標準輸入的字節複製到a中,不知道它的大小。

爲什麼你要做一個循環10次?您將覆蓋每個循環迭代a,所以您只能從最後一次獲得該值。

+0

你在混合'scanf'和'printf'嗎? 'scanf'什麼都沒有從'a'中讀取,它會寫入它。 – mch

+0

@mch fixed [15個字符] – stackptr

1

您在循環中重寫了10次相同的緩衝區,這意味着緩衝區將包含在上次讀取時輸入的數據,並且之前的9個字符串將丟失。

也輸入超過9個字符將導致緩衝區溢出,這將調用undefined behavior

您應該限制從輸入緩衝區掃描的字符數,然後clear the rest of the buffer。 (不fflush(stdin);

scanf("%9s",a); 

是否一維數組作爲工作字符串列表,或者一個字符串?

如果它以空字符結尾,那麼yes,它的字符串就像這樣。而a是第一個元素的地址。

+---+---+---+---+---+---+----+ 
| S | t | r | i | n | g | \0 | 
+---+---+---+---+---+---+----+ 
    a a+1 a+2 

如果你通過這個數組即ie。到printf(),他將打印所有字符,直到他達到\0

如果你想讀的字符串列表,您必須聲明二維數組指針到指針到焦和指針分配足夠的內存。

int c; 
char a[10][10]; 
for(i=0;i<10;i++) 
{ 
    scanf("%9s",a[i]); 
    while ((c = getchar()) != '\n' && c != EOF) ; 
} 
+0

事實上,他將它覆蓋了10次。 – tilz0R

+0

是的,但我的意思是輸入數據 –

+0

*您在循環中重寫了9次相同的緩衝區*不,他做了10次。 – tilz0R

2

每個定義的字符串都是一個以空字符結尾的字符數組。所以每個字符數組只要包含一個\0就會成爲一個字符串,定義該字符串的結尾。

在內存中,字符串只是一堆字節(爲簡單起見,但不一定)按順序放置。取字符串"Hello"例如

+---+---+---+---+---+---+ 
| H | e | l | l | o | \0| 
+---+---+---+---+---+---+ 

你的陣列char a[10]指向這樣的存儲器位置具有足夠的空間(在本例中「H」)的開始來存儲10個字符。 通過使用scanf您正在存儲一個字符串(字符序列+終止\0)在該緩衝區(一遍又一遍)。 scanf將字符存儲在那裏,並在寫入最後一個元素之後向元素添加終止的\0。這可以讓你安全地存儲任何字符序列,它是最多9個字符長,自10字符需要是\0

1

是否一維數組作爲工作字符串列表,或者一個字符串?

相當寬泛的問題。

char a[10];聲明表一個具有大小爲10的char元件

char *a[10];聲明表,其具有尺寸爲10個char *元件,其可以可能的點到字符串(當你爲它分配內存和複製有效的C字符串)

在您的代碼中: 'scanf(「%s」,a);' a表示數組的第一個元素的地址。因此,scanf在那裏寫入數據,每次都覆蓋以前的內容。如果您的scanf-ED輸入將需要更多的10個元素(包括尾隨0)存儲,你會得到一個UB,很可能SEGFAUT

5

在C中,是一個0結尾的字符值的序列-IOW,字符串"Hello"被表示爲字符序列'H','e', 'l', 'l', 'o', 0。字符串是存儲char陣列(或wchar_t寬字符串):

char str[] = "Hello"; 

在內存方面,str會是這個樣子:

 +---+ 
str: |'H'| str[0] 
    +---+ 
    |'e'| str[1] 
    +---+ 
    |'l'| str[2] 
    +---+ 
    |'l'| str[3] 
    +---+ 
    |'o'| str[4] 
    +---+ 
    | 0 | str[5] 
    +---+ 

它可以存儲多個字符串在單個1D陣列中,雖然幾乎沒有人這樣做:

char strs[] = "foo\0bar"; 

在存儲器:

 +---+ 
strs: |'f'| strs[0] 
     +---+ 
     |'o'| strs[1] 
     +---+ 
     |'o'| strs[2] 
     +---+ 
     | 0 | strs[3] 
     +---+ 
     |'b'| strs[4] 
     +---+ 
     |'a'| strs[5] 
     +---+ 
     |'r'| strs[6] 
     +---+ 
     | 0 | strs[7] 
     +---+ 

"foo"存儲開始strs[0],而串"bar"存儲開始strs[4]的字符串。

通常,存儲的陣列,你要麼使用的char 2D陣列:

char strs[][MAX_STR_LEN] = { "foo", "bar", "bletch" }; 

或指針的一維數組來char

char *strs[] = { "foo", "bar", "bletch" }; 

在第一種情況下,字符串的內容存儲在strs數組中:

 +---+---+---+---+---+---+---+ 
strs: |'f'|'o'|'o'| 0 | ? | ? | ? | 
     +---+---+---+---+---+---+---+ 
     |'b'|'a'|'r'| 0 | ? | ? | ? | 
     +---+---+---+---+---+---+---+ 
     |'b'|'l'|'e'|'t'|'c'|'h'| 0 | 
     +---+---+---+---+---+---+---+ 

在第二,每個strs[i]到一個不同的,一維數組的char

 +---+     +---+---+---+---+ 
strs: | | strs[0] ------> |'f'|'o'|'o'| 0 | 
     +---+     +---+---+---+---+ 
     | | strs[1] ----+ 
     +---+    | +---+---+---+---+ 
     | | strs[2] -+ +-> |'b'|'a'|'r'| 0 | 
     +---+   |  +---+---+---+---+ 
        | 
        |  +---+---+---+---+---+---+---+ 
        +----> |'b'|'l'|'e'|'t'|'c'|'h'| 0 | 
          +---+---+---+---+---+---+---+ 

在代碼中,a可以(並且通常旨在)存儲單個串這是9個字符長(不包括0終止符)。就像我所說的,幾乎沒有人在單個一維數組中存儲多個字符串,但可以(在這種情況下,a可以存儲2個4個字符的字符串)。

+0

很好的答案。現在我覺得我應該刪除我的:D – muXXmit2X

相關問題