[英]C-program on macOS cannot open its input file
我有一個使用 gcc 和 makefile 在 macOS High Sierra 上構建的 C 程序。 程序做的第一件事是讀取二進制輸入文件。 文件名可以從終端命令行與 shell 命令一起指定,或者程序將在未指定時要求它。
我的問題是,當輸入文件沒有與 shell 命令一起指定時,程序返回一個錯誤,說它無法打開文件。
以下是哪些有效,哪些無效:(程序和輸入文件在同一目錄中)
./program_name –i input.dat
=> 工作正常
./程序名稱
=> 錯誤打開文件
=> 錯誤打開文件
我在 linux 和 windows 上運行完全相同的源代碼,它可以正常工作,所以我認為它一定是我不明白的操作系統問題?
我可以補充一點,該程序不受信任,因為它不是來自應用商店。 CTRL-單擊圖標解決了這個問題。
--EDIT - 抱歉沒有添加可驗證代碼。
澄清一下:argc/argv 部分工作正常。 這是例程的最后一部分,它提示輸入出錯的文件名。 也許這確實是 Jabberwocky 建議的路徑。 我今晚會檢查一下,並會在這里跟進。
void GetFileName(nr_args, args, filename, json)
int nr_args;
char **args;
char *filename;
int* json;
{
int i = 1;
filename[0] = '\0';
/* the command 'interpreter' itself is stored in argv[0] */
while (i<nr_args) {
if (strcmp(args[i], "-e") == 0) {
/* we cannot set the json flag here, because */
/* flags have not been initialized yet */
*json = 1;
i++;
}
else {
if (strcmp(args[i], "-i") == 0) {
if (nr_args > i+1) {
/* inputfile was specified */
strncpy(filename, args[++i], MAX_ID_LENGTH);
i++;
}
}
else {
PrintError(41, NULL, args[i]);
i++;
}
}
}
if (filename[0] == '\0') {
printf("\n\nInputfile: ");
scanf("%19s", filename);
filename[MAX_ID_LENGTH] = '\0';
/* clear the input buffer, to prevent parsing an */
/* empty string as the first user command */
/* always do a getchar() independent of OS */
getchar();
printf("\n");
}
}
這是打開文件的部分(來自 main() )
/* Get filename */
GetFileName(argc, argv, inputfile, &json);
/* Open the datafile */
if ((datafile = fopen(inputfile, "rb")) == NULL) {
PrintError(40, NULL, inputfile);
ExitProgram();
return(OK);
}
EDIT2--根據 Andrew Henle 的回復,這是原型。
void GetFileName(int, char**, char*, int*);
該函數是從定義它的同一個文件中調用的。
我在 linux 和 windows 上運行完全相同的源代碼,它可以正常工作
那是沒有意義的。
這是一個舊的 K&R 風格的函數定義:
void GetFileName(nr_args, args, filename, json)
int nr_args;
char **args;
char *filename;
int* json;
{
...
如果調用代碼使用函數原型,則無法安全地調用該函數。 K&R 定義的函數期望它的所有參數都沒有完成默認參數提升。 該函數的原型意味着調用者不會執行這些提升。 不匹配將導致未定義的行為。
不要使用這么古老的函數。 您不能將它們與原型一起使用,並且沒有原型,您在函數調用中就沒有類型安全性。
使用正確的、符合 C 標准的函數定義:
void GetFileName( int nr_args, char **args, char *filename, int* json )
{
...
然后為所有對該函數的調用提供一個合適的原型。
我做了以下對我有用的例程。
所以,作為一個例子:
然后這個例程將返回:/usr/mac/my-name/programs/input.dat
感謝你的幫助。
#include <sys/param.h> /* realpath() */
#include <limits.h> /* PATH_MAX */
#include <mach-o/dyld.h> /* _NSGetExectablePath() */
char *GetFullPath(const char*);
#define MAX_FILENAME_LEN 100 /* or another value */
char *GetFullPath(const char *filename)
{
char path_buf[PATH_MAX + 1];
char resolved_name[PATH_MAX + 1];
char *real_path;
char *return_path;
uint32_t buf_size = sizeof(path_buf);
int index = 1;
/* this functions returns the full path of the current */
/* running application appended with var 'filename' at */
/* the end. In case of an error it returns NULL. */
if ((return_path = (char *) malloc(MAX_FILENAME_LEN)) == NULL) {
printf("GetFullPath(): error in Malloc()\n");
return(NULL);
}
/* get relative path */
if (_NSGetExecutablePath(path_buf, &buf_size) != 0) {
/* buffer too small */
printf("File Path too long.");
free(return_path);
return(NULL);
}
/* convert to absolute path */
if ( (real_path = realpath(path_buf, resolved_name)) == NULL) {
printf("Could not determine path.\n");
free(return_path);
return(NULL);
}
/* strip the application name from the end of the path */
index = strlen(real_path) - 1;
while (real_path[index] != '/') {
index--;
}
/* now check if there's enough room in return_path */
if (strlen(real_path) + strlen(filename) >= MAX_FILENAME_LEN) {
printf("File path too long.\n");
free(return_path);
return(NULL);
}
/* there's enough room, copy path and filename to return_path */
strncpy(return_path, real_path, index+1);
/* do not try to free() real_path */
return_path[index+1] = '\0';
strncat(return_path, filename, strlen(filename));
return(return_path); /* caller must free() return_path */
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.