簡體   English   中英

char *與getchar的奇怪輸出到printf

[英]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類型,但您聲明cchar類型。
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM