[英]Weird output of char * with getchar to printf
我正在為即將到來的課程使用C語言技能,在使用getchar
構建字符串之后,我在printf
遇到了這個奇怪的輸出。 具體來說,我嘗試輸出的任何字符串都將在每個字母后附加相同的字符序列。 foo
變成"f?8@{?o?8@{?o?8@{?"
使用cc
編譯,並使用Apple LLVM 5.0
(Xcode)進行f¿:¿o¿:¿0¿:¿
編譯。 這是說明問題的示例代碼:
char * input_buffer = malloc( sizeof( char ) );
char c;
while ( ( c = getchar() ) != '\n' ) {
strcat(input_buffer, &c);
}
// problem output
printf( "\n%s\n", input_buffer );
// foo -> f¿:¿o¿:¿0¿:¿
// weird side effect is the 4 is required to get a proper len
printf("\ncharacters: %lu\n", strlen( input_buffer ) / 4 );
我到處搜索過,但在其他任何地方都看不到,但是這似乎有點極端。 這是我沒有考慮到的某種編碼問題嗎?
您不能調用strcat(input_buffer, &c);
。
傳遞給strcat
每個參數都必須是有效的以null結束的字符串。
&c
為0后下一個字節的可能性很小。
input_buffer
指向的第一個字節為0的機會也不是很高。
換句話說, strcat
在兩個參數中都讀取“垃圾”,直到遇到一個0字符為止。
更改:
while ( ( c = getchar() ) != '\n' ) {
strcat(input_buffer, &c);
}
至:
for (int i=0; 1; i++)
{
c = getchar();
if (c == '\r' || c == '\n')
{
input_buffer[i] = 0;
break;
}
input_buffer[i] = c;
}
input_buffer
分配僅一個char
空間。 strcat(input_buffer, &c);
是錯的。 您正在將字符(不以null結尾的字符串)與字符串連接。 getchar
返回int
類型,但您聲明c
為char
類型。 char * input_buffer = malloc( sizeof( char ) );
sizeof (char)
根據定義為1。 這將為單個字符分配空間,並使input_buffer
指向該字符。
您也沒有檢查分配是否成功。 當失敗時, malloc
返回一個空指針; 您應該經常檢查。
並且input_buffer
指向的已分配char
對象包含垃圾。
char c;
while ( ( c = getchar() ) != '\n' ) {
strcat(input_buffer, &c);
}
getchar()
返回一個int
,而不是char
。 您可以將結果分配給char
對象,但是這樣做會丟失檢測和文件結束或錯誤情況的能力。 當沒有更多的字符要讀取時, getchar()
返回EOF
; 您應該始終進行檢查,並且這樣做需要將結果存儲在int
。 ( EOF
是一個整數值,不等於任何有效字符。)
strcat(input_buffer, &c);
input_buffer
指向一個未初始化的char
。 您可以將其視為由單個char
元素組成的數組。 strcat
的第一個參數必須已經包含一個以null終止的有效字符串,並且它必須具有足夠的空間來容納該字符串以及您要附加的內容。
c
是單個char
對象,包含您剛剛使用getchar(). The second argument to
讀取的任何字符getchar(). The second argument to
strcat getchar(). The second argument to
is a
char * , so you've got the right type -- but that
char *`必須指向有效的以null終止的字符串。
strcat
首先將掃描input_buffer
指向的數組以找到終止的'\\0'
字符,以便知道從何處開始附加-並且它可能會掃描到內存中,該內存不屬於已聲明或分配的任何對象,可能會崩潰您的程序。 如果沒有中斷,它將復制以c
開頭的字符,並將其復制到您不擁有的內存中。 您有多種形式的不確定行為。
您不需要使用strcat
將單個字符附加到字符串。 您可以分配它。
這是一個簡單的例子:
char input_buffer[100];
int i = 0; /* index into input_buffer */
int c;
while ((c = getchar()) != '\n' && c != EOF) {
input_buffer[i] = c;
i ++;
}
input_buffer[i] = '\0'; /* ensure that it's properly null-terminated */
為了簡單起見,我分配了固定大小的緩沖區,而不是使用malloc
。
同樣為了簡單起見,我省略了所有檢查,確保輸入沒有超出輸入緩沖區的末尾。 如果是這樣, 如果幸運的話 ,該程序可能會崩潰; 如果您不走運,它可能會在消除不屬於您的內存時發揮作用。 如果輸入線不太長,它將正常運行。 在任何實際程序中,您都需要檢查一下。
順便說一句,使用fgets()
可以更輕松地完成此處的工作-但最好學習一下工作在較低級別上的工作方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.