01/10/2018, 15:48

Thắc mắc khi khai báo giới hạn chuỗi

int main()
{
    char str[10];
    int length;
    printf("Nhap chuoi: ");
    gets(str);
    length = str_length(str);
    printf("
Do dai cua chuoi vua nhap la: %d", length);
    return 0;
}
int str_length(char *p)
{
    int count_length = 0;
    while(*p != '')
    {
        count_length ++;
        p++;
    }
    return count_length;
}

Mình đang thắc mắc tại sao khi khai báo chuỗi là str[10] nhung khi nhập vào nhiều hơn 10ký tự mà vẫn không báo lỗi(khi nhập khoảng 27ký tự trở đi thì bắt đầu báo lỗi stopped working ) . Thậm chí str[0] mà vẫn nhập chuỗi vào được.
Mong được chỉ giáo.

Aster-Dynos viết 17:54 ngày 01/10/2018

Hello bạn lvp, mình không rành Tiếng Việt lắm nên câu trả lời này mình xẽ giải bằng Tiếng Anh nha. Nếu như phần nào bạn không hiểu thì cứ hỏi, I will try my best đễ giải thích bằng Tiếng Việt cho bạn.

####Answer:

So the main problem here in your code lies on this line

gets(str);

which is a very dangerous function to use, as you would have seen this message when your code compiled

warning: the `gets’ function is dangerous and should not be used.

The reason is because the function gets() will just read from the input stream until a newline or an end-of-file character is reached, regardless of whether or not it can store the string into its buffer (char str[10] in your case). In other words, it doesn’t check for any array bound and just throw the input string into the buffer and hope for the best.

Now here comes the second problem. In C, there is NO array bound or string bound checking. This means that the compiler doesn’t throw an exception or error when it tries to read a string that is way past its buffer size limit. Instead it just writes whatever was left over into the next memory section after the buffer. Thus there are 2 possible scenarios here:

  1. You can continue to enter more characters than your buffer size (up until a certain point)

    • This is because the next memory might be empty, or one that the program has not used yet so it can freely write its data into it without any problem. Consider yourself lucky here.

    • On the other hand, if the next memory is not empty and its content doesn’t have write protection. Then the program will overwrite its newly written data into those contents and you might find some variables corrupted or produce garbage value the next time you tried to access them. This is a debugging nightmare, so consider yourself unlucky if you did land here.

  2. Your program CRASHED

  • Congratulation, and consider yourself really lucky because the program tried to access part of the memory that is write protected , i.e only allowed to be accessed by the system itself, and crashed. This is a lot easier to debug than the first case.

####Solution
Now that we have identified the problem, I recommend you to use the function fgets() instead of gets() for your program.

fgets()'s syntax is as follow:

char *fgets(char *str, int n, FILE *stream)

the int n here is important as it limits the size of our string input to prevent our array-out-of- bound/buffer-overflow problem that we had seen above. Your gets() and your char array functions should now be rewritten as

 char str[11];   /* 10 characters + 1 '\0' */
 fgets(str, 11, stdin); 

to solve your problem.

rogp10 viết 17:54 ngày 01/10/2018

fgets sẽ không lọc phím enter cuối.

lvp viết 17:48 ngày 01/10/2018

thanks very much, but stdin what does it mean.

Aster-Dynos viết 18:01 ngày 01/10/2018

Không có chi, bạn. As for your question,

stdin is the standard input stream, where bytes of data come into the program to be manipulated. In most of the cases, the standard input stream here is your keyboard, which you use to enter characters (which are just streams of byte) into your program.

To make this a bit easier to understand, you can think of it as just whatever inputs you are expecting from outside your program.

lvp viết 18:02 ngày 01/10/2018

Vậy làm sao để giải quyết vấn đề này a. Dù cho giới hạn 10 ký tự nhập đúng 10 ký tự mà nó chỉ hiển thị ra 9 ký tự thôi.

rogp10 viết 17:48 ngày 01/10/2018

Tham số thứ hai thực chất là độ dài của buffer. Do phải chứa kí tự '\0' kết thúc rồi trừ đi ‘\n’ nữa khi gõ vào thì chỉ còn thực nhận 8 char.

Aster-Dynos viết 17:51 ngày 01/10/2018

Mình quên, fgets() chỉ lấy n-1 character thôi, như bạn @rogp10 nói. Cái thằng index cuối cùng nó phải dữ cho cái thằng \0.
Nếu như bạn muốn store 10 thằng thì code đúng bây giờ là.

fgets(str,11,stdin)

EDIT: Mình đã fix post phía trên cho bạn luôn.

Bài liên quan
0