我對 C 語言作業非常陌生,所以如果我剛剛犯了一個簡單的錯誤,請原諒我,但我非常困惑。我的代碼如下:
#include <stdio.h>
#include <string.h>
int
main ()
{
char first[10],last[10],address[20],city[10],state[3],zipcode[5];
printf("\n\nPart 3:\n");
printf("Please enter your name and address:\n");
printf("First Name: ");
scanf("%s", first);
printf("Last Name: ");
scanf("%s", last);
printf("Address: ");
fgetc(stdin);
fgets(address, 20, stdin);
address[strcspn(address,"[/r/n]")] = 0;
printf("City: ");
scanf("%s", city);
printf("State: ");
scanf("%s", state);
printf("Zipcode: ");
scanf("%s", zipcode);
printf("%s %s\n%s%s, %s, %s",first,last,address,city,state,zipcode);
return 0;
}
一切正常,除非首先讀取最終的列印陳述句不輸出,它只是以姓氏開頭。例子:
對于輸入
Please enter your name and address:
First Name: Ben
Last Name: Johnson
Address: 1234 Smith St
City: Townsville
State: CA
Zipcode: 12345
我得到以下輸出:
Johnson
1234 Smith St
Townsville, CA, 12345
只是不確定哪里出了問題,因為我的第一個變數的輸入方式與其他正在作業的變數完全相同。
uj5u.com熱心網友回復:
您正在寫入陣列city并且zipcode超出范圍,這會導致未定義的行為。
輸入字串Townsville是10字符長,因此它需要11包括終止空字符在內的字符。但是,該陣列city只有10字符空間,因此不足以存盤該字串。因此,當scanf嘗試存盤Townsville到中時city,它會溢位緩沖區。
陣列zipcode也有同樣的問題。對于所述輸入12345,它需要 6 個字符(包括終止空字符),但您只為5字符提供了陣列空間。
為了防止將來出現此類問題,我建議您使用fgets所有資料,因為fgets永遠不會溢位緩沖區,前提是您傳遞正確大小的緩沖區(您在發布的代碼中執行此操作)。但是,這將意味著大量額外的代碼,因為您還必須撰寫代碼以在每次呼叫時洗掉換行符fgets。因此,最好撰寫自己的函式。此函式還可以驗證是否已讀入整行,如果緩沖區不夠大,則列印錯誤訊息。
我已經重寫了您的代碼以使用這樣的功能:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void get_line_from_user( char *buffer, int buffer_size );
int main( void )
{
char first[10],last[10],address[20],city[10],state[3],zipcode[5];
printf("Part 3:\n");
printf("Please enter your name and address:\n");
printf("First Name: ");
get_line_from_user( first, sizeof first );
printf("Last Name: ");
get_line_from_user( last, sizeof last );
printf("Address: ");
get_line_from_user( address, sizeof address );
printf("City: ");
get_line_from_user( city, sizeof city );
printf("State: ");
get_line_from_user( state, sizeof state );
printf("Zipcode: ");
get_line_from_user( zipcode, sizeof zipcode );
printf("%s %s\n%s%s, %s, %s",first,last,address,city,state,zipcode);
return 0;
}
//This function will read exactly one line of input from the
//user. On failure, the function will never return, but will
//print an error message and call "exit" instead.
void get_line_from_user( char *buffer, int buffer_size )
{
char *p;
//attempt to read one line of input
if ( fgets( buffer, buffer_size, stdin ) == NULL )
{
printf( "Error reading from input\n" );
exit( EXIT_FAILURE );
}
//attempt to find newline character
p = strchr( buffer, '\n' );
//make sure that entire line was read in (i.e. that
//the buffer was not too small to store the entire line)
if ( p == NULL )
{
//a missing newline character is ok if the next
//character is a newline character or if we have
//reached end-of-file (for example if the input is
//being piped from a file or if the user enters
//end-of-file in the terminal itself)
if ( getchar() != '\n' && !feof(stdin) )
{
printf( "Line input was too long!\n" );
exit( EXIT_FAILURE );
}
}
else
{
//remove newline character by overwriting it with
//null character
*p = '\0';
}
}
現在,如果輸入太長,程式會給你一個正確的錯誤訊息,而不是溢位緩沖區:
Part 3:
Please enter your name and address:
First Name: Ben
Last Name: Johnson
Address: 1234 Smith St
City: Townsville
Line input was too long!
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/507344.html
上一篇:如何更有效地使用此陳述句
下一篇:迭代代碼以在第n項添加新行
