Create a stack that reads from a data text file, without using an array. Should I use fscanf?

huangapple go评论69阅读模式
英文:

Create a stack that reads from a data text file, without using an array. Should I use fscanf?

问题

以下是您提供的代码的翻译部分:

// 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");
    if (in == NULL) {
        printf("File not found.");
        return 1;
    }

    // Show the allocation count when we start
    PrintAllocations("On startup");

    // create a stack and see the effect on the number of allocations
    Stack S = initStack();
    PrintAllocations("After initStack called");

    // push the data onto the stack, showing the data and allocations
    UserData D;
    while (fscanf(in, "%d", &D.num) == 1) {
        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)) {
        D = pop(S);
        PrintStackItem("peek called, data is", D);
        PrintStackItem("pop called, data is", D);
    }
    // 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;
}

请注意,我已经修复了一些代码中的错误,特别是在从文件中读取数据和将数据推送到堆栈中的部分。如果您还需要关于特定错误的更多帮助,请提出具体问题。

英文:

I'm trying to implement a stack that is read from a data file, without using arrays. I have all the file codes, I'm just modifying the main tester code.

This was given as a step.. but I'm not sure what he's asking, besides removing all of the array codes:

"4. Edit the tester code to read in the data from the file you create. You must remove all
code dealing with an array and update the code to read in the data and place it directly
in the stack using only stack functions. You cannot hardcode the number of lines you
read in from the file nor can you change any code in the stack. How you do this is the
challenge. "

The text file (StackData.txt) will have the following data (both the number and taskname):

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

This is what I have so far:

// printf support
#include &lt;stdio.h&gt;
// stack callable routines
#include &quot;Stack.h&quot;
// UserData definition for making and getting stack data
#include &quot;UserData.h&quot;
// 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(&quot;StackData.txt&quot;, &quot;r&quot;);
int fscanf(FILE *in, char txt[50]);
if (in == NULL) {
printf(&quot;File not found.&quot;);
return 1;
}    
// Show the allocation count when we start
PrintAllocations (&quot;On startup&quot;);
// create a stack ans see the effect of on the number of allocations
Stack S = initStack();
PrintAllocations (&quot;After initStack called&quot;);
// push the data on the stack, showing the data and allocations
for (int loop = 0; loop &lt; in; loop++)
{
UserData D = FILE *in[loop];
push (S, D);
PrintStackItem(&quot;push called, data is&quot;, 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 (&quot;peek called, data is&quot;, peek(S));
PrintStackItem (&quot;pop  called, data is&quot;, pop(S));
}
// delete the stack and see the effect on the allocations
PrintAllocations (&quot;Before deleteStack called&quot;);
S = deleteStack(S);
PrintAllocations (&quot;After deleteStack called&quot;);
return 0;
}
/*
PrintStackData prints out the received message and the data in UserData
*/
void PrintStackItem (char msg[], UserData D)
{
printf (&quot;%s %d, #allocations is %d\n&quot;, 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 (&quot;%s, #allocations is %d\n&quot;, msg, AllocationCount);
return;
}

This is the code for Stack:

#ifndef Stack_h
#define Stack_h
// The calls on a stack need to pass or return UserData
#include &quot;UserData.h&quot;
// Our stack will use a linked list, so we need to resolve LLInfoPtr
#include &quot;LinkedList.h&quot;
// The stack empty() call returns a boolean
#include &lt;stdbool.h&gt;
// 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 */

This is the code for 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

This is the code for Linkedlist:

#ifndef LINKEDLIST_H_INCLUDED
#define LINKEDLIST_H_INCLUDED
// The LL functions use UserData
#include &quot;UserData.h&quot;
// The Linked List needs the definition of what a Node is. A Node has
// UserData and linkage information for both &quot;next and &quot;prev&quot;
// 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

I didn't get an output..but here are the errors:

Error messages

答案1

得分: 0

你分享的原始代码片段缺少 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 会丢弃字符串,因为你似乎没有地方来存储它在你的 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

一旦你删除那些虚构的函数,应该可以更或多少地正常工作。

英文:

The original snippet of code that you shared was missing definitions of UserData and Stack, all the functions (initStack(), deleteStack(), push(), peek(), pop(), empty()) so this is probably the best we can do to help you:

  1. Delete the declaration "int fscanf(FILE *in, char txt[50]);". You get that correct one from stdio.h already.
  2. The loop:
    for (int loop = 0; loop &lt; in; loop++)
{
UserData D = FILE *in[loop];
push (S, D);
PrintStackItem(&quot;push called, data is&quot;, D);
}

should probably be something like:

    for(;;) {
UserData D;
int rv = fscanf(in, &quot;%d%*s&quot;, &amp;D.num); // %*s will discard the string as you you don&#39;t seem to have a place to store it in your UserData.
if(rv != 1)
break;
push (S, D);
PrintStackItem(&quot;push called, data is&quot;, D);
}
  1. Delete the PrintStackItem() and PrintAllocations() declarations and instead moved main() the bottom of your file.

Here's the minimal required for your original code to compile:

#include &lt;stdio.h&gt;
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 (&quot;%s %d, #allocations is %d\n&quot;, msg, D.num, AllocationCount);
}
void PrintAllocations (char msg[]) {
printf (&quot;%s, #allocations is %d\n&quot;, msg, AllocationCount);
return;
}
int main(int argc, const char * argv[]) {
FILE* in = fopen(&quot;StackData.txt&quot;, &quot;r&quot;);
if (!in) {
printf(&quot;File not found.&quot;);
return 1;
}
PrintAllocations (&quot;On startup&quot;);
Stack S = initStack();
PrintAllocations (&quot;After initStack called&quot;);
for (;;) {
UserData D;
int rv = fscanf(in, &quot;%d%*s&quot;, &amp;D.num);
if(rv != 2)
break;
push (S, D);
PrintStackItem(&quot;push called, data is&quot;, D);
}
while (!empty(S)) {
PrintStackItem (&quot;peek called, data is&quot;, peek(S));
PrintStackItem (&quot;pop  called, data is&quot;, pop(S));
}
PrintAllocations (&quot;Before deleteStack called&quot;);
deleteStack(S);
PrintAllocations (&quot;After deleteStack called&quot;);
}

and here is resulting output:

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

Once you remove those dummy functions it should work more or less.

huangapple
  • 本文由 发表于 2023年2月18日 13:15:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75491356.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定