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

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

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

问题

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

  1. // printf support
  2. #include <stdio.h>
  3. // stack callable routines
  4. #include "Stack.h"
  5. // UserData definition for making and getting stack data
  6. #include "UserData.h"
  7. // local functions
  8. // PrintStackItem is a local function that we can call to print out a message (msg) and
  9. // a UserData item. So we can see how many things are allocated as we proceed,
  10. // it will also print out the number of things allocated
  11. static void PrintStackItem(char msg[], UserData D);
  12. // PrintAllocations is a local function that will print out a message (msg) and the
  13. // current global AllocationCount
  14. static void PrintAllocations(char msg[]);
  15. int main(int argc, const char* argv[]) {
  16. FILE* in = fopen("StackData.txt", "r");
  17. if (in == NULL) {
  18. printf("File not found.");
  19. return 1;
  20. }
  21. // Show the allocation count when we start
  22. PrintAllocations("On startup");
  23. // create a stack and see the effect on the number of allocations
  24. Stack S = initStack();
  25. PrintAllocations("After initStack called");
  26. // push the data onto the stack, showing the data and allocations
  27. UserData D;
  28. while (fscanf(in, "%d", &D.num) == 1) {
  29. push(S, D);
  30. PrintStackItem("push called, data is", D);
  31. }
  32. // pop and print the stack content
  33. // peek at the data before popping it so we can see what peek yields
  34. while (!empty(S)) {
  35. D = pop(S);
  36. PrintStackItem("peek called, data is", D);
  37. PrintStackItem("pop called, data is", D);
  38. }
  39. // delete the stack and see the effect on the allocations
  40. PrintAllocations("Before deleteStack called");
  41. S = deleteStack(S);
  42. PrintAllocations("After deleteStack called");
  43. return 0;
  44. }
  45. /*
  46. PrintStackData prints out the received message and the data in UserData
  47. */
  48. void PrintStackItem(char msg[], UserData D) {
  49. printf("%s %d, #allocations is %d\n", msg, D.num, AllocationCount);
  50. }
  51. /*
  52. PrintAllocations prints out the received message and the current allocation count
  53. The allocation count is global AllocationCount
  54. */
  55. void PrintAllocations(char msg[]) {
  56. printf("%s, #allocations is %d\n", msg, AllocationCount);
  57. return;
  58. }

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

英文:

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. 1 task1
  2. 2 task2A
  3. 7 task3A
  4. 9 task2B
  5. 3 task4A
  6. 2 task4B
  7. 6 task3B

This is what I have so far:

  1. // printf support
  2. #include &lt;stdio.h&gt;
  3. // stack callable routines
  4. #include &quot;Stack.h&quot;
  5. // UserData definition for making and getting stack data
  6. #include &quot;UserData.h&quot;
  7. // local functions
  8. // PrintStackItem is a local function that we can call to print out a message (msg) and
  9. // a UserData item. So we can see how many things are allocated as we proceed,
  10. // it will also print out the number of things allocated
  11. static void PrintStackItem (char msg[], UserData D);
  12. // PrintAllocations is a local function that will print out a message (msg) and the
  13. // current global AllocationCount
  14. static void PrintAllocations (char msg[]);
  15. int main(int argc, const char * argv[]) {
  16. FILE* in = fopen(&quot;StackData.txt&quot;, &quot;r&quot;);
  17. int fscanf(FILE *in, char txt[50]);
  18. if (in == NULL) {
  19. printf(&quot;File not found.&quot;);
  20. return 1;
  21. }
  22. // Show the allocation count when we start
  23. PrintAllocations (&quot;On startup&quot;);
  24. // create a stack ans see the effect of on the number of allocations
  25. Stack S = initStack();
  26. PrintAllocations (&quot;After initStack called&quot;);
  27. // push the data on the stack, showing the data and allocations
  28. for (int loop = 0; loop &lt; in; loop++)
  29. {
  30. UserData D = FILE *in[loop];
  31. push (S, D);
  32. PrintStackItem(&quot;push called, data is&quot;, D);
  33. }
  34. // pop and print the stack content
  35. // peek at the data before popping it so we can see what peek yields
  36. while (!empty(S))
  37. {
  38. PrintStackItem (&quot;peek called, data is&quot;, peek(S));
  39. PrintStackItem (&quot;pop called, data is&quot;, pop(S));
  40. }
  41. // delete the stack and see the effect on the allocations
  42. PrintAllocations (&quot;Before deleteStack called&quot;);
  43. S = deleteStack(S);
  44. PrintAllocations (&quot;After deleteStack called&quot;);
  45. return 0;
  46. }
  47. /*
  48. PrintStackData prints out the received message and the data in UserData
  49. */
  50. void PrintStackItem (char msg[], UserData D)
  51. {
  52. printf (&quot;%s %d, #allocations is %d\n&quot;, msg, D.num, AllocationCount);
  53. }
  54. /*
  55. PrintAllocations prints out the received message and the current allocation count
  56. The allocation count is global AllocationCount
  57. */
  58. void PrintAllocations (char msg[])
  59. {
  60. printf (&quot;%s, #allocations is %d\n&quot;, msg, AllocationCount);
  61. return;
  62. }

This is the code for Stack:

  1. #ifndef Stack_h
  2. #define Stack_h
  3. // The calls on a stack need to pass or return UserData
  4. #include &quot;UserData.h&quot;
  5. // Our stack will use a linked list, so we need to resolve LLInfoPtr
  6. #include &quot;LinkedList.h&quot;
  7. // The stack empty() call returns a boolean
  8. #include &lt;stdbool.h&gt;
  9. // This is the layout of a stack. Notice that it contains
  10. // a pointer to our underlying linked list and a simple boolean
  11. // to indicate if our stack is empty (true) or not empty (false)
  12. typedef struct {
  13. LLInfoPtr LL;
  14. bool empty;
  15. } StackInfo, *Stack;
  16. // initStack() allocates a stack and initializes it
  17. Stack initStack();
  18. // empty() returns the boolean for the Stack S (true is empty, false
  19. is not empty)
  20. bool empty(Stack S);
  21. // push() places the UserData on the top of the stack
  22. void push (Stack S, UserData D);
  23. // pop() returns the UserData on the top of the stack and deletes
  24. // the data from the stack
  25. UserData pop (Stack S);
  26. // peep() returns the UserData on the top of the stack but will not
  27. // delete it from the stack
  28. UserData peek (Stack S);
  29. // deleteStack() deletes the frees the storage that was allocated by
  30. the call
  31. // to initStack()
  32. Stack deleteStack(Stack S);
  33. #endif /* Stack_h */

This is the code for UserData:

  1. #ifndef USERDATA_H_INCLUDED
  2. #define USERDATA_H_INCLUDED
  3. // The UserData struct defines what each node in the LL
  4. // contains.
  5. // User data in each node contains an integer
  6. typedef struct {
  7. int num;
  8. } UserData, *UserDataPtr;
  9. #endif // USERDATA_H_INCLUDED

This is the code for Linkedlist:

  1. #ifndef LINKEDLIST_H_INCLUDED
  2. #define LINKEDLIST_H_INCLUDED
  3. // The LL functions use UserData
  4. #include &quot;UserData.h&quot;
  5. // The Linked List needs the definition of what a Node is. A Node has
  6. // UserData and linkage information for both &quot;next and &quot;prev&quot;
  7. // for a doubly linked list).
  8. typedef struct node
  9. {
  10. UserData Data;
  11. struct node *next;
  12. struct node *prev;
  13. } Node, *NodePtr;
  14. // A LL Information block contains Head and Tail pointers to a LL
  15. // For speed, it also contains a running count of the number of nodes
  16. // currently in the LL started at Head and finishing at Tail.
  17. // Head is used when adding or removing from the LL front,
  18. // Tail is needed only when adding to the end of the LL
  19. typedef struct {
  20. NodePtr Head;
  21. NodePtr Tail;
  22. int NumNodesInList;
  23. } LLInfo, *LLInfoPtr;
  24. // Verifying allocation / deallocation of dynamic memory is done through
  25. // AllocationCount. The variable is declared in LinkedList.c and is linked to
  26. // through the extern
  27. extern int AllocationCount;
  28. // ShouldDelete is an enum that has two valid values called DELETE_NODE
  29. // and RETAIN_NODE that are used in calling to get user data from the front
  30. // of the LL
  31. typedef int ShouldDelete;
  32. enum ShouldDelete {DELETE_NODE=1, RETAIN_NODE=2};
  33. // declarations for LL callable functions follow
  34. // LL_Init allocates a LL Information structure, initializing Head, Tail and NumNodesInList
  35. // and returning the address of the structure
  36. LLInfoPtr LL_Init ();
  37. // LL_Delete frees up the LL Information structure
  38. LLInfoPtr LL_Delete (LLInfoPtr LLI_Ptr);
  39. // LL_AddAtFront adds user data to the front of the underlying LL accessed through
  40. // the LL Information struct
  41. void LL_AddAtFront (LLInfoPtr LLI_Ptr, UserData theData);
  42. // LL_AddAtEnd adds user data to the Tail of the underlying LL accessed through the
  43. // LL information struct
  44. void LL_AddAtEnd (LLInfoPtr LLI_Ptr, UserData theData);
  45. // LL_GetFront returns the user data currently at the Head of the underlying LL and
  46. //, optionally removes the user data from the LL
  47. UserData LL_GetFront (LLInfoPtr LLI_Ptr, ShouldDelete Choice);
  48. // LL_Length returns the number of nodes in the underlying LL
  49. int LL_Length (LLInfoPtr LLI_Ptr);
  50. // LL_GetAtIndex returns the node at the specified index starting at 0
  51. UserData LL_GetAtIndex (LLInfoPtr, int FetchIndex);
  52. // LL_SetAtIndex updates the node at the specified index starting at 0
  53. void LL_SetAtIndex (LLInfoPtr LLI_Ptr, UserData D, int UpdateIndex);
  54. // LL_Swap swaps the nodes in the underlying LL specified by indices starting at 0
  55. void LL_Swap (LLInfoPtr LLI_Ptr, int Index1, int Index2);
  56. #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. 循环部分:

  1. for (int loop = 0; loop < in; loop++)
  2. {
  3. UserData D = FILE *in[loop];
  4. push (S, D);
  5. PrintStackItem("push called, data is", D);
  6. }

可能应该像这样:

  1. for(;;) {
  2. UserData D;
  3. int rv = fscanf(in, "%d%*s", &D.num); // %*s 会丢弃字符串,因为你似乎没有地方来存储它在你的 UserData 结构中。
  4. if(rv != 1)
  5. break;
  6. push (S, D);
  7. PrintStackItem("push called, data is", D);
  8. }
  1. 删除 PrintStackItem()PrintAllocations() 的声明,并将 main() 移动到文件底部。

这是使原始代码能够编译所需的最小代码:

  1. #include <stdio.h>
  2. int AllocationCount = 0;
  3. typedef struct {
  4. } Stack;
  5. typedef struct {
  6. int num;
  7. } UserData;
  8. Stack initStack() {
  9. return (Stack) {};
  10. }
  11. Stack deleteStack(Stack S) {
  12. return (Stack) {};
  13. }
  14. void push(Stack S, UserData D) {
  15. }
  16. UserData peek(Stack S) {
  17. return (UserData) { 0 };
  18. }
  19. UserData pop(Stack S) {
  20. return (UserData) { 0 };
  21. }
  22. int empty(Stack S) {
  23. return 1;
  24. }
  25. void PrintStackItem (char msg[], UserData D) {
  26. printf ("%s %d, #allocations is %d\n", msg, D.num, AllocationCount);
  27. }
  28. void PrintAllocations (char msg[]) {
  29. printf ("%s, #allocations is %d\n", msg, AllocationCount);
  30. return;
  31. }
  32. int main(int argc, const char * argv[]) {
  33. FILE* in = fopen("StackData.txt", "r");
  34. if (!in) {
  35. printf("File not found.");
  36. return 1;
  37. }
  38. PrintAllocations ("On startup");
  39. Stack S = initStack();
  40. PrintAllocations ("After initStack called");
  41. for (;;) {
  42. UserData D;
  43. int rv = fscanf(in, "%d%*s", &D.num);
  44. if(rv != 2)
  45. break;
  46. push (S, D);
  47. PrintStackItem("push called, data is", D);
  48. }
  49. while (!empty(S)) {
  50. PrintStackItem ("peek called, data is", peek(S));
  51. PrintStackItem ("pop called, data is", pop(S));
  52. }
  53. PrintAllocations ("Before deleteStack called");
  54. deleteStack(S);
  55. PrintAllocations ("After deleteStack called");
  56. }

这是输出的结果:

  1. On startup, #allocations is 0
  2. After initStack called, #allocations is 0
  3. push called, data is 1, #allocations is 0
  4. push called, data is 2, #allocations is 0
  5. push called, data is 7, #allocations is 0
  6. push called, data is 9, #allocations is 0
  7. push called, data is 3, #allocations is 0
  8. push called, data is 2, #allocations is 0
  9. push called, data is 6, #allocations is 0
  10. Before deleteStack called, #allocations is 0
  11. 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:
  1. for (int loop = 0; loop &lt; in; loop++)
  2. {
  3. UserData D = FILE *in[loop];
  4. push (S, D);
  5. PrintStackItem(&quot;push called, data is&quot;, D);
  6. }

should probably be something like:

  1. for(;;) {
  2. UserData D;
  3. 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.
  4. if(rv != 1)
  5. break;
  6. push (S, D);
  7. PrintStackItem(&quot;push called, data is&quot;, D);
  8. }
  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:

  1. #include &lt;stdio.h&gt;
  2. int AllocationCount = 0;
  3. typedef struct {
  4. } Stack;
  5. typedef struct {
  6. int num;
  7. } UserData;
  8. Stack initStack() {
  9. return (Stack) {};
  10. }
  11. Stack deleteStack(Stack S) {
  12. return (Stack) {};
  13. }
  14. void push(Stack S, UserData D) {
  15. }
  16. UserData peek(Stack S) {
  17. return (UserData) { 0 };
  18. }
  19. UserData pop(Stack S) {
  20. return (UserData) { 0 };
  21. }
  22. int empty(Stack S) {
  23. return 1;
  24. }
  25. void PrintStackItem (char msg[], UserData D) {
  26. printf (&quot;%s %d, #allocations is %d\n&quot;, msg, D.num, AllocationCount);
  27. }
  28. void PrintAllocations (char msg[]) {
  29. printf (&quot;%s, #allocations is %d\n&quot;, msg, AllocationCount);
  30. return;
  31. }
  32. int main(int argc, const char * argv[]) {
  33. FILE* in = fopen(&quot;StackData.txt&quot;, &quot;r&quot;);
  34. if (!in) {
  35. printf(&quot;File not found.&quot;);
  36. return 1;
  37. }
  38. PrintAllocations (&quot;On startup&quot;);
  39. Stack S = initStack();
  40. PrintAllocations (&quot;After initStack called&quot;);
  41. for (;;) {
  42. UserData D;
  43. int rv = fscanf(in, &quot;%d%*s&quot;, &amp;D.num);
  44. if(rv != 2)
  45. break;
  46. push (S, D);
  47. PrintStackItem(&quot;push called, data is&quot;, D);
  48. }
  49. while (!empty(S)) {
  50. PrintStackItem (&quot;peek called, data is&quot;, peek(S));
  51. PrintStackItem (&quot;pop called, data is&quot;, pop(S));
  52. }
  53. PrintAllocations (&quot;Before deleteStack called&quot;);
  54. deleteStack(S);
  55. PrintAllocations (&quot;After deleteStack called&quot;);
  56. }

and here is resulting output:

  1. On startup, #allocations is 0
  2. After initStack called, #allocations is 0
  3. push called, data is 1, #allocations is 0
  4. push called, data is 2, #allocations is 0
  5. push called, data is 7, #allocations is 0
  6. push called, data is 9, #allocations is 0
  7. push called, data is 3, #allocations is 0
  8. push called, data is 2, #allocations is 0
  9. push called, data is 6, #allocations is 0
  10. Before deleteStack called, #allocations is 0
  11. 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:

确定