C-программа на macOS не может открыть свой входной файл - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть C-программа, построенная на MacOS High Sierra с использованием gcc и make-файла.Первым делом программа читает двоичный файл ввода.Имя файла может быть либо указано в командной строке терминала вместе с командой оболочки, либо программа запросит его, если оно не указано.

Моя проблема заключается в том, что когда входной файл не указан вместе с командой оболочки, программа возвращает ошибку, говоря, что не может открыть файл.

Вот что работает, а что нет: (программа и входной файл находятся в одном каталоге)

  1. открытьтерминал
  2. из командной строки типа:

    . / имя_программы –i input.dat

=> отлично работает

  1. открыть терминал
  2. из командной строки типа:

    . / Имя_программы

  3. подсказки программы: Inputfile:
  4. Я набираю: input.dat

=> ошибка открытия файла

  1. открыть Finder и перейти в каталог с программой и входным файлом
  2. дважды щелкнуть по значку имя_программы
  3. программа запускается в терминале и запрашивает: Inputfile:
  4. Я набираю: input.dat

=> Ошибка открытия файла

Я запускаю тот же самый исходный код на Linux и Windows, где он работает нормально, поэтому я думаю, что это должно бытьОС, чего я не понимаю?

Могу добавить, что программе не доверяли, потому что она не пришла из магазина приложений.Ctrl-клик на иконке решил, что.

- РЕДАКТИРОВАТЬ - извините, что не добавили проверяемый код.

Чтобы уточнить: часть argc / argv работает нормально.это последний раздел процедуры, где он запрашивает имя файла, где он идет не так.Может быть, это действительно путь, как предложил Джаббервоки.Я проверю это сегодня вечером и расскажу здесь.

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-- Согласно ответу Эндрю Хенле, это прототип.

void    GetFileName(int, char**, char*, int*);

Функция вызывается из того же файла, который определен в.

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Я сделал следующую процедуру, которая работает для меня.

Итак, в качестве примера:

  • , если программа находится в папке / usr / mac / my-name / Programs/
  • и введенное имя файла ввода - input.dat

. Затем эта процедура вернет: /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 */
}
0 голосов
/ 13 февраля 2019

Я запускаю тот же самый исходный код в 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 )
{
...

А затем предоставить надлежащий прототип для всех вызовов функции.

...