2015-08-05 19 views
5

Tôi đang tự học C++ những ngày này và tôi có một số vấn đề hiểu tại sao mã này không biên dịch bằng cách sử dụng #g++ -std=c++11 source.cpp. Trên thực tế nó không quan trọng mà tiêu chuẩn cụ thể tôi sử dụng, nó chỉ không biên dịch.Phạm vi dựa trên vòng lặp trong hàm vượt qua một mảng là giá trị

#include <iostream> 
#include <string> 
using namespace std; 
int print_a(char array[]) 
{ 
    for(char c : array) 
     cout << c; 
    cout << endl; 
    return 0; 
} 
int main(void) 
{ 
    char hello[] {"Hello!"}; 
    print_a(hello); 
    return 0; 
} 

Các thông báo lỗi:

[email protected]:~/Documents$ g++ -std=c++11 source.cpp 
source.cpp: In function ‘int print_a(char*)’: 
source.cpp:6:15: error: ‘begin’ was not declared in this scope 
    for(char c : array) 
      ^
source.cpp:6:15: note: suggested alternatives: 
In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0, 
       from /usr/include/c++/4.9/string:52, 
       from /usr/include/c++/4.9/bits/locale_classes.h:40, 
       from /usr/include/c++/4.9/bits/ios_base.h:41, 
       from /usr/include/c++/4.9/ios:42, 
       from /usr/include/c++/4.9/ostream:38, 
       from /usr/include/c++/4.9/iostream:39, 
       from source.cpp:1: 
/usr/include/c++/4.9/initializer_list:89:5: note: ‘std::begin’ 
    begin(initializer_list<_Tp> __ils) noexcept 
    ^
/usr/include/c++/4.9/initializer_list:89:5: note: ‘std::begin’ 
source.cpp:6:15: error: ‘end’ was not declared in this scope 
    for(char c : array) 
      ^
source.cpp:6:15: note: suggested alternatives: 
In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0, 
       from /usr/include/c++/4.9/string:52, 
       from /usr/include/c++/4.9/bits/locale_classes.h:40, 
       from /usr/include/c++/4.9/bits/ios_base.h:41, 
       from /usr/include/c++/4.9/ios:42, 
       from /usr/include/c++/4.9/ostream:38, 
       from /usr/include/c++/4.9/iostream:39, 
       from source.cpp:1: 
/usr/include/c++/4.9/initializer_list:99:5: note: ‘std::end’ 
    end(initializer_list<_Tp> __ils) noexcept 
    ^
/usr/include/c++/4.9/initializer_list:99:5: note: ‘std::end’ 
+0

Thông báo lỗi trình biên dịch cung cấp cho bạn là gì? – Iowa15

+0

@Davycc, sẽ tốt hơn nếu bạn thêm thông báo lỗi vào câu hỏi. Bạn có thể xóa nhận xét sau đó. –

Trả lời

7

Lý do nó không biên dịch là trong C++ một tham số chức năng như char array[]điều chỉnh để char* array. Chức năng của bạn thực sự trông giống như

int print_a(char* array) 
{ 
.... 
} 

và các vòng phạm vi dựa không thể đối phó với một con trỏ.

Một giải pháp là chuyển mảng bằng tham chiếu. C++ không cho phép bạn truyền các mảng đơn giản theo giá trị. Ví dụ, điều này sẽ chấp nhận một mảng của 5 char s:

int print_a(const char (& array)[5]) 
{ 
    for(char c : array) cout << c; 
    cout << endl; 
    return 42; 
} 

Để khái quát này để mảng có kích thước khác nhau, bạn có thể sử dụng một mẫu:

template <std::size_t N> 
int print_a(const char (& array)[N]) 
{ 
    for(char c : array) cout << c; 
    cout << endl; 
    return 42; 
} 

Tất nhiên, có được dễ dàng hơn các cách để in chuỗi bị chấm dứt bằng không:

char hello[] {"Hello!"}; 
cout << hello << endl; 

Và có các loại thư viện chuẩn làm cho chuỗi ký tự đi qua hoặc bộ đệm char dễ dàng hơn. Ví dụ, std::string, std::vector<char>, std::array<char, N> (nơi N là một hằng số thời gian biên dịch.)

+0

Cảm ơn bạn! Tôi chỉ đang chơi với nó. Đó là loại thực hành cho tôi.Tôi đồng ý, có nhiều cách tốt hơn để làm tương tự nhưng đó là cách đơn giản nhất để tìm hiểu về các vòng lặp dựa trên phạm vi và phân rã mảng, bạn có nghĩ vậy không ?! P.S. Cảm ơn tất cả các bạn. Tôi đánh giá cao sự giúp đỡ của bạn! – Davycc

+1

@Davycc Nó thực sự là loại điều chỉnh. Phân rã là những gì xảy ra khi bạn khởi tạo một con trỏ từ một mảng. – juanchopanza

3

Đây

int print_a(char array[]) 
{ 
    for(char c : array) 
     cout << c; 
    cout << endl; 
    return 0; 
} 

Mảng được phân rã đến một pointer, bởi vì khi bạn vượt qua một mảng có giá trị, những gì chính xác bạn đang làm để vượt qua con trỏ đến phần tử đầu tiên của mảng, và các vòng lặp dựa trên phạm vi không thể làm việc với con trỏ, do đó lỗi bạn đang nhận được.

See this để biết cách phân rã mảng và giải pháp là gì.

Bạn cần sử dụng chuyển bằng tham chiếu hoặc con trỏ.

3

Khi bạn vượt qua mảng đến chức năng, nó là "phân rã" tới con trỏ. Như trong chức năng thực sự trông như thế này: int print_a(char *array) {...} Loại vòng lặp bạn đang sử dụng, được gọi là vòng lặp phạm vi, không thể xử lý con trỏ, là nguồn gốc của lỗi (cố gắng lặp qua con trỏ không có ý nghĩa).

Hoặc bạn phải chuyển mảng theo tham chiếu hoặc chỉ sử dụng vòng lặp thông thường.

Thành thật mà nói, nếu bạn đang sử dụng C++, hãy sử dụng C++. Sử dụng std::string, or std::vector.

+0

Mảng chỉ * phân rã * khi bạn truyền nó vì tham số hàm là một con trỏ. – juanchopanza

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