Why is code ignored?

I do not understand why code is ignored (seems to be skipped over) in the area identified between lines highlighted with
//**********************************
//**********************************
Lines 180-188

//**********************************
//**********************************

It's got me baffled. Can anyone help?


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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  // SIMPLE BEAM

#include <iostream>
#include <fstream>
#include <cstdio>
#include <string>
#include <cmath>	   //note we need to include this to use pow(b,e)
#include <iomanip>   //this has to be included to use setprecision()
#include <windows.h>

using namespace std;

/* Keeps window open upon completion. User closes
   window by pressing key at the prompt. */
inline void keep_window_open() {
	char ch;
	cin >> ch;
}

// Set console window size (Windows Only!)
void SetWindow(int Width, int Height)
    {
    _COORD coord;
    coord.X = Width;
    coord.Y = Height;

    _SMALL_RECT Rect;
    Rect.Top = 0;
    Rect.Left = 0;
    Rect.Bottom = Height - 1;
    Rect.Right = Width - 1;

    HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);      // Get Handle
    SetConsoleScreenBufferSize(Handle, coord);            // Set Buffer Size
    SetConsoleWindowInfo(Handle, TRUE, &Rect);            // Set Window Size
    }

// DECLARE GLOBAL VARIABLES
double  L,  rl, rr, ra, rb;
int j, k, nl, ns;
double vk, mk, mm, sm, z, z1, z2,wl;
double s, t;
double b, d, ec, i2;
string ldType;
string a1, a2, a3, a4, a5, a6;

//------------------------------------------------------------------------

// Set cursor position on the screen
void gotoxy(int x, int y)
{
	HANDLE hConsoleOutput;
	COORD dwCursorPosition;

	dwCursorPosition.X = x;
	dwCursorPosition.Y = y;
	hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hConsoleOutput,dwCursorPosition);
}

//---------------------------------------------------------------------

// Enter row of spaces at 0,24
void EnterRowOfSpaces()
{
	//gotoxy(0,24);
 	//cout << "                                                              ";
 	gotoxy(0,24);
   for (int i=1;i<80;i++)
	    cout << " ";
}

//----------------------------------------------------------------------

// Print a bar in prompt area at 0,23
void PrintBar()
{
   gotoxy(0,23);
   for (int i=1;i<80;i++)
	    cout << ":";
	    //cout << (char)223;
}

//-----------------------------------------------------------------------

//Print a line of dashes at 0,14
void PrintLine()
{
   gotoxy(0,14);
   for (int i=1;i<80;i++)
	    cout << "-";
}

//-----------------------------------------------------------------------

// Clear 6 rows in display area
void Clear6Rows()
{
      gotoxy(0,15);
	    string sp = "                                                              ";
	    cout << sp << endl << sp << endl << sp <<endl
               << sp << endl << sp << endl << sp ;
}

//------------------------------------------------------------------------

//Enter the data function
void EnterData()
{
   // TITLE
   gotoxy(0,0);
   cout << "\t\t\tSIMPLE BEAM DESIGN";

	//int num1, num2, i;

	PrintLine();

	gotoxy(0,22);
	 cout << "ENTER DATA BELOW, WHEN PROMPTED:"  << endl;
	 PrintBar();


// ENTER DATA REQUESTS IN PROMPT AREA
   gotoxy(0,24);
   cout << "ENTER NUMBER OF SECTIONS TO BE CONSIDERED ALONG BEAM ";
   cin >> ns;
   EnterRowOfSpaces();

   gotoxy(0,24);
   cout << "ENTER NUMBER OF LOADS ON THE SPAN: ";
   cin >> nl;
   nl=nl+1;
   EnterRowOfSpaces();

   gotoxy(0,24);
   cout << "ENTER SPAN OF BEAM (metres): ";
   cin >> L;

     // Display entered data at line 10
   gotoxy(0,0);
   cout	<< "No Of Sections: " << ns
				<< "   No of Loads: " << nl
				<< "   Span of Beam: " << L << " metres";



    int tl[nl+1];

   //INITIALIZE ARRAYS FOR SF & BM AT SECTIONS
   double vs[ns+1];
   double ms[ns+1];
   double W[nl+1];
   double a[nl+1];
   double c[nl+1];
   double dist[ns];
   double ds[ns];
   double dk, zd, k1, mx;
   double dm = 0, sd = 0;
   double s1[ns+1];
   string desc[nl+1];
   // End of initialization of arrays







//---------------------------------------------------
	// LOOP FOR NUMBER OF LOADS
	//---------------------------------------------------
	for (int j = 1; j<nl; j++) {         // start the FOR loop for loads
      gotoxy(0,24);
      EnterRowOfSpaces();
      gotoxy(0,24);
      cout <<"LOAD NUMBER " << j ;
      cout <<":  ENTER TYPE OF LOAD (1, 2, 3 or 4): ";
      cin >> tl[j];

      //**************************************
      //**************************************
      // WHY IS THIS SECTION OF CODE IGNORED???
      EnterRowOfSpaces();
      gotoxy(0,24);
      cout << "ENTER DESCRIPTION OF LOAD: ";
      getline(cin, desc[j]);
      //***************************************
      //***************************************

      //PROGRAM STARTS AGAIN HERE!
      EnterRowOfSpaces();
      gotoxy(0,24);
      cout<<"ENTER LOAD, W (kN): ";
      cin>>W[j];

      EnterRowOfSpaces();
      gotoxy(0,24);
      cout << "ENTER DISTANCE OF START OF LOAD FROM LEFT SUPPORT (metres): ";
      cin >> a[j];

      EnterRowOfSpaces();
      gotoxy(0,24);
      cout<<"ENTER LENGTH OF LOAD COVER - 0 IF PL (metres): ";
      cin>>c[j];
      cout<<endl;
	}
      // End entering beam load and dimensional data




	// End of Function EnterData()
}

	  int i = 20;
    //int nl;
    //nl = 3;
    const int arraySize = nl+1;


int main()
{
   // Set the console window size
   SetWindow(80,30);

	EnterData();

	// Clear data entry areas
	Clear6Rows();
	gotoxy(0,24);
	EnterRowOfSpaces();
	gotoxy(0,24);
   return 0;
}
Last edited on
I've not tried to compile or run this. However, reading through the code, it looks like a common problem of mixing formatted input with cin (e.g. cin >> x;) together with getline(). The two don't always play nicely together because of the way that whitespace is handled.

I suggest you try this. After line 178
 
      cin >> tl[j];

insert this line to remove the trailing newline which is left in the input buffer:
 
    cin.ignore(1000, '\n');



Unrelated to that problem, I noticed variable-length arrays being used in several places, which are not a standard part of C++ but are a compiler extension provided by some compilers.

The C++ replacement would be std::vector.
e.g.
 
    int tl[nl+1];
would become
 
    vector<int>  tl(nl+1);


(requires #include <vector> )
The behaviour is the same as an array once that is done. (though vectors offer other benefits which you may not need).
Last edited on
@Chervil
Thank you that has resolved the problem. I'm not sure how, but it has solved the problem.

I understand that cin can leave the newline character. I'm not sure how cin.ignore(1000, '\n'); gets over this, nor why it is a problem in just this one place in the code. Should cin.ignore(1000, '\n'); be inserted after every cin?

With respect to the use of vectors, I've only just starting to read up on vectors and I'm finding them a bit complicated at present. I'll probably return to the in due course.
vectors are just better arrays. You can use them exactly like an array, if you allocate them:

vector<int> I(100); //works pretty much the same as int I[100];

there is more to it, of course; vector has a built-in size and can grow in size and do other things, but to get started, you can do the above type of lines and use it exactly as if you had your arrays.

cin.ignore only needs to happen before you call getline. I did not look super close but I did not see another getline so I think you do not need any more of those. It is clearing the input buffer so getline will work, just in case the input buffer has stray whitespace. What was happening is NOT that the lines were skipped, it was that getline was reading a blank line.

Last edited on
You can read a little more about cin.ignore() in this thread:

http://www.cplusplus.com/forum/beginner/223189/#msg1022987
@Chervil
I see. A bit rough and ready, but does the job. It's in my code.

@jonnin
Thank you for your response. I'm sure I'll get my head around vectors in due course and will change the code accordingly, but I'm really a beginner at C++ and it's on my todo list.
There is only one getline in the code at present.
I could understand if we were only talking about the effect on getline, but there is a cout statement before getline which isn't showing on the screen, or is it immediately being cleared (so fast you can't see it)?
When it comes to cout not displaying, that may be because the output is buffered. Usually the contents of the buffer are put onto the console before any cin. But it may sometimes be necessary to flush the buffer. Sounds complicated/technical? I won't attempt the details, but putting a flush after the output should do it
 
    cout << "something something" << flush;

edit: probably best to ignore the above for now.

Actually, thinking about it (I still didn't try to run the program) your use of gotoxy() makes this program a little different to those programs where the output simply scrolls each time. Since you are placing successive outputs in the same place on the screen, there's no way you would see the earlier output, unless there was a pause - such as waiting of the user to type some input.
Last edited on
@Chervil
I'm not sure i can agree with your statement about waiting for the user to type some input.

The code is based on a BASIC program I wrote for the Amstrad CPC about 35 years ago. Basically the console screen is divided into three sections, the top section is used for display, the middle for issuing prompt guidance and the bottom line is used to display a prompt and input an answer. Upon pressing ENTER the next prompt comes up. There is no other sort of waiting for user input.

This system is used throughout the coding and it is only before the use of getline that it broke down. However, the workaround you provided solved this.

Ultimately, the idea is that this code will provide a way of providing an analysis of a simply supported beam. This can then be extended to design steel, concrete and timber beams. In the domestic situation, almost all beams are simply supported, so more complicated analysis is not required. When I get to (if I get to) designing steel beams etc, I shall have to ensure proper understanding of current codes of practice, because it is many years since I last did any structural design. Maybe someone on the forum will be able to help with this in due course.

Your help, and jonnin, to date is very much appreciated.
I'm not sure i can agree with your statement about waiting for the user to type some input.


Well, let me try to explain:
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
      gotoxy(0,24);
      EnterRowOfSpaces();
      gotoxy(0,24);
      cout <<"LOAD NUMBER " << j ;
      cout <<":  ENTER TYPE OF LOAD (1, 2, 3 or 4): ";
      cin >> tl[j];

      //**************************************
      //**************************************
      // WHY IS THIS SECTION OF CODE IGNORED???
      EnterRowOfSpaces();
      gotoxy(0,24);
      cout << "ENTER DESCRIPTION OF LOAD: ";
      getline(cin, desc[j]);
      //***************************************
      //***************************************

      //PROGRAM STARTS AGAIN HERE!
      EnterRowOfSpaces();
      gotoxy(0,24);
      cout<<"ENTER LOAD, W (kN): ";
      cin>>W[j];

I think it's fair to say that all the output in that block of code is printed at the same place on the screen. gotoxy(0,24); is used consistently before each cout.

What happens next? Well there's a cin >> tl[j];
The program will pause there and wait for the user to type something, and press enter. As soon as the user presses enter, the program reads the value of tl[j] from the input buffer. Remember there is also a newline character after the input , and possibly some other characters depending on what the user typed.

Now the program proceeds to line 183, 184, 185 and outputs the next prompt to the screen.
Next it waits for the user to type a line of text and press enter. How long does it wait? Well it finds the newline already there so it continues immediately, certainly in less than the 1/60 second which might be a screen refresh rate. We're talking nanoseconds here, I guess. The result is a line of length zero, an empty string, is stored in desc[j].

Now the program proceeds to line 191, 192, 193, displays the prompt and waits for the user to enter W[j].

Does that clarify anything? I hope so.

As for BASIC. I used that a lot in the past, though not on the same machine you mentioned. BASIC can be a lot of fun because it is usually fairly bullet-proof, it has all the rough edges rounded off and the i's dotted and t's crossed. In a language like C++ you often have to dot the i's and cross the t's yourself - if that metaphor makes sense.

What is commonly done rather than using getline() or cin >> directly, is to write a very short function which might position the cursor, output the prompt and get the input, possibly also doing some validation, such as making sure that the user didn't type a letter when a number was expected, that sort of thing, and it could tidy-up the input buffer after each input. Then, the main program just uses a simple function call and everything becomes simple again because all the messy details are inside a function. It also avoids having to write the same code over and over again. That code might look something like this:
1
2
3
4
5
      get_number("ENTER TYPE OF LOAD (1, 2, 3 or 4): ", tl[j]);

      get_string("ENTER DESCRIPTION OF LOAD: ", desc[j]);
      
      get_number("ENTER LOAD, W (kN): ", W[j]);

... but that's just an example.
Last edited on
@Chervil
I think we are actually agreeing, just expressing it different ways.

I hear what you are saying about writing a function for input. At the moment, there is no error checking at all in my code and you could enter almost anything at the prompts. That is still to come after I have got the outline working properly. There's still a lot of work to do.

I'm using this code as an example to learn C++. After so long away from serious coding the slope is very steep, but every success along the way is very gratifying, particularly when help is provided so freely.
Some of the suggestions I mentioned:
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// SIMPLE BEAM

#include <iostream>
#include <fstream>
#include <cstdio>
#include <string>
#include <cmath>       // note we need to include this to use pow(b,e)
#include <iomanip>     // this has to be included to use setprecision()
#include <vector>      // to handle variable-length arrays.
#include <sstream>     // for I/O as string
#include <windows.h>

using namespace std;

/* Keeps window open upon completion. User closes
   window by pressing key at the prompt. */
inline void keep_window_open() 
{
    char ch;
    cin >> ch;
}

// Set console window size (Windows Only!)
void SetWindow(int Width, int Height)
{
    _COORD coord;
    coord.X = Width;
    coord.Y = Height;

    _SMALL_RECT Rect;
    Rect.Top = 0;
    Rect.Left = 0;
    Rect.Bottom = Height - 1;
    Rect.Right = Width - 1;

    HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);      // Get Handle
    SetConsoleScreenBufferSize(Handle, coord);            // Set Buffer Size
    SetConsoleWindowInfo(Handle, TRUE, &Rect);            // Set Window Size
}

// DECLARE GLOBAL VARIABLES
double  L,  rl, rr, ra, rb;
int    j, k, nl, ns;
double vk, mk, mm, sm, z, z1, z2,wl;
double s, t;
double b, d, ec, i2;
string ldType;
string a1, a2, a3, a4, a5, a6;

//------------------------------------------------------------------------

// Set cursor position on the screen
void gotoxy(int x, int y)
{
    HANDLE hConsoleOutput;
    COORD dwCursorPosition;

    dwCursorPosition.X = x;
    dwCursorPosition.Y = y;
    hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hConsoleOutput,dwCursorPosition);
}

//---------------------------------------------------------------------

// Enter row of spaces at 0,24
void EnterRowOfSpaces()
{
    gotoxy(0,24);    
    cout << string(80, ' ');
}

//----------------------------------------------------------------------

// Print a bar in prompt area at 0,23
void PrintBar()
{
    gotoxy(0,23);
    cout << string(80, ':');    
}

//-----------------------------------------------------------------------

//Print a line of dashes at 0,14
void PrintLine()
{
    gotoxy(0,14);
    cout << string(80, '-');
}

//-----------------------------------------------------------------------

// Clear 6 rows in display area
void Clear6Rows()
{
    gotoxy(0,15);
    string sp(80, ' ');
    cout << sp;
    for (int i=0; i<5; ++i)
        cout << '\n' << sp;
}

//------------------------------------------------------------------------

// integer
void get_number(const string & prompt, int & value)
{
    gotoxy(0,24);
    EnterRowOfSpaces();
    gotoxy(0,24);    
    cout << prompt;
    cin  >> value;
    cin.ignore(1000, '\n');
}
//------------------------------------------------------------------------

// double
void get_number(const string & prompt, double & value)
{
    gotoxy(0,24);
    EnterRowOfSpaces();
    gotoxy(0,24);    
    cout << prompt;
    cin  >> value;
    cin.ignore(1000, '\n');
}

//------------------------------------------------------------------------

void get_string(const string & prompt, string & value)
{
    gotoxy(0,24);
    EnterRowOfSpaces();
    gotoxy(0,24);    
    cout << prompt;
    getline(cin, value);
}

//------------------------------------------------------------------------

//Enter the data function
void EnterData()
{
    // TITLE
    gotoxy(0,0);
    cout << "\t\t\tSIMPLE BEAM DESIGN";

    //int num1, num2, i;

    PrintLine();

    gotoxy(0,22);
    cout << "ENTER DATA BELOW, WHEN PROMPTED:"  << endl;
    PrintBar();

    // ENTER DATA REQUESTS IN PROMPT AREA
    get_number("ENTER NUMBER OF SECTIONS TO BE CONSIDERED ALONG BEAM ", ns);
    
    get_number("ENTER NUMBER OF LOADS ON THE SPAN: ", nl);
    nl = nl + 1;
        
    get_number("ENTER SPAN OF BEAM (metres): ", L);

    // Display entered data at line 10
    gotoxy(0,0);
    cout << "No Of Sections: " << ns
         << "   No of Loads: " << nl
         << "  Span of Beam: " << L << " metres";

    vector<int> tl( nl + 1 );   // variable-length array

    //INITIALIZE ARRAYS FOR SF & BM AT SECTIONS
    vector<double> vs( ns + 1 );
    vector<double> ms( ns + 1 );
    vector<double> W( nl + 1 );
    vector<double> a( nl + 1 );
    vector<double> c( nl + 1 );
    vector<double> dist( ns );
    vector<double> ds( ns );

    double dk, zd, k1, mx;
    double dm = 0, sd = 0;

    vector<double> s1( ns + 1 );
    vector<string> desc( nl + 1 );
    // End of initialization of arrays


    //---------------------------------------------------
    // LOOP FOR NUMBER OF LOADS
    //---------------------------------------------------
    for (int j = 1; j<nl; j++) 
    {         
        ostringstream oss;
        oss << "LOAD NUMBER " << j 
            <<":  ENTER TYPE OF LOAD (1, 2, 3 or 4): ";
            
        get_number(oss.str(), tl[j]);

        get_string("ENTER DESCRIPTION OF LOAD: ", desc[j]);
        
        get_number("ENTER LOAD, W (kN): ", W[j]);

        get_number("ENTER DISTANCE OF START OF LOAD FROM LEFT SUPPORT (metres): ", a[j]);
        
        get_number("ENTER LENGTH OF LOAD COVER - 0 IF PL (metres): ", c[j]);
        cout << endl;
    }
    // End entering beam load and dimensional data

}

//-----------------------------------------------------------

int main()
{
    // Set the console window size
    SetWindow(80,30);

    EnterData();

    // Clear data entry areas
    Clear6Rows();
    gotoxy(0,24);
    
    EnterRowOfSpaces();
    gotoxy(0,24);
    
    return 0;
}
@Chervil
Thank you very much for the code examples. I'll have a good look at it and digest it before I continue coding.
Ray
@Chervil
I like it!
I'll incorporate it in the code.

I'm not sure about:
1
2
3
ostringstream oss;
oss << "LOAD NUMBER " << j 
      <<":  ENTER TYPE OF LOAD (1, 2, 3 or 4): ";

but I'll see if I can find out what it means.

I'll also look into expanding the functions to incorporate width, precision and error checking. That'll take me a bit of time.
Topic archived. No new replies allowed.