Как я могу использовать Fgets в VS - PullRequest
0 голосов
/ 03 декабря 2018

Я пытался запустить этот код на VS2017.Код компилируется и выполняется, но не так, как я хочу.Итак, я пытаюсь использовать отладчик, и он говорит:

Ошибка отладки!Программа:

Файл: minkernel \ crts \ ucrt \ src \ appcrt \ stdio \ fgets.cpp

Строка: 33

Выражение: stream.valid ()

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

Любая помощь будет принята с благодарностью!

(мой соответствующий код):

int main(int argc, char *argv[]) {
    int i, count_commands, PC_A, lastLine;
    int *PC = &PC_A;
    FILE *memin;
    FILE *memout;
    FILE *regout;
    FILE *trace;
    FILE *count;
    assert(argc == 6);
    *PC = 0;
    count_commands = 0;
    //allocationg memory for registers content
    char **regs = (char **)(malloc(sizeof(char *) * 16));
    for (i = 0; i < 16; i++) {
        regs[i] = (char *)(malloc(sizeof(char) * 9));
        for (int j = 0; j < 8; j++) {
            regs[i][j] = '0';
        }
        regs[i][8] = '\0';
    }
    //allocationg memory for the memory image we have
    char **memory = (char **)(malloc(sizeof(char *) * 4096));
    for (i = 0; i < 4096; i++) {
        memory[i] = (char *)(malloc(sizeof(char) * 9));
        memory[i][0] = '\0';
    }

    //load memin image into memory
    char *line = (char *)malloc(sizeof(char) * 8);
    memin = fopen(argv[1], "r");
    if (memin != NULL) {
        perror(strerror(errno));
    }
    int j = 0;
    while ((line = fgets(line, 10, (FILE *)memin)) != NULL) {
        strcpy(memory[j], line);
        memory[j][8] = '\0';
        j++;
    }

1 Ответ

0 голосов
/ 04 декабря 2018

После открытия файла в коде OP есть такая проверка:

if (memin != NULL) {
    perror(strerror(errno));
}

Итак, если открытие прошло успешно , выводится строка ошибки.В моей реализации он сообщает:

Success: Success

Никаких действий не предпринимается, если не удается открыть файл.

Когда дело доходит до фактического чтения всехстрок в файле, есть некоторые другие проблемы.Буфер (массив char) с именем line размером 8 динамически выделяется и передается в fgets:

while ((line = fgets(line, 10, (FILE *)memin)) != NULL) {
//                         ^^

Обратите внимание, что 10 также передается как размер буфера, что неверно, поскольку позволяет fgets записывать данные за пределы выделенного массива.

Кроме того, учитывая, что компилятором OP является MSVC 2017, я предполагаю, что этот кодработает в Windows, поэтому есть вероятность, что в файле строки заканчиваются последовательностью "\r\n", а не одиночной '\n'.Даже если OP уверен, что каждая строка представляет собой строку из 8 символов, fgets требуется буфер по крайней мере размером 8 + 3 (8 + '\ r' + '\ n' + '\ 0'), чтобы прочитать их безопасно.

Рассмотрим, как эти предложения реализованы в этом фрагменте:

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

#define MEM_SIZE  1024u
#define LINE_SIZE  128u
#define STR_SIZE     8u

int main(int argc, char *argv[])
{
    // Try to open the input file
    if (argc < 2) {
        fprintf(stderr, "Missing file name in command line.\n");
        return EXIT_FAILURE;
    }
    FILE *memin = fopen(argv[1], "r");
    if (memin == NULL) {
        fprintf(stderr, "Unable to open file [%s].\n", argv[1]);
        return EXIT_FAILURE;
    }
    // I'd use plain arrays to store the lines
    char memory[MEM_SIZE][STR_SIZE + 1] = {{'\0'}};
    char line[LINE_SIZE] = {'\0'};
    size_t count = 0;
    while ( count < MEM_SIZE && fgets(line, LINE_SIZE, memin) ) {
        size_t length = strcspn(line, "\r\n");
        if (length > STR_SIZE) {
            fprintf(stdout, "Warning, line too long: %zu.\n", count);
            length = STR_SIZE;
        }
        memcpy(memory[count], line, length);
        memory[count][STR_SIZE] = '\0';
        ++count;
    }

    for ( size_t i = 0; i < count; ++i ) {
        printf("[%s]\n", memory[i]);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...