Я пытаюсь реализовать стек, который читается из файла данных, без использования массивов. У меня есть все коды файлов, я просто модифицирую основной код тестера.
Это было дано как шаг ... но я не уверен, что он спрашивает, кроме удаления всех кодов массива:
"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
Я не получил вывод .. но вот ошибки:
Сообщения об ошибках
:( Боже, ты прав. Есть ли способ сохранить его в стеке без использования массивов..?
Или, говоря иначе, я думаю, что задание глупое. Также вы разместили фрагменты кода, поэтому мы не можем его запустить.
Я не думаю, что будет компилироваться, кстати, вы хотите проверить это fopen() в случае успеха, прежде чем пытаться fscanf() иначе он будет segfault в случае неудачи. int fscanf(FILE *in, char txt[50]); выглядит как декларация. Хочешь хочешь int id; char text[50]; fscanf(in, "%d%s", id, txt).
loop < in
смысла нет. Вы хотите проверить возвращаемое значение fscanf()
и выйти из цикла, если это необходимо. UserData D = FILE *in[loop];
смысла нет.
Задайте вопрос вместо того, чтобы просто передать задачу по исправлению вашего кода.
В этом вопросе отсутствует соответствующий Минимальный воспроизводимый пример. Предоставленные фрагменты не образуют полную программу, которую можно скомпилировать и отладить. Пожалуйста, сократите то, что показано, до соответствующих частей и включите отсутствующие определения функций. Некоторые комментарии к коду являются чрезмерными, и, вероятно, некоторые из операций со связанными списками являются излишними для вашего вопроса.
В исходном фрагменте кода, которым вы поделились, отсутствовали определения UserData и Stack, всех функций (initStack(), deleteStack(), push(), peek(), pop(), empty()), поэтому, вероятно, это лучшее, что мы можем сделать, чтобы помочь вам:
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);
}
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
Как только вы удалите эти фиктивные функции, все должно работать более или менее.
Я добавил недостающие коды.
В ваших пользовательских данных нет места для хранения текстовых значений. Что вы должны делать с ними (задача1, задача2А и т.д.). Мы очень предпочитаем, чтобы вы делились программой, а не фрагментами, которые нам приходится собирать самим.
Все готово?
Да, прости. Сейчас промежуточная неделя... спасибо, что помогли мне! Это был правильный ответ после изменения нескольких вещей.
argv
— это массив, значит, вы уже проиграли? Если вы хотите сохранить эту строку в памяти, это массив. Публикуйте ошибки в текстовом виде здесь вместо внешних ссылок.