2012-01-06 25 views
30

Đây là chương trình tôi đang cố chạy thẳng từ phần 1.9 của "Ngôn ngữ lập trình C".Tại sao tôi nhận được lỗi "loại xung đột cho đường biên" khi biên soạn ví dụ dòng dài nhất trong chương 1 của K & R2?

#include <stdio.h> 
#define MAXLINE 1000 

int getline(char line[], int maxline); 
void copy(char to[], char from[]); 

main() 
{ 
    int len; 
    int max; 
    char line[MAXLINE]; 
    char longest[MAXLINE]; 

    max = 0; 
    while ((len = getline(line, MAXLINE)) > 0) 
     if (len > max) { 
     max = len; 
     copy(longest, line); 
     } 
    if (max > 0) 
     printf("%s", longest); 
return 0; 
} 


int getline(char s[], int lim) 
{ 
    int c, i; 

    for (i=0; i<lim-1 && (c=getchar()) !=EOF && c != '\n'; ++i) 
     s[i] = c; 
    if (c == '\n') { 
     s[i] = c; 
     ++i; 
    } 
    s[i] = '\0'; 
    return i; 
} 


void copy(char to[], char from[]) 
{ 
    int i; 

    i = 0; 
    while ((to[i] = from[i]) != '\0') 
     ++i; 
} 

Đây là lỗi tôi nhận được khi tôi cố gắng để biên dịch chương trình sử dụng Ubuntu 11.10:

cc  word.c -o word 
word.c:4:5: error: conflicting types for ‘getline’ 
/usr/include/stdio.h:671:20: note: previous declaration of ‘getline’ was here 
word.c:26:5: error: conflicting types for ‘getline’ 
/usr/include/stdio.h:671:20: note: previous declaration of ‘getline’ was here 
make: *** [word] Error 1 

Chỉ cần chắc chắn rằng nó không phải là một vấn đề với bản in trong cuốn sách, tôi tham chiếu tập hợp các câu trả lời này để quay lại các bài tập của chương từ cuốn sách (http://users.powernet.co.uk/eton/kandr2/krx1.html) và tôi nhận được một lỗi tương tự khi tôi cố gắng chạy các bài tập 18, 19, 20 , 21, v.v., từ liên kết đó. Thật khó để học khi tôi không thể chạy các chương trình để xem chúng xuất ra như thế nào. Vấn đề này bắt đầu khi giới thiệu các mảng ký tự và các cuộc gọi hàm trong một chương trình. Tôi đánh giá cao bất kỳ lời khuyên nào về vấn đề này.

Trả lời

28

Vấn đề là getline() là chức năng thư viện chuẩn. (được xác định trong stdio.h) Chức năng của bạn có cùng tên và do đó xung đột với nó.

Giải pháp là chỉ cần thay đổi tên.

+4

Đã bỏ qua 20 phút. SHould've chỉ googled –

+0

hahaha tôi quá @ dmtri.com – samrap

+1

** getline() ** là ** không ** chức năng thư viện chuẩn, nó là phần mở rộng, vì @moooeeeep đã nêu rõ hơn và cũng ở đây http: //stackoverflow.com/questions/7376566/can-an-ansi-c-compliant-implementation-include-additional-functions-in-its-stand bởi @Dietrich Epp. Vì vậy, nếu bạn đang viết mã ngày hôm nay, bạn không nên sử dụng 'getline()', nhưng nếu bạn phụ thuộc vào một thư viện đã sử dụng chức năng 'getline()' tự thực hiện của nó thì sao? Tôi nghĩ, theo nghĩa rộng, câu trả lời của @ moooeeeep là phù hợp hơn. –

2

Bạn phải thay đổi tên của tuyến đường vì nó đã tồn tại.

+0

@downvoter: lý do? – BlackBear

+0

Tôi có cùng một vấn đề được mô tả trong câu hỏi. Tôi tra cứu một số tài liệu tham khảo C để xem liệu 'getline() 'có được xác định trong thư viện chuẩn nhưng không tìm thấy nó, làm tôi bối rối hơn nữa. Các câu trả lời mà tôi thấy hữu ích ở đây là các câu trả lời xác định rằng 'getline()' được định nghĩa trong Thư viện chuẩn _POSIX_. Đơn giản chỉ cần nói 'nó đã tồn tại' là khó hiểu và có lẽ không chính xác. –

+0

@IsaacKleinman mặc dù tôi thừa nhận rằng câu trả lời của tôi không đủ chính xác, nhưng vẫn đúng: trích dẫn từ câu trả lời được chấp nhận "Vấn đề là getline() là hàm thư viện chuẩn. (Được định nghĩa trong stdio.h)" – BlackBear

3

/usr/include/stdio.h:671:20: note: previous declaration of ‘getline’ was here

Điều đó sẽ cho bạn gợi ý. Hãy thử và đổi tên hàm getline() trong mã thành mã khác.

Ngoài ra, việc khai báo main() theo cách này là kiểu cũ. Hàm không có kiểu trả về và đối số đã khai báo, theo mặc định, chấp nhận một số đối số không xác định và trả về một int. Đây là trường hợp gần như đối với main(): nó trả về một int, nhưng có hai đối số. Bạn đã tốt hơn khai báo nó như:

int main(int argc, char **argv) 

hay:

int main(int argc, char *argv[]) 
+1

Điều này đã không được chấp nhận chỉ trong C99. Định nghĩa hàm kiểu cũ vẫn được sử dụng cho hàm 'main' trong phiên bản K & R cuối cùng (ấn bản 2). – ouah

+0

Thật sao? Tôi nghĩ rằng nó đã không được chấp nhận cho miễn là đặc điểm kỹ thuật ANSI C đầu tiên ... – fge

+0

Dù sao - bình luận chỉnh sửa – fge

7

Điều này là do stdio.h có một chức năng getline().

Vì vậy, một điều đơn giản để làm cho công việc này sẽ được đổi tên chức năng của bạn để my_getline()

Cả getline()getdelim() ban đầu GNU phần mở rộng. Chúng được chuẩn hóa trong POSIX.1-2008.

+0

Đây là câu trả lời đúng cho câu hỏi. Không phải cách khắc phục nó, nhưng tại sao nó lại thất bại nếu cuốn sách được viết bởi các chuyên gia? "Bởi vì cuốn sách được viết khi getline chưa được chuẩn hóa." Ahhh, Cảm ơn bạn. – mimoralea

+0

@mikiemorales Cuốn sách được viết theo tiêu chuẩn khác. Xem câu trả lời của tôi: http://stackoverflow.com/a/17378451/1025391 – moooeeeep

2

getline bây giờ là một chức năng POSIX khai báo trong stdio.h

Đổi tên bạn getline chức năng để một tên khác và nó sẽ biên dịch.

1

Đã là một hàm được gọi là getline được định nghĩa trong tệp "stdio.h". Vì vậy, một cuộc xung đột trong nguyên mẫu! Đổi tên chức năng của bạn thành "my_getline" hoặc tên khác và tất cả sẽ ổn!

27

Chức năng xung đột getline() là phần mở rộng GNU/POSIX.

K & R nêu rõ rằng chúng giải quyết ANSI C cụ thể trong sách (c.f.), không cung cấp chức năng này.

Các tác giả trình bày hướng dẫn đầy đủ về lập trình ngôn ngữ chuẩn ANSI.

Để đặt gcc thành chế độ tương thích "K & R", bạn có thể chỉ định chế độ ANSI hoặc ISO để biên dịch. Các mục đích này nhằm vô hiệu hóa tiện ích mở rộng, ví dụ: chức năng getline(). Điều này cuối cùng có thể loại bỏ nhu cầu chỉnh sửa các ví dụ khác được cung cấp bởi K & R.

Ví dụ, sau đây biên dịch tốt:

$ gcc test.c -ansi 
$ gcc test.c -std=c89 

(. Ngoại trừ việc họ phàn nàn về kiểu trả về mặc định ngầm của main() với -Wall)

ràng trên một số hệ thống, các chế độ này có thể không làm việc như được trình bày ở đây (apparantly some version(s) of Mac OS fail to correctly disable all extensions). Tôi đã thử nghiệm thành công trên máy của tôi:

$ gcc --version 
gcc (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8) 
Copyright (C) 2012 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+0

Tôi đã thử 'gcc test.c -ansi'. Có vẻ như nó không hoạt động. – Jack

+0

@Jack bạn đã thử phiên bản OS/- nào? – moooeeeep

+0

Tôi sử dụng macOS Sierra Phiên bản 10.12.5. Bất kỳ sự thay thế nào cho 'gcc test.c -ansi' trong hệ điều hành này? – Jack

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