Fgets возвращает пустой экран - PullRequest
0 голосов
/ 28 января 2019

Я новичок в C, это мой первый проект, и я учил сам.В моей программе одна из моих функций должна прочитать строку из файла и сохранить ее в массиве символов.Когда я отслеживаю программу с помощью gdb, массив (строка []) - это просто нули.Это приводит к тому, что моя программа возвращает ошибку «Ошибка: в строке файла ресурсов отсутствует разделитель«: »\ n». Вот мой код:

//return the line number (0 based) that the cmd is on, -1 if absent
int locateCmd(char cmd[]) {
        int lineIndex = -1;     //-1, because lineIndex is incramented before the posible return
        char cmdTemp[10] = "\0";

        //create a compareable cmd with correct cmd that has its remaining values zeroed out
        char cmdCmp[10] = "\0";
        memset(cmdCmp, 0, sizeof(cmdCmp));
        for (int i = 0; i < strlen(cmd); i++) {
                cmdCmp[i] = cmd[i];
        }

        FILE *file = fopen(ASSET_FILE, "r");

        //loop until target line is reached
        while (strcmp(cmdTemp, cmdCmp) != 0)  {
                //check if last line is read
                if (lineIndex == lineCounter(file)-1) {
                        return -1;
                }

                memset(cmdTemp, 0, sizeof(cmdTemp));
                char line[61];
                fgets(line, 61, file);
                //set cmdTemp to the command on current line
                lineIndex++;
                for (int i = 0; line[i] != ':'; i++) {
                        cmdTemp[i] = line[i];

                        //return error if line doesn't contain a ':'
                        if (line[i] = '\n') {
                        printf("Error: a line in the asset file lacks a ':' separator\n");
                        exit(1);
                        }
                }
        }

        return lineIndex;
}

В некотором контексте этой функции передается команда,и его задача - прочитать документ, который выглядит следующим образом:

command:aBunchOfInfoOnTheComand
anotherCommand:aBunchOfInfoOnTheComand

и выбрать строку, в которой хранится переданная команда (cmd []).

Проблема связана сfgets в строке 24. Я разделил соответствующую часть этого кода на небольшую тестовую программу, и она отлично работает.Тестовая программа, которая работает:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char *argv[]) {
    FILE *file = fopen("tutorInfo.txt", "r");
    char line[61];
    fgets(line, 61, file);
    printf("%s\n", line);
}

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

1 Ответ

0 голосов
/ 29 января 2019

Поскольку OP не предоставил Минимальный, Полный и Проверяемый пример , я должен основывать свой ответ на функциональном описании, представленном в вопросе.

Я уже рассмотрел некоторую ошибкуи угловые дела, но я уверен, что я пропустил некоторые.Подход также неэффективен, поскольку файл читается снова и снова, вместо того, чтобы анализировать его один раз и возвращать каталог hash / map / для легкого поиска.В реальном коде я бы использовал что-то вроде GLib вместо того, чтобы тратить свое время, пытаясь заново изобрести колесо (а) ...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LINE_BUFFER_LENGTH 200

unsigned int locateCmd(FILE *fh, const char *key, const char **cmd_line) {
  unsigned int found = 0;
  size_t key_length = strlen(key);
  *cmd_line = NULL;

  /* make sure to start read from start of file */
  rewind(fh);

  unsigned int line_no = 0;
  static char buffer[LINE_BUFFER_LENGTH];
  while (!feof(fh) && (found == 0)) {
    // NOTE: EOF condition will be checked on the next iteration
    fgets(buffer, sizeof(buffer), fh);
    size_t length = strlen(buffer);
    line_no++;

    if (buffer[length - 1] != '\n') {
      printf("line %u is too long, aborting!\n", line_no);
      return(0);
    }

    if ((strncmp(key, buffer, key_length) == 0) &&
        (buffer[key_length] == ':')) {
      found              = line_no;
      buffer[length - 1] = '\0'; // strip line ending
      *cmd_line          = &buffer[key_length + 1];
    }
  }

  return(found);
}

int main(int argc, char *argv[]) {
  FILE *fh = fopen("dummy.txt", "r");
  if (!fh) {
    perror("file open");
    return(1);
  }

  int ret = 0;
  while (--argc > 0) {
    const char *cmd;
    const char *key  = *++argv;
    unsigned line_no = locateCmd(fh, key, &cmd);
    if (line_no != 0) {
      printf("key '%s' found on line %u: %s\n", key, line_no, cmd);
      ret = 0;
    } else {
      printf("key '%s' not found!\n", key);
    };
  }

  if (fclose(fh) != 0) {
    perror("file close");
    return(1);
  }

  return(ret);
}

Тестовый ввод dummy.txt:

command:aBunchOfInfoOnTheComand
anotherCommand:aBunchOfInfoOnTheComand
brokenline

foo:bar
toolong:sadflkjaLKFJASDJFLKASJDFLKSAJ DLFKJ SLDKJFLKASDFASDFKJASKLDJFLKASJDFLKJASDLKFJASLKDFJLKASDJFLKASJDLFKJASDKLFJKLASDJFLKSAJDFLKJASDLKFJKLASDJFLKASJDFKLJASDLKFJLKASDJFLKASJDFLKJSADLKFJASLKDJFLKC

Некоторые тестовые прогоны:

$ gcc -Wall -o dummy dummy.c
$ ./dummy command foo bar
key 'command' found on line 1: aBunchOfInfoOnTheComand
key 'foo' found on line 5: bar
line 6 is too long, aborting!
key 'bar' not found!
...