Bạn đã gặp phải vấn đề chính xác với scanf() và% s - điều gì sẽ xảy ra khi bạn không biết có bao nhiêu đầu vào?
Nếu bạn thử chạy char mystring[0];
, chương trình của bạn sẽ biên dịch tốt. Nhưng bạn sẽ luôn luôn segfault. Bạn đang tạo một mảng có kích thước 0, vì vậy khi bạn cố gắng đặt một thứ gì đó vào mảng đó, bạn sẽ ngay lập tức thoát khỏi giới hạn cho chuỗi của bạn (vì không có bộ nhớ nào được phân bổ) - đó là một segfault.
Vì vậy, điểm 1: bạn phải luôn phân bổ kích thước cho chuỗi của mình. Tôi có thể nghĩ đến rất ít trường hợp (được, không có) nơi bạn muốn nói char mystring[0]
thay vì char *mystring
.
Tiếp theo, khi bạn sử dụng scanf, bạn không bao giờ muốn sử dụng trình chỉ định "% s" - vì điều này sẽ không thực hiện bất kỳ kiểm tra giới hạn nào về kích thước của chuỗi. vì vậy ngay cả khi bạn có:
char mystring[512];
scanf("%s", mystring);
nếu người dùng nhập hơn 511 ký tự (kể từ thứ 512 là \ 0), bạn sẽ vượt ra ngoài giới hạn của mảng.Cách khắc phục điều này là:
scanf("%511s", mystring);
Điều này là tất cả để nói rằng C không có cơ sở để tự động thay đổi kích thước một chuỗi nếu có nhiều đầu vào hơn bạn mong đợi. Đây là loại điều bạn phải làm bằng tay.
Một cách để giải quyết vấn đề này là sử dụng fgets().
Bạn có thể nói:
while (fgets(mystring, 512, stdin))
{
/* process input */
}
Sau đó, bạn có thể sử dụng sscanf() để phân tích mystring
Hãy thử đoạn mã trên, với một chuỗi có độ dài 5. Sau 4 nhân vật đã được đọc, mã mà lặp lại một lần nữa để lấy phần còn lại của đầu vào. "Đang xử lý" có thể bao gồm mã để phân bổ lại chuỗi là kích thước lớn hơn và sau đó nối đầu vào mới nhất từ fgets().
Mã trên không hoàn hảo - nó sẽ làm cho chương trình của bạn lặp và xử lý bất kỳ độ dài chuỗi vô hạn nào, vì vậy bạn có thể muốn có một số giới hạn cứng bên trong (ví dụ, lặp tối đa 10 lần).
t nên được thêm rằng% s đọc từ, chứ không phải toàn bộ chuỗi. Bởi vì chuỗi định dạng scanf sử dụng dấu cách và dòng mới làm dấu phân tách.Trong trường hợp này, hãy sử dụng% c thay thế (với chiều rộng trường), hoặc fgets như bạn đã đề cập. Trong trường hợp% c với chiều rộng trường, hãy nhớ khởi tạo toàn bộ chuỗi bộ đệm về 0. –
Chương trình sẽ không luôn luôn segfault. Trong thực tế, có lẽ không phải hầu hết thời gian. Chương trình của bạn có thể sẽ bị âm thầm. Không phải là C đáng yêu sao? :-) –