2015-10-12 43 views
20

Trong khi tôi đang đặt cùng một chức năng để hoa trong C++ Tôi nhận thấy rằng tôi đã không nhận được kết quả mong muốn trong C.C chuỗi sang chữ hoa trong C và C++

hàm C++

#include <iostream> 
#include <cctype> 
#include <cstdio> 

void strupp(char* beg) 
{ 
    while (*beg++ = std::toupper(*beg)); 
} 

int main(int charc, char* argv[]) 
{ 
    char a[] = "foobar"; 
    strupp(a); 
    printf("%s\n", a); 
    return 0; 
} 

Output như mong đợi:

FOOBAR 


C chức năng

#include <ctype.h> 
#include <stdio.h> 
#include <string.h> 

void strupp(char* beg) 
{ 
    while (*beg++ = toupper(*beg)); 
} 

int main(int charc, char* argv[]) 
{ 
    char a[] = "foobar"; 
    strupp(a); 
    printf("%s\n", a); 
    return 0; 
} 

Kết quả là kết quả mong đợi với ký tự đầu tiên mất tích

OOBAR 

Có ai biết tại sao kết quả bị cắt khi biên dịch trong C?

+5

Và nếu bạn thực sự muốn thực hiện điều này trong 'C++': 'std :: transform (a, a + strlen (a), a, std :: toupper); ' – PaulMcKenzie

+0

Bạn có thể giải thích lý do tại sao bạn mong đợi điều này để chuyển đổi một chuỗi thành chữ hoa? Cụ thể, tại sao bạn mong đợi phía bên phải của '=' được đánh giá trước bên trái? –

+0

Tôi biết ơn tất cả những người đã đưa ra phản hồi và thông tin giá trị được cung cấp –

Trả lời

29

Vấn đề là không có điểm chuỗi trong

while (*beg++ = toupper(*beg)); 

hành vi Vì vậy, chúng tôi đã xác định. Trình biên dịch đang làm gì trong trường hợp này là đánh giá beg++ trước toupper(*beg) Trong C, trong C++ nó đang làm theo cách khác.

+0

Điều này có nghĩa là việc sao chép chuỗi c-1 kiểu cổ điển 'while (* s ++ = * t ++); 'có hành vi không xác định? –

+3

@markh Không phải vì đó là hai biến khác nhau. Điều này đồng nghĩa với 'while (* s ++ = * s ++)' – NathanOliver

+0

@SteveJessop Trên thực tế, 'while (* s ++ = * t ++);' đã định nghĩa hành vi ngay cả khi 's == t'. Lý do 'strcpy' là không xác định với các vùng chồng chéo là' strcpy' không nhất thiết phải được thực hiện với 'while (* s ++ = * t ++);'. – immibis

15
while (*beg++ = std::toupper(*beg)); 

dẫn đến hành vi không xác định.

Cho dù *beg++ được sắp xếp trước hoặc sau std::toupper(*beg) không được chỉ định.

Việc sửa chữa đơn giản là sử dụng:

while (*beg = std::toupper(*beg)) 
    ++beg; 
10

Dòng

while (*beg++ = toupper(*beg)); 

chứa một tác dụng phụ trên một thực thể mà đang được sử dụng hai lần. Bạn không thể biết, có hay không beg ++ được thực hiện trước hoặc sau khi * beg (bên trong toupper). Bạn thật may mắn khi cả hai triển khai đều thể hiện cả hai hành vi, vì tôi khá chắc là nó giống nhau đối với C++. (Tuy nhiên, đã có một số thay đổi quy tắc cho C++ 11, mà tôi không nhất định - vẫn còn, đó là phong cách xấu.)

Chỉ cần di chuyển cầu xin ++ ra khỏi tình trạng này:

while (*beg = toupper(*beg)) beg++; 
3

với đối với câu trả lời ở trên, 'f' không bao giờ được chuyển vào bên trong hàm, bạn nên thử sử dụng hàm này:

 while ((*beg = (char) toupper(*beg))) beg++; 
+0

đúc vào char là quan trọng vì giá trị của loại int có thể không phù hợp với loại thu char – vishal

+1

Đó đúc đạt được không có gì mà sẽ không xảy ra mà không có nó anyway. – Flexo

Các vấn đề liên quan