2010-06-11 23 views
7

Thực hành tốt nhất được coi là gì khi đề cập đến tên chương trình? Tôi đã nhìn thấy:Thực hành tốt nhất khi đề cập đến tên của chương trình trong C

#define PROGRAM_NAME "myprog" 
printf("this is %s\n", PROGRAM_NAME); 

cũng như:

printf("this is %s\n", argv[0]); 

Tôi biết, đó là cách tiếp cận thứ hai sẽ cho tôi ./myprog hơn myprog khi chương trình không được gọi từ $PATH và rằng cách tiếp cận đầu tiên sẽ đảm bảo tính nhất quán liên quan đến tên của chương trình.

Nhưng có điều gì khác, điều đó làm cho một cách tiếp cận vượt trội hơn phương pháp kia không?

+0

Nếu bạn muốn có hằng số, hãy sử dụng hằng số (tức là ở cấp độ toàn cầu, 'const char * const PROGRAM_NAME =" myprog ";'). Làm như vậy sẽ đảm bảo rằng chuỗi chỉ được lưu trữ một lần trong bộ nhớ. – mk12

Trả lời

5

Cách tiếp cận thứ hai là vượt trội khi bạn có nhiều liên kết. Trong các hệ thống * nix, đôi khi hành vi phụ thuộc vào cách bạn gọi một chương trình. Vì vậy, khó mã hóa tên chương trình rõ ràng sẽ là một vấn đề - nó không bao giờ có thể kiểm tra điều đó.

+0

điều này có nghĩa là "hành vi phụ thuộc vào cách bạn gọi một chương trình"? tôi thực sự không thể hiểu được nó. – guest

+0

@guest: ví dụ: 'gcc' và' g ++ 'có thể giống với tệp thực thi, kiểm tra tên được gọi và sửa đổi các tùy chọn liên kết phù hợp. Không thể nhớ nó thực sự là hay không. –

+0

Ví dụ: Theo mặc định, grep in các dòng phù hợp. Ngoài ra, ba chương trình biến thể egrep, fgrep và rgrep có sẵn. egrep giống như grep -E. fgrep giống như grep -F. rgrep cũng giống như grep -r. –

0

Tài khoản cũ vượt trội hơn sau này khi bạn không có argv trong tầm tay.

#define PROGRAM_NAME "myprog" 

void salute() 
{ 
    // no argv available 

    printf("Hello from %s\n", PROGRAM_NAME); 
} 

void main(int argc, char** argv) 
{ 
    salute(); 
} 
+0

có tạo ra sự khác biệt lớn như vậy không? tôi không nghĩ 'argc' và' argv' có giá quá nhiều – guest

+0

ah. tôi hiểu ý bạn là gì. yeah, làm cho cảm giác hoàn hảo – guest

+1

Tôi nhận được quan điểm của bạn, nhưng trong ví dụ của bạn về cơ bản bạn đang tạo ra một biến toàn cầu. Nếu bạn cần program_name, sau đó vượt qua nó (argv) như là một tham số để chào() và vấn đề của bạn được giải quyết. – MJB

0

Phụ thuộc dù argv là trong phạm vi hay không ...

5

tôi đã cố gắng để có tốt nhất của cả hai thế giới:

char const * program_name; 

int main(int argc, char **argv) { 
    program_name = argv[0]; 
    //... 
} 

Nếu bạn cần program_name có sẵn trong một số tập tin khác mà bạn có thể khai báo nó như thế này:

extern char const * program_name; 

Tôi tuyên bố "char const * "bởi vì tôi muốn nó là một con trỏ trỏ tới dữ liệu const. Tôi không chắc chắn nếu tôi đã làm đúng phần này.

+0

Không tệ.Sidesteps các câu hỏi trong đó là tốt hơn bằng cách trả lời "cả hai," nhưng không phải là xấu. – MJB

1

Cách tiếp cận thứ hai có thể cung cấp cho bạn các chuỗi như /usr/bin/myprog nếu bạn thực hiện theo cách đó; basename nên cung cấp tên của file thực thi (bạn có thể coi như tên chương trình của bạn) ... trừ khi nó được symlinked ... (trong trường hợp đó, bạn có tên của liên kết ... có thể được sử dụng để lựa chọn loại nào đó trong hành vi của chương trình).

Cách tiếp cận đầu tiên "sửa chữa" các tên chương trình với những gì các lập trình viên muốn, bất kể như thế nào người dùng đổi tên tập tin thực thi hoặc symlinked (hoặc thậm chí hardlinked)

+0

Có, tôi đã sử dụng các sản phẩm có vẻ như bạn có một số tệp thực thi, nhưng thực ra nó chỉ là một với nhiều liên kết đến nó. Điều này có vẻ điên rồ, nhưng nó là một cách hay để giữ nhiều công cụ đồng bộ qua nhiều lần sửa đổi. –

2

Tôi thường sử dụng argv[0], hoặc basename(argv[0]) nếu có thể. Từ POV của người dùng, tôi nghĩ rằng nếu họ đổi tên hoặc liên kết cứng một tệp thực thi (hoặc ai đó làm điều đó cho họ), thì họ muốn thư từ nó xuất hiện dưới tên họ đang sử dụng, không phải dưới một tên khác được biên dịch như, mà họ có thể hoặc có thể không biết. Tương tự, nếu bạn phát hiện trong tương lai bạn muốn biên dịch chương trình của bạn dưới các tên khác nhau với các tùy chọn khác nhau, để đưa ra các phiên bản khác nhau, bạn có muốn quấn #ifndef xung quanh #define và đảm bảo rằng nó được xác định thông qua dòng lệnh trình biên dịch : -DPROGRAM_NAME=myprog_demo, hoặc bạn chỉ muốn làm điều đó và nó hoạt động?

Trường hợp ngoại lệ có thể là nếu hướng dẫn sử dụng của bạn là một trích xuất từ ​​trang manpage hoặc tài liệu khác, thì có thể bạn muốn gắn cứng tên chương trình vào đó. Nhưng sau đó bạn có thể sẽ không sử dụng #define.

Triển khai không cần cung cấp argv[0], tuy nhiên, để thực hành di động tốt nhất cũng có thể xử lý trường hợp đó. Sau đó, một lần nữa, nếu hệ thống của bạn không cung cấp nó thì có lẽ người dùng cũng không thực sự thấy các tin nhắn trên bất kỳ loại thiết bị đầu cuối nào.

Bằng cách này:

#define PROGRAM_NAME "myprog" 
puts("this is " PROGRAM_NAME); 
+0

'tên cơ sở 'không phải là di động. Nó chỉ được yêu cầu bởi POSIX (trong libgen.h). Ngoài ra, hãy nhớ rằng nó có thể sửa đổi chuỗi bạn cho nó, và con trỏ trả về có thể là một offset từ con trỏ ban đầu, hoặc một chuỗi được cấp phát tĩnh (vì vậy đừng cố giải phóng những gì nó cung cấp cho bạn, và don 't cố gắng để giải phóng những gì bạn * đã cho * nó ngay lập tức sau). Tôi sẽ tránh nó trừ khi bạn chắc chắn 100% bạn hiểu được việc quản lý bộ nhớ có liên quan và bạn không quan tâm đến tính di động. – mk12

+1

Do đó, "nếu có thể". Nhưng bạn nói đúng rằng 'basename (argv [0])' chính nó là một biểu hiện hơi mơ hồ, nó giả định rằng bạn không có ý định sử dụng args nữa. –

1

Nó không chính xác trả lời câu hỏi của bạn cho thực hành tốt nhất chương trình, nhưng tôi nghĩ bạn cũng nên ghi nhớ những gì tốt nhất cho người dùng. Cá nhân tôi thích các chương trình tự giới thiệu mình bằng cách sử dụng argv[0], tức là lệnh mà tôi đã gọi và không phải tên ngẫu nhiên mà trình mã hóa được mã hóa cứng trong chương trình. Một vài ví dụ nơi một tên hardcoded là gây phiền nhiễu hoặc ít nhất là không hữu ích:

  • tôi đã tạo ra một liên kết đến một chương trình
  • Tôi đã đổi tên thành nhị phân cho một số lý do
  • Tôi có nhiều thực thi với cùng một tên nền trong các thư mục khác nhau trong số $PATH
  • Chương trình của tôi cung cấp cho tôi gợi ý về các cách khác để gọi nó, ví dụ: trong thông báo "sử dụng"

Tình huống duy nhất tôi muốn sử dụng tên chương trình được mã cứng là khi tôi đang sử dụng ứng dụng GUI. Tôi sẽ không muốn thấy "~/foo/bar.pl" làm tiêu đề cửa sổ.

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