Создайте стек, который считывает данные из текстового файла без использования массива. Должен ли я использовать fscanf?

Я пытаюсь реализовать стек, который читается из файла данных, без использования массивов. У меня есть все коды файлов, я просто модифицирую основной код тестера.

Это было дано как шаг ... но я не уверен, что он спрашивает, кроме удаления всех кодов массива:

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

Текстовый файл (StackData.txt) будет содержать следующие данные (и номер, и имя задачи):

1 task1
2 task2A
7 task3A
9 task2B
3 task4A
2 task4B
6 task3B

Это то, что у меня есть до сих пор:

// printf support
#include <stdio.h>
// stack callable routines
#include "Stack.h"
// UserData definition for making and getting stack data
#include "UserData.h"
// local functions

// PrintStackItem is a local function that we can call to print out a message (msg) and
// a UserData item.  So we can see how many things are allocated as we proceed,
// it will also print out the number of things allocated
static void PrintStackItem (char msg[], UserData D);

// PrintAllocations is a local function that will print out a message (msg) and the
// current global AllocationCount
static void PrintAllocations (char msg[]);

int main(int argc, const char * argv[]) {

    FILE* in = fopen("StackData.txt", "r");
    int fscanf(FILE *in, char txt[50]);
    if (in == NULL) {
       printf("File not found.");
       return 1;
 }    


    // Show the allocation count when we start
    PrintAllocations ("On startup");
    
    // create a stack ans see the effect of on the number of allocations
    Stack S = initStack();
    PrintAllocations ("After initStack called");

    // push the data on the stack, showing the data and allocations
    for (int loop = 0; loop < in; loop++)
    {
        UserData D = FILE *in[loop];
        push (S, D);
        PrintStackItem("push called, data is", D);
    }
    // pop and print the stack content
    // peek at the data before popping it so we can see what peek yields
    while (!empty(S))
    {
        PrintStackItem ("peek called, data is", peek(S));
        PrintStackItem ("pop  called, data is", pop(S));
    }
    // delete the stack and see the effect on the allocations
    PrintAllocations ("Before deleteStack called");
    S = deleteStack(S);
    PrintAllocations ("After deleteStack called");
    return 0;
}

/*
   PrintStackData prints out the received message and the data in UserData
*/
void PrintStackItem (char msg[], UserData D)
{
    printf ("%s %d, #allocations is %d\n", msg, D.num, AllocationCount);
}

/* 
   PrintAllocations prints out the received message and the current allocation count
   The allocation count is global AllocationCount
*/
void PrintAllocations (char msg[])
{
    printf ("%s, #allocations is %d\n", msg, AllocationCount);
    return;
}

Это код для стека:

#ifndef Stack_h
#define Stack_h

// The calls on a stack need to pass or return UserData
#include "UserData.h"
// Our stack will use a linked list, so we need to resolve LLInfoPtr
#include "LinkedList.h"
// The stack empty() call returns a boolean
#include <stdbool.h>

// This is the layout of a stack.  Notice that it contains
// a pointer to our underlying linked list and a simple boolean
// to indicate if our stack is empty (true) or not empty (false)

typedef struct {
    LLInfoPtr LL;
    bool empty;
} StackInfo, *Stack;

// initStack() allocates a stack and initializes it
Stack       initStack();
// empty() returns the boolean for the Stack S (true is empty, false 
is not empty)
bool        empty(Stack S);
// push() places the UserData on the top of the stack
void        push (Stack S, UserData D);
// pop() returns the UserData on the top of the stack and deletes
// the data from the stack
UserData    pop (Stack S);
// peep() returns the UserData on the top of the stack but will not
// delete it from the stack
UserData    peek (Stack S);
// deleteStack() deletes the frees the storage that was allocated by 
the call
// to initStack()
Stack       deleteStack(Stack S);

#endif /* Stack_h */

Это код для UserData:

#ifndef USERDATA_H_INCLUDED
#define USERDATA_H_INCLUDED

// The UserData struct defines what each node in the LL
// contains.

// User data in each node contains an integer
typedef struct {
    int num;
} UserData, *UserDataPtr;


#endif // USERDATA_H_INCLUDED

Это код для Linkedlist:

#ifndef LINKEDLIST_H_INCLUDED
#define LINKEDLIST_H_INCLUDED

// The LL functions use UserData
#include "UserData.h"

// The Linked List needs the definition of what a Node is. A Node has
// UserData and linkage information for both "next and "prev"
// for a doubly linked list).

typedef struct node
{
    UserData Data;
    struct node *next;
    struct node *prev;
} Node, *NodePtr;


// A LL Information block contains Head and Tail pointers to a LL
// For speed, it also contains a running count of the number of nodes
// currently in the LL started at Head and finishing at Tail.
// Head is used when adding or removing from the LL front,
// Tail is needed only when adding to the end of the LL
typedef struct {
    NodePtr Head;
    NodePtr Tail;
    int     NumNodesInList;
    } LLInfo, *LLInfoPtr;

// Verifying allocation / deallocation of dynamic memory is done through
// AllocationCount.  The variable is declared in LinkedList.c and is linked to
// through the extern
extern int AllocationCount;

// ShouldDelete is an enum that has two valid values called DELETE_NODE
// and RETAIN_NODE that are used in calling to get user data from the front
// of the LL
typedef int ShouldDelete;
enum ShouldDelete {DELETE_NODE=1, RETAIN_NODE=2};

// declarations for LL callable functions follow

// LL_Init allocates a LL Information structure, initializing Head, Tail and NumNodesInList
// and returning the address of the structure
LLInfoPtr       LL_Init         ();
// LL_Delete frees up the LL Information structure
LLInfoPtr       LL_Delete       (LLInfoPtr LLI_Ptr);
// LL_AddAtFront adds user data to the front of the underlying LL accessed through
// the LL Information struct
void            LL_AddAtFront   (LLInfoPtr LLI_Ptr, UserData     theData);
// LL_AddAtEnd adds user data to the Tail of the underlying LL accessed through the
// LL information struct
void            LL_AddAtEnd     (LLInfoPtr LLI_Ptr, UserData     theData);
// LL_GetFront returns the user data currently at the Head of the underlying LL and
//, optionally removes the user data from the LL
UserData        LL_GetFront     (LLInfoPtr LLI_Ptr, ShouldDelete Choice);
// LL_Length returns the number of nodes in the underlying LL
int             LL_Length       (LLInfoPtr LLI_Ptr);
// LL_GetAtIndex returns the node at the specified index starting at 0
UserData        LL_GetAtIndex   (LLInfoPtr, int FetchIndex);
// LL_SetAtIndex updates the node at the specified index starting at 0
void            LL_SetAtIndex   (LLInfoPtr LLI_Ptr, UserData D, int UpdateIndex);
// LL_Swap swaps the nodes in the underlying LL specified by indices starting at 0
void            LL_Swap         (LLInfoPtr LLI_Ptr, int Index1, int Index2);
#endif // LINKEDLIST_H_INCLUDED

Я не получил вывод .. но вот ошибки:

Сообщения об ошибках

argv — это массив, значит, вы уже проиграли? Если вы хотите сохранить эту строку в памяти, это массив. Публикуйте ошибки в текстовом виде здесь вместо внешних ссылок.
Allan Wind 18.02.2023 06:40

:( Боже, ты прав. Есть ли способ сохранить его в стеке без использования массивов..?

NotSoGoodAtThis 18.02.2023 06:43

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

Allan Wind 18.02.2023 06:45

Я не думаю, что будет компилироваться, кстати, вы хотите проверить это fopen() в случае успеха, прежде чем пытаться fscanf() иначе он будет segfault в случае неудачи. int fscanf(FILE *in, char txt[50]); выглядит как декларация. Хочешь хочешь int id; char text[50]; fscanf(in, "%d%s", id, txt).

Allan Wind 18.02.2023 06:49
loop < in смысла нет. Вы хотите проверить возвращаемое значение fscanf() и выйти из цикла, если это необходимо. UserData D = FILE *in[loop]; смысла нет.
Allan Wind 18.02.2023 06:50

Задайте вопрос вместо того, чтобы просто передать задачу по исправлению вашего кода.

Allan Wind 18.02.2023 06:51

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

Oka 18.02.2023 17:26
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
2
7
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В исходном фрагменте кода, которым вы поделились, отсутствовали определения UserData и Stack, всех функций (initStack(), deleteStack(), push(), peek(), pop(), empty()), поэтому, вероятно, это лучшее, что мы можем сделать, чтобы помочь вам:

  1. Удалите объявление "int fscanf(FILE *in, char txt[50]);". Вы уже получили правильный ответ из stdio.h.
  2. Петля:
    for (int loop = 0; loop < in; loop++)
    {
        UserData D = FILE *in[loop];
        push (S, D);
        PrintStackItem("push called, data is", D);
    }

Вероятно, должно быть что-то вроде:

    for(;;) {
        UserData D;
        int rv = fscanf(in, "%d%*s", &D.num); // %*s will discard the string as you you don't seem to have a place to store it in your UserData.
        if (rv != 1)
            break;
        push (S, D);
        PrintStackItem("push called, data is", D);
     }
  1. Удалите объявления PrintStackItem() и PrintAllocations() и вместо этого переместите main() нижнюю часть файла.

Вот минимум, необходимый для компиляции исходного кода:

#include <stdio.h>

int AllocationCount = 0;

typedef struct {
} Stack;

typedef struct {
    int num;
} UserData;

Stack initStack() {
    return (Stack) {};
}

Stack deleteStack(Stack S) {
    return (Stack) {};
}

void push(Stack S, UserData D) {
}

UserData peek(Stack S) {
    return (UserData) { 0 };
}

UserData pop(Stack S) {
    return (UserData) { 0 };
}

int empty(Stack S) {
    return 1;
}

void PrintStackItem (char msg[], UserData D) {
    printf ("%s %d, #allocations is %d\n", msg, D.num, AllocationCount);
}

void PrintAllocations (char msg[]) {
    printf ("%s, #allocations is %d\n", msg, AllocationCount);
    return;
}

int main(int argc, const char * argv[]) {
    FILE* in = fopen("StackData.txt", "r");
    if (!in) {
        printf("File not found.");
        return 1;
    }
    PrintAllocations ("On startup");
    Stack S = initStack();
    PrintAllocations ("After initStack called");
    for (;;) {
        UserData D;
        int rv = fscanf(in, "%d%*s", &D.num);
        if (rv != 2)
            break;
        push (S, D);
        PrintStackItem("push called, data is", D);
    }
    while (!empty(S)) {
        PrintStackItem ("peek called, data is", peek(S));
        PrintStackItem ("pop  called, data is", pop(S));
    }
    PrintAllocations ("Before deleteStack called");
    deleteStack(S);
    PrintAllocations ("After deleteStack called");
}

И вот результат:

On startup, #allocations is 0
After initStack called, #allocations is 0
push called, data is 1, #allocations is 0
push called, data is 2, #allocations is 0
push called, data is 7, #allocations is 0
push called, data is 9, #allocations is 0
push called, data is 3, #allocations is 0
push called, data is 2, #allocations is 0
push called, data is 6, #allocations is 0
Before deleteStack called, #allocations is 0
After deleteStack called, #allocations is 0

Как только вы удалите эти фиктивные функции, все должно работать более или менее.

Я добавил недостающие коды.

NotSoGoodAtThis 18.02.2023 07:28

В ваших пользовательских данных нет места для хранения текстовых значений. Что вы должны делать с ними (задача1, задача2А и т.д.). Мы очень предпочитаем, чтобы вы делились программой, а не фрагментами, которые нам приходится собирать самим.

Allan Wind 18.02.2023 07:32

Все готово?

Allan Wind 19.02.2023 06:01

Да, прости. Сейчас промежуточная неделя... спасибо, что помогли мне! Это был правильный ответ после изменения нескольких вещей.

NotSoGoodAtThis 21.02.2023 04:18

Другие вопросы по теме