My structure file only displays the last line of my fstream files. I also question abo

Pages: 12
Hey all, i want to finish up my code without changing much since my teacher requires us to keep it in the same format with mostly the same functions. But for some reason my output file looks like this:

Part Number         Description                   Quantity in Stock        Price
25483                "Special Order Widget"       (null)                   3100.00

Process returned 0 (0x0)   execution time : 0.017 s
Press any key to continue.



instead of this: Part Number Description Quantity in Stock Price
----------------------------------------------------------------------
23093 Basic Widget 143 299.99
23355 Mid-Range Widget 2556 749.99
21546 Advanced Widget 14 1599.99
25483 Special Order Widget 0 3100.00

It's lined up well, but for some reason when i paste it, it's not, but why is it only posting the last line from my input file, and null instead of "0"

The other question is can i use fstream to write and save this file as "prog2.out." , or do i have to use ofstream as well?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>

using namespace std;

#define DEBUG 1

#define MAX_WIDGETS 20
struct Widget {
    int number;
    string description;
    int quantity;
    double price;
};

bool openFileIn(fstream &, string);
int getWidgets(fstream &, Widget *);
int showWidgets(Widget *);
void split(const string&, char , vector<string>& );

int main()
{
	fstream dataFile;                              // data file
    Widget *widgets = new Widget[MAX_WIDGETS];     // dynamically allocate widget records

	if (openFileIn(dataFile, "widgets.dat"))
	{
        // get item data from file into array
    	getWidgets(dataFile, widgets);

    	dataFile.close();

        showWidgets(widgets);
	}
	else
       cout << "File open error!" << endl;

	return 0;
}

//***********************************************************
// Definition of function openFileIn. Accepts a reference   *
// to an fstream object as an argument. The file is opened  *
// for input. The function returns true upon success, false *
// upon failure.                                            *
//***********************************************************

bool openFileIn(fstream &file, string name)
{
   file.open(name.c_str(), ios::in);
   if (file.fail())
      return false;
   else
      return true;
}


/*
 * getWidget data one line at a time from
 * the file. Parse the line using ',' as delimiter.
 * Save data read to a Widget record pointed to
 * by s_ptr;
 */
int getWidgets(fstream &file, Widget *s_ptr)
{
    string input;	// To hold file input
    int count = 0;

    // Read student data from file using ',' as a delimiter.
    while (count < MAX_WIDGETS && getline(file, input)) {

        // vector to hold the tokens.
        vector<string> tokens;

        // Tokenize str1, using ' ' as the delimiter.
        split(input, ',', tokens);

        /*
         * copy the tokens to the widget record
         */
        s_ptr->number  = atoi(tokens.at(0).c_str());
        s_ptr->description =  tokens.at(1);
        s_ptr->quantity =  atoi(tokens.at(2).c_str());
        s_ptr->price =  atof(tokens.at(3).c_str());

        count++;
        cout << endl;
    }
}

/*
 * show all widgets
 */
int showWidgets(Widget *s_ptr)
{
    /* Display the headings for each column, with spacing and justification flags */
    printf("%-20s%-30s%-25s%-8s\n", "Part Number", "Description", "Quantity in Stock", "Price");

    // Read widget data from file using ',' as a delimiter.
    for (int i = 0; i < MAX_WIDGETS; i++) {

        if (s_ptr->number != 0) {

            printf("%-20d%-30s%-25s%-2.2f\n",
                    s_ptr->number,
                    s_ptr->description.c_str(),
                    s_ptr->quantity,
                    s_ptr->price);

            s_ptr++;
        }

        /* If the number field is zero, then we reached the last item description., break
         * out of the for loop.
         */
        else
            break;
    }
}

//**************************************************************
// The split function splits s into tokens, using delim as the *
// delimiter. The tokens are added to the tokens vector.       *
//**************************************************************
void split(const string& s, char delim, vector<string>& tokens)
{
   int tokenStart = 0;  // Starting position of the next token

   // Find the first occurrence of the delimiter.
   int delimPosition = s.find(delim);

   // While we haven't run out of delimiters...
   while (delimPosition != string::npos)
   {
      // Extract the token.
      string tok = s.substr(tokenStart, delimPosition - tokenStart);

      // Push the token onto the tokens vector.
      tokens.push_back(tok);

      // Move delimPosition to the next character position.
      delimPosition++;

      // Move tokenStart to delmiPosition.
      tokenStart = delimPosition;

      // Find the next occurrence of the delimiter.
      delimPosition = s.find(delim, delimPosition);

      // If no more delimiters, extract the last token.
      if (delimPosition == string::npos)
      {
         // Extract the token.
         string tok = s.substr(tokenStart, delimPosition - tokenStart);

         // Push the token onto the vector.
         tokens.push_back(tok);
      }
   }
}

Last edited on
> null instead of "0"
read the warnings
foo.cpp|112 col 21| warning: format specifies type 'char *' but the argument has type 'int' [-Wformat]
1
2
3
4
5
            printf("%-20d%-30s%-25s%-2.2f\n",
                    s_ptr->number,
                    s_ptr->description.c_str(),
                    s_ptr->quantity,
                    s_ptr->price);

"%s" is for c-strings, not for numbers
iirc you need "%d", but rtfm


> why is it only posting the last line from my input file
you only read onto widgets[0], each new line you read from the file you overwrite the value on widgets[0]


other error (in no particular order):
- {get,show}Widgets() promise to return int, but they do not return a value
- `widgets' leaks memory (missing delete[]), I fail to see a good reason for dynamic allocation
- `showWidgets()' consider that you did fill all the elements on the array, you access uninitialised data when doing if (s_ptr->number != 0)


> can i use fstream to write and save this file as "prog2.out."
sure


PS: next time post the input file too, shouldn't have to guess that it was a csv
I'm kinda lost on what you wrote here? I did fix the null problem, that makes sense

why is it only posting the last line from my input file
you only read onto widgets[0], each new line you read from the file you overwrite the value on widgets[0]

Also what do i write and where to save my original source code from widgets.dat into prog2.out?
1
2
3
4
5
6
7
8
9
10
//getWidgets(dataFile, widgets);
int getWidgets(fstream &file, Widget *s_ptr) //s_ptr = widgets, *str = widgets[0]
{
    //...
    while (count < MAX_WIDGETS && getline(file, input)) {
        //...
        s_ptr->number  = atoi(tokens.at(0).c_str()); //you always write onto *str
        //...
    }
}
compare against showWidgets()


> Also what do i write and where to save my original source code from
> widgets.dat into prog2.out?
¿see `showWidgets()'? print to a file instead of the screen
I still don't get it, i haven't tried using fprintf yet bc i wanna do this first, bc it makes more sense.
Last edited on
So compare the two in the get widgets function? I have no idea lol?
 
int getWidgets(fstream &file, Widget *s_ptr) //s_ptr = widgets, *str = widgets[0] 

so what ur saying is each time i run this code it overwrites the previous one, which is why it only shows me the last line of my file... i don't get why tho
Yeah idk i can't figure it out i've been trying to decipher what you wrote for the last hour and made no progress
You seem to be 'relying' on pointer math to "walk through" your array without actually using it.

C ++ Pointer Arithmetic - https://www.tutorialspoint.com/cplusplus/cpp_pointer_arithmatic.htm

Without incrementing your pointer to point to the next element in the array (or one other than the first) you are going to be constantly pointing to the first element, overwriting it.

This is why using C constructs instead of a C++ container like std::vector can bite you in the butt when one doesn't know all the ins and out of dealing with pointers.
okay so it has something to do with incrementing my pointer from what i've been reading
Well i tried adding *s_ptr++; to the bottom and now i only see the column headers for my output lol, got i hate this teacher lol, it really is a butt in the butt, he said we have to learn his way bc certain industries require a code to be done a certain way

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int getWidgets(fstream &file, Widget *s_ptr) // each new line overwrites th
{
    string input;	// To hold file input
    int count = 0;

    // Read student data from file using ',' as a delimiter.
    while (count < MAX_WIDGETS && getline(file, input)) {

        // vector to hold the tokens.
        vector<string> tokens;

        // Tokenize str1, using ' ' as the delimiter.
        split(input, ',', tokens);

        /*
         * copy the tokens to the widget record
         */
        s_ptr->number  = atoi(tokens.at(0).c_str());
        s_ptr->description =  tokens.at(1);
        s_ptr->quantity =  atoi(tokens.at(2).c_str());
        s_ptr->price =  atof(tokens.at(3).c_str());

        *s_ptr++;
        count++;
        
Last edited on
idek i'm watching a video on it now, so it looks like i have to "post increment" somewhere in the function...? It's probably painful to read my posts sorry i'm just confused asf
s_ptr++, NOT *s_ptr++. You incremented the value of what is stored at the memory location stored in the pointer.

Pointer basics - https://www.learncpp.com/cpp-tutorial/67-introduction-to-pointers/

Pointer math basics - https://www.learncpp.com/cpp-tutorial/6-8-pointers-and-arrays/ & https://www.learncpp.com/cpp-tutorial/6-8a-pointer-arithmetic-and-array-indexing/

<RANT>
Requiring pointer math and other C constructs from a beginner learning C++, saying it is what industries require, shows he (and/or the curriculum he teaches from) doesn't have much of a clue about what modern C++ has to offer. Or doesn't care.This is not C++ 101 material IMO, this is intermediate to advanced stuff.
</RANT>

Many times instructors teach "C first" because that is how they learned, or with a curriculum that is years old material based around C.

I am NOT saying you need to know about the bleeding edge material that new C++ standards have. I am NOT saying you shouldn't know about not-beginner topics like pointers. I simply disagree with WHEN certain concepts are taught. Pointers are one of the language concepts that can be delayed. Look at the difficulties you are experiencing. Using std::vectors could greatly simplify the code you have to write.
Last edited on
I'm trying to learn off the link you sent and it just doesn't make sense to me, all the examples show an array built into the example, so they just point to the next number in the array, so idk, i also tried making that change
s_ptr++, NOT *s_ptr++
and it does the exact same thing.... only print the headers.
Last edited on
Using std::vectors could greatly simplify the code you have to write.

Yeah my professor said that "we absolutely can not use any form of std:: ... " LOL
I'm at 5 hours of making no progress at this one spot so like idek lol, kinda going mad at this point
Like what kind of professor that i'm paying money to teach me, tells me go learn it on our own if he hasn't taught it yet lol... college is a big waste of money lol, i should of did a coding bootcamp smh
Last edited on
In ShowWidgets, you need to move s_ptr++ to AFTER the "}". (move line 115 to line 117).

Your code is checking the contents of s_ptr->number. If it's 0, do nothing. But s_ptr doesn't change and you keep looping through the same array element.

If you increment s_ptr, then you will check each element in the array and process it accordingly.

Edit: Oh, wait. I see that you are breaking out of the for loop if s_ptr->number is 0. Never mind.

Sorry.
Last edited on
does anyone have a solution?
Pages: 12