Choosing a programming language to learn can be challenging, especially for someone with a background in older languages like assembly, Fortran, and Pascal. C# and C++ are considered for firmware design, while Python is favored for its ease of use and relevance to gaming, particularly with grandchildren. C++ is noted for its speed and compactness, making it suitable for game programming, but it may require more effort to learn compared to C#. Resources like Visual Studio for C# and various online tutorials can help beginners get started, while microcontroller programming can be explored through platforms like Arduino and Raspberry Pi. Ultimately, the choice should align with personal interests in scientific or gaming applications.
There are reasons that goto is frowned on. Some standards forbid it. Bad programmers have put so many gotos in their code that they become spider webs. If you use it, make sure there is no other way and keep it as simple as possible. Avoid it if possible.
There are reasons that goto is frowned on. Some standards forbid it. Bad programmers have put so many gotos in their code that they become spider webs. If you use it, make sure there is no other way and keep it as simple as possible. Avoid it if possible.
I thought myThing is a 20 character string, that is each element is only ONE charater. like if myThing [] = "Hello"
No. In the declaration std::string myThing[20];, myThing is a container with 20 elements, each of which is an std::string. Each element is not necessarily a single character.
yungman said:
myThing[0] = 'H'; myThing[1] = 'e'; myThing[2] = 'l'; etc. But you are saying myThing[0] = "Hello" a whole word. Which one is correct?
See above.
yungman said:
I am learning loops, the goto, while, do-while all doing the same thing. Do I have to learn all or them or I just stick with one and be done with it? too many options here.
The goto statement is not a loop -- it's a branch instruction.
There are three types of loops: for (which you didn't mention), while, and do ... while. They don't all do the same thing.
A for loop is usually used when you want the loop to execute a specific number of times.
A while loop is usually used when you don't know how many times the loop should execute. It checks the condition expression first, so the loop body might not execute at all.
A do...while loop is also used when you don't know how many times the loop should execute, but it checks the condition expression after each loop iteration. It will always execute at least once.
FactChecker said:
There are reasons that goto is frowned on. Some standards forbid it. Bad programmers have put so many gotos in their code that they become spider webs.
Granted, goto is usually frowned on, but there are legitimate reasons to use it, such as to bail out under extraordinary conditions. Some arguments pro, per Steve McConnell's "Code Complete," pp. 348,349.
A well-placed goto can eliminate the need for duplicate code.
The goto is useful in a routine that allocates resources, performs operations on those resource, and then deallocates the resources. With a goto, you can clean up in one section of code.
In some cases, the goto can result in faster and smaller code. Knuth's 1974 article cited a few cases in which the goto produces a legitimate gain.
Two decades' worth of research with gotos has failed to demonstrate their harmfulness. In a survey of the literature, B.A. Sheil concluded that unrealistic test conditions, poor data analysis, and inconclusive result failed to suppor the claim of Shneiderman and others that the number of bugs in code was proportional to the number of gotos (1981).
Finally, the goto was incorporated into the Ada language, the most carefully engineered programming language in history. Ada was developed long after the arguments on both sides of the goto debate had been fully developed.
yungman said:
So "while" it is! too many options in C++.
Suit yourself, but really, you should learn all three loop constructs: for, while, do...while.
I thought myThing is a 20 character string, that is each element is only ONE charater. like if myThing [] = "Hello"
myThing[0] = 'H'; myThing[1] = 'e'; myThing[2] = 'l'; etc. But you are saying myThing[0] = "Hello" a whole word. Which one is correct?
myThing is a collection of 20 strings. Each string is a collection of characters. If you want to access individual characters, you need to specify two indexes: which string and which character. Example:
Code:
std::string myThing[20];
myThing[0] = "Hello";
myThing[1] = "my";
myThing[2] = "name";
std::cout << "First word is " << myThing[0] << std::endl;
std::cout << "Second letter of third word is " << myThing[2][1] << std::endl;
myThing[0][0] = 'J';
std::cout << "First word is now " << myThing[0] << std::endl; // guess it, then try it!
Last edited:
#256
yungman
5,741
294
Mark44 said:
No. In the declaration std::string myThing[20];, myThing is a container with 20 elements, each of which is an std::string. Each element is not necessarily a single character.
See above.
The goto statement is not a loop -- it's a branch instruction.
There are three types of loops: for (which you didn't mention), while, and do ... while. They don't all do the same thing.
A for loop is usually used when you want the loop to execute a specific number of times.
A while loop is usually used when you don't know how many times the loop should execute. It checks the condition expression first, so the loop body might not execute at all.
A do...while loop is also used when you don't know how many times the loop should execute, but it checks the condition expression after each loop iteration. It will always execute at least once.
Granted, goto is usually frowned on, but there are legitimate reasons to use it, such as to bail out under extraordinary conditions. Some arguments pro, per Steve McConnell's "Code Complete," pp. 348,349.
Suit yourself, but really, you should learn all three loop constructs: for, while, do...while.
To me, for is different from the others as you program how many times. The other ones just loop until jumping out. Just use an if statement to to goto start. They all do the same thing at the end.
Well, among sane programmers, GOTOs are fine. But look around at your fellow programmers -- are they sane? Or are they sociopaths? The odds are that some are sociopaths. ;>)
To me, for is different from the others as you program how many times.
All three loop constructs are different, as I explained in post #253.
yungman said:
The other ones just loop until jumping out.
No. The body of a while loop might not execute at all.
yungman said:
Just use an if statement to to goto start. They all do the same thing at the end.
Well, sure, the assembly code that the compiler generates boils down to compare instructions and jump instructions.
yungman said:
too many options in C++.
All procedural programming languages at a higher level than assembly provide the same sorts of loop statements.
#259
yungman
5,741
294
I have been reviewing int array and char array, and then strings. A lot of my confusion are in this area. I feel I have been asking stupid questions. Also, I am reading back this thread again, memory is failing!
I'll be back.
#260
yungman
5,741
294
Mark44 said:
......
C++:
char sayHello2 = "Hello";
Both definitions store the letters in the first 5 bytes of memory, followed by an ASCII null character. Both arrays have a length of 5, the number of characters up to the null.
........
This is about post #239
I though this is a 6 elements char array as the last one is '\0'.
I want to confirm these
1) You can declare: char myChar[] = " This" to create a 5 elements char array. But after this, you can ONLY write one element at a time. There's no myChar = "ABCD" one step filling 4 characters.
2) After declaring int myNumbers[] = {1,2,3,4,5}, I cannot read all 5 numbers in one code line, has to be one element at a time eg. cout << myNumbers[1] << endl; to read out "2".
3) There is no command to write all 5 numbers into myNumber[] in one line of code, has to be one number at a time.
C++ and C can be very frustrating for scientific and engineering use. It lacks several features that were in FORTRAN specifically for that use (like reading and writing arrays).
1) You can declare: char myChar[] = " This" to create a 5 elements char array. But after this, you can ONLY write one element at a time. There's no myChar = "ABCD" one step filling 4 characters.
Correct. The reason that you can't assign a new string to it is that myChar is a constant -- it can't be modified. In particular it is a pointer constant, which I don't think you've gotten to yet.
yungman said:
2) After declaring int myNumbers[] = {1,2,3,4,5}, I cannot read all 5 numbers in one code line, has to be one element at a time eg. cout << myNumbers[1] << endl; to read out "2".
Sort of correct, although your use of "read out" is a bit confusing. I would rephrase this to say that you can't output all of the numbers at the same time -- you have to access them one at a time.
I said "sort of correct" because the following is one code line.
3) There is no command to write all 5 numbers into myNumber[] in one line of code, has to be one number at a time.
Correct. After the array has been initialized, there's no way to reassign a set of new values other than one at a time.
#263
yungman
5,741
294
Mark44 said:
......
C++:
char sayHello2[] = "Hello";
Both definitions store the letters in the first 5 bytes of memory, followed by an ASCII null character. Both arrays have a length of 5, the number of characters up to the null.
........
I though this is a 6 elements char array as the last one is '\0'.
Mark44 said:
Correct. The reason that you can't assign a new string to it is that myChar is a constant -- it can't be modified. In particular it is a pointer constant, which I don't think you've gotten to yet.
I can change the characters in myChar, it is not defined as constant. just has to be one by one.
If I do cout << myChar; I will get "FGst" as I changed the first two characters. I actually verified with the program.
ThanksI don't mean to challenge you, I just feel this is very important for me to understand this for once. I am NOT learning anything more new until I get through array and strings. I want it to be very clear on this.
Both definitions store the letters in the first 5 bytes of memory, followed by an ASCII null character. Both arrays have a length of 5, the number of characters up to the null.
........
yungman said:
I though this is a 6 elements char array as the last one is '\0'.
The array has 6 elements, but the length of the string is 5, as reported by strlen(), is the number of characters up to, but not including the terminating null.
yungman said:
I can change the characters in myChar, it is not defined as constant. just has to be one by one.
If I do cout << myChar; I will get "FGst" as I changed the first two characters. I actually verified with the program.
myChar IS a constant, but myChar[0], myChar[1], etc. are not constants. You can change the individual characters in the string, provided that you include the index of the character (in brackets).
In short, you can't do this: myChar = "FGst";, but you can change individual characters as you did in your code example.
The constant that myChar represents is the address of the first byte in the array. Because myChar is a constant, you are not allowed to assign an new value (i.e., an address) to it.
#265
yungman
5,741
294
Mark44 said:
From post #239:
The array has 6 elements, but the length of the string is 5, as reported by strlen(), is the number of characters up to, but not including the terminating null. myChar IS a constant, but myChar[0], myChar[1], etc. are not constants. You can change the individual characters in the string, provided that you include the index of the character (in brackets).
In short, you can't do this: myChar = "FGst";, but you can change individual characters as you did in your code example.
The constant that myChar represents is the address of the first byte in the array. Because myChar is a constant, you are not allowed to assign an new value (i.e., an address) to it.
Thanks
So myChar is actually an address pointing to the first character of the array? I thought I asked and you said it's not somewhere. Is that true for int array, strings also?
Also, if I declare myChar[] = "Test", I forever locked myself that strlen() is going to be 4 for the rest of the program?
With C-style arrays, whether of chars, ints or anything else, the name of an array by itself with no index (subscript) always "decays" to a pointer to the first item in the array.
This is not true for C++ std::string or std::array. The name of a string variable always represents the entire string, which is an object that contains more than just the chars. You can assign literal strings to them, and they automatically resize themselves accordingly.
Code:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
int main ()
{
string name = "Huey";
cout << name << " has " << name.length() << " characters." << endl;
name = "Dewey";
cout << name << " has " << name.length() << " characters." << endl;
return 0;
}
Output:
Code:
Huey has 4 characters.
Dewey has 5 characters.
(the first C++ program on my new iMac, after installing the compiler today! )
Last edited:
#267
yungman
5,741
294
jtbell said:
With C-style arrays, whether of chars, ints or anything else, the name of an array by itself with no index (subscript) always "decays" to a pointer to the first item in the array.
.......
What is the meaning of "decays"? Do you mean the array name is actually a POINTER ( address) to the first member of the array ( char, int and others)?
Thanks
I don't even look at strings and std::array. I just concentrate on array and C-String and resolve that, hopefully tomorrow I can get into strings. That's another can of worms. I just get the feeling that this is very very important to just go through the program and move on.
What is the meaning of "decays"? Do you mean the array name is actually a POINTER ( address) to the first member of the array ( char, int and others)?
In a declaration like int numArray[5];, this is an array of five int values. However, if the name appears by itself, with no brackets, the name is a constant - the address of the first int value in the array -- a pointer. In this case, the address is of the first byte of the four bytes that hold an int value.
This business of array names being addresses will become more significant when you study functions and their parameters.
#269
yungman
5,741
294
Mark44 said:
In a declaration like int numArray[5];, this is an array of five int values. However, if the name appears by itself, with no brackets, the name is a constant - the address of the first int value in the array -- a pointer. In this case, the address is of the first byte of the four bytes that hold an int value.
This business of array names being addresses will become more significant when you study functions and their parameters.
Sorry, I need to absolutely confirm: numArray[5] is an array with 5 elements. numArray is the address that point to the first element of array numArray[5].
Are std::strings like this also? Without brackets is the address pointing to the first element?
Seems to be a really good book, I read the part on std::string section, it's very good. I should have waited for this book instead of wasting time on the first book. Now I am thinking whether I should stop and start over again following this new book.
I bought this used for cheap, it's in really bad shape. First time I bought a used book that is like this, pages wrinkled, pen marked all over the place, all worn out. I am going to read more, if it is that good, I might buy a better condition one.
Sorry, I need to absolutely confirm: numArray[5] is an array with 5 elements. numArray is the address that point to the first element of array numArray[5].
Why do you need to confirm this ? it's exactly what I said, and which you quoted.
yungman said:
Are std::strings like this also?
No, they are very different.
yungman said:
Without brackets is the address pointing to the first element?
No. In @jtbell's post, name is a string instance, an object of type std::string. It contains data members such as size and capacity, as well as the data making up the characters in the string, and provides access to all of the function members that belong to the object. A C-type character array has only the characters in it, and none of the other capabilities of the Standard Template Library string class.
Are std::strings like this also? Without brackets is the address pointing to the first element?
No, as I wrote in post #266.
#273
Jarvis323
1,247
988
yungman said:
numArray is the address that point to the first element of array numArray[5].
Sort of.
There are two types of raw arrays, static and dynamic. This is a static array. The memory is allocated on the stack, which is limited in size. A dynamic array is allocated manually and stored on the heap, which has much more space.
C:
int x[5]; // static array
int * y= new int[5]; // dynamic allocation
...
delete [] y; // must manually delete y
So you can see x and y are both "arrays", but y's type is a pointer/memory address. x and y are used the same way, by accessing their elements by index with the bracket operator.
So what is the bracket operator in this case? It's actually syntactic sugar (simplified syntax) for two operatotions put together: pointer arithmetic and dereferencing.
To understand pointer arithmetic, first understand that pointers store memory addresses to typed values each with specific sizes in bytes (e.g. an int is 4 bytes), but memory itself is addressed byte by byte. That is, say the first byte (8 bits) has address 1, then the next byte has address 2. An int starting at address 1 covers 4 bytes. So address 5 is the address 1 int beyond address 1. So pointer arithmetic means, say y is a pointer to an int starting at address 1, then y+2 is actually y's value + sizeof(int)*2, which is the address 9, 8 bytes (2 ints) passed the first one.
Now the bracket operator used to access elements in the array is actually doing this: y[2] is equivalent to *(y+2). y+2 gives you the address of the third element using pointer arithmetic. Then the * dereferences the result (another overload), which means it grabs those 4 bytes starting at the address of the first byte where the int value is stored and returns it as an int.
So why is x almost a pointer but not truly a pointer?
When you use the bracket operator to access elements, it's treated like a pointer. You can say it decays in that it is implicitly cast to a pointer first. So for x, the bracket operator is more like this: x[2] is *(((int *)x)+2). This is casting x to a pointer to an int, then doing pointer arithmetic, then dereferencing the pointer. So what is the difference between x and a pointer? Mainly it is that sizeof(x) is the size in bytes of the array, which is 5*4, whereas sizeof(y) is the size of a pointer, which is 8 on 64 bit executables or 4 on 32 bit executables.
std::string can't be explained until you've learned about classes. But you can think of it as an object that internally stores and manages a dynamically allocated c-string/char array.
This is an actual textbook, written for use in college/university programming courses. The link is to the 6th edition (2009). By the time it came out, I had already stopped teaching C++, so I never used it myself. That it uses std::string is a good sign. Does it also use std::vector?
It's now up to the 10th edition (2019), so it must be a popular textbook used by many schools. It's expensive because of the way the textbook "racket" works. The 8th edition (2013) probably includes some of the significant additions to C++ in the C++11 standard (like std::array and range-based for-loops). It might be worth watching for a cheap copy of that edition or a later one.
First time I bought a used book that is like this, pages wrinkled, pen marked all over the place, all worn out.
That means it was probably actually used by a student for two semesters in a real C++ course. Maybe two or three students in successive years, depending on when the next edition appeared.
Because it's a textbook, it probably has lots of programming exercises. Hint, hint...
Last edited:
#275
yungman
5,741
294
jtbell said:
This is an actual textbook, written for use in college/university programming courses. The link is to the 6th edition (2009). By the time it came out, I had already stopped teaching C++, so I never used it myself. That it uses std::string is a good sign. Does it also use std::vector?
It's now up to the 10th edition (2019), so it must be a popular textbook used by many schools. It's expensive because of the way the textbook "racket" works. The 8th edition (2013) probably includes some of the significant additions to C++ in the C++11 standard (like std::array and range-based for-loops). It might be worth watching for a cheap copy of that edition or a later one.
That means it was probably actually used by a student for two semesters in a real C++ course. Maybe two or three students in successive years, depending on when the next edition appeared.
Because it's a textbook, it probably has lots of programming exercises. Hint, hint...
I spent more time on the book reading std::string and even some pointers. It is a REALLY REALLY good book. This is the one my grandson used, he even gave me the pdf file. But due to my neck problem, I cannot read on the monitor for long time, besides I want to ruin my own book by writing notes. I bought the used one for cheap, I am printing the book out chapter by chapter to read now.
So far, it's very clear, I think I only have to print the function and one or two chapters more, those condition logical comparison, boolean stuffs and even the looping stuffs are quite easy, I think I got the idea from even the worst book...the first one. It's the structures, naming stuffs that's hard for me. All the instance, class, headers, objects stuffs. The programming is actually not hard as long as I get all the names straight.
I somehow have a mental block of names, so often I ask the person for phone number, I remember the phone number and didn't remember the name!
#276
yungman
5,741
294
I am so stoked reading the GADDIS book, it is so simple. I read the std::string, but I decided to stop and go through what I learn in the last 2 weeks or so. Now I think I have a better feel of the names...
That object is just a self contained module with both data and programs, it just carry out request from the main program with given parameter and return results. It is like a module that the main program call upon to perform a task.
That cout and cin are object that the main program can call to write a stream onto the console or read as stream from the keyboard, that << and >> are streaming operator.
That header files contain a set of object files of particular type of function that the program to call on. Just like cout and cin are object in iostream for streaming. That we #include <iostream> in order to access to cout and cin.
These were all a blur to me before, the first book doesn't explain any of these. When you guys explain, it's really over my head. This book really starting from basic on up. I went through quite a few pages, I think it's worth my while to even have to stop for a few days and catch up with all the holes I missed.
Before, all the names and terms is just like people's names, why you call John? Why your last name is Jones? It's like I just blindly remember the names and it's hard.
I learn a lot on strings also, but I don't even want to talk about it until I back track all the stuffs and revisit again.
I am stoked.
#277
yungman
5,741
294
I am working of cin.get(). I think I got what I want from the program, BUT, it's really not what I want.
I want the program to read in any character from the keyboard, display it and show the ASCII number. Then loop back to ask another character. I want it to exit when I hit ENTER ( ASCII = 10)
I understand for cin, I need to hit the character and then ENTER to get it going or else it will just sit there and wait. cin.get can recognize ENTER as character. BUT, I still have to hit ENTER again before it will exit the loop. this is because I have to put in cin.ignore to prevent the program from reading the ENTER that is in the stream and exit without looping. Is there any way to exit right when I hit ENTER if I choose to exit?
C++:
#include <iostream>
using namespace std;
int main()
{
int Ascii = 0;
char userSelection = 'A';
do
{
cout << "hit any key: ";
cin.get(userSelection);
cin.ignore();
Ascii = userSelection;
cout << "you hit: " << userSelection << ", the ASCII is = " << Ascii << endl;
} while (userSelection != 10) ;
return 0;
}
Rather than try and fit an answer into what you wrote, I'm going to totally rewrite it for you. In doing this you will see that nearly every line is different. Apart from the difference between this
C:
int main()
{
// Code here.
and this
C:
int main() {
// Code here.
, and 2 spaces of indent vs. 4, which are just different style choices, all the other differences are important. Some of them (like
C:
int ascii = 0;
vs
C:
int Ascii = 0;
wont stop your code working, but they can make it more vulnerable to mistakes and you should get into the right habits now.
So here we go, you can also see this working at https://repl.it/repls/RealSubduedAtom. This code is missing comments of course, you might like to add them as you work through it.
C:
#include <iostream>
using namespace std;
#define EOL '\n'
int main() {
int ascii = 0;
char userSelection = 0;
while (userSelection != EOL) {
cout << "type a key and [enter]: ";
cin.get(userSelection);
ascii = userSelection;
if (userSelection == EOL) continue;
cin.ignore(255, EOL);
cout << "the first key was: " << userSelection
<< ", the ASCII is " << ascii << endl;
}
return 0;
}
#279
yungman
5,741
294
Thanks, that's what I want, but I don't understand.
So ENTER = '\n' ? I did not know about this!
I don't remember whether I can use const char EOL = '\n' instead of #define EOL '\n'
What is continue? I don't see in while loop have anything to do with this.
You put the user's input in two variables, a char and an int, so you could display it in both formats. Instead, you can use just the char variable to get both formats:
Code:
cout << "the first key was: " << userSelection
<< ", the ASCII is " << int(userSelection) << endl;
We call this "casting" the char variable to int.
It works the other way, too. If you have int ascii = 97;, then cout << char(ascii) displays a.
#283
yungman
5,741
294
pbuk said:
So here we go, you can also see this working at https://repl.it/repls/RealSubduedAtom. This code is missing comments of course, you might like to add them as you work through it.
C:
#include <iostream>
using namespace std;
#define EOL '\n'
int main() {
int ascii = 0;
char userSelection = 0;
while (userSelection != EOL) {
cout << "type a key and [enter]: ";
cin.get(userSelection);
ascii = userSelection;
if (userSelection == EOL) continue;
cin.ignore(255, EOL);
cout << "the first key was: " << userSelection
<< ", the ASCII is " << ascii << endl;
}
return 0;
}
Thanks for the program. I think I understand, I just want to confirm one thing.
When cin.get(userSelection), it read two characters into the keyboard buffer: first character and the '\n' as last character. The userSelection contain the first character after the cin.get() line.
Then in the line if (userSelection == EOL), This read out the next character from the keyboard buffer, which is '\n'.
Thanks for the program. I think I understand, I just want to confirm one thing.
When cin.get(userSelection), it read two characters into the keyboard buffer: first character and the '\n' as last character. The userSelection contain the first character after the cin.get() line.
No, that's not quite right. First of all the code you write does not read into a buffer, this part is done by the operating system. Also, cin is actually a line input buffer cin.get which is why you have to hit enter, rather than a keyboard buffer which reads keys straight away.
So cin.get(userSelection) waits for a character to appear in the keyboard line input buffer (which will only happen after return has been entered) and then reads one character from the buffer into userSelection which is passed by reference.
yungman said:
Then in the line if (userSelection == EOL), This read out the next character from the keyboard buffer, which is '\n'.
Does it look like this code reads anything from any input buffer?
Wouldn't break instead of continue also exit the loop cleanly in your example?
Yes it would, but breaking out of a while(true) loop is not a very understandable way to write code. Putting the termination condition up front makes it much easier to see when you want the loop to terminate.
jtbell said:
You put the user's input in two variables, a char and an int, so you could display it in both formats. Instead, you can use just the char variable to get both formats:
Code:
cout << "the first key was: " << userSelection
<< ", the ASCII is " << int(userSelection) << endl;
We call this "casting" the char variable to int.
It works the other way, too. If you have int ascii = 97;, then cout << char(ascii) displays a.
Yes this is the way I would normally do it but the OP used two variables so I kept to that. Note that you can also cast using (int) userSelection which the compiler treats exactly the same way; I prefer this because int(userSelection) looks like a function call. Note also that when you do ascii = userSelection the compiler is performing an implicit cast. With certain compiler settings, userSelection = ascii will report a warning, @yungman can you think why?
So cin.get(userSelection) waits for a character to appear in the keyboard line input buffer (which will only happen after return has been entered) and then reads one character from the buffer into userSelection which is passed by reference.
And of course your cin.ignore() ensures that, if you enter more than one character before pressing 'return', the program processes only the first one and skips over the rest.
A useful exercise for yungman: "comment out" the cin.ignore(), recompile, run, and then enter a word instead of a single character and see what happens.
#288
yungman
5,741
294
I want to know how the keyboard buffer works when using cin, cin.get and cin.ignore.
I still want to confirm about how cin.get can make it jump out of the loop with just hitting ENTER where the rest of the character, you need to enter the character, then press ENTER. Please check what I said is correct or not.
My understanding is when cin >>character, it needs to hit ENTER before it does anything. When hitting ENTER, two characters are stored in the keyboard buffer...the character and '\n'. cin read the first character, leaving the '\n' in the keyboard buffer. If cin.get() follows, it immediate read the '\n' from the last cin and treat it as a character and move on without reading the character supposed to be entered from the keyboard.
I still don't get how C++ pick which character to read in the keyboard buffer, when is it start reading, is it only read when hitting the ENTER key?
I want to know how the keyboard buffer works when using cin, cin.get and cin.ignore.
I still want to confirm about how cin.get can make it jump out of the loop with just hitting ENTER where the rest of the character, you need to enter the character, then press ENTER. Please check what I said is correct or not.
I am sorry, I can't really understand what you are saying. If you want to work out how it works the best thing is just to play with it.
yungman said:
My understanding is when cin >>character, it needs to hit ENTER before it does anything.
Correct, you won't see anything from cin until you hit enter.
yungman said:
When hitting ENTER, two characters are stored in the keyboard buffer...the character and '\n'.
As many characters as you have typed before hitting enter are in the buffer - it could be 0, 1 or many - as well as the \n (i.e. ENTER) character.
yungman said:
cin read the first character, leaving the '\n' in the keyboard buffer.
Only if it was there - if the first and only character was \n then the buffer is now empty.
yungman said:
If cin.get() follows, it immediate read the '\n' from the last cin and treat it as a character and move on without reading the character supposed to be entered from the keyboard.
Nowhere in either your code or mine is one cin.get() followed by another.
yungman said:
I still don't get how C++ pick which character to read in the keyboard buffer, when is it start reading, is it only read when hitting the ENTER key?
Not exactly. In order for the buffer to be read, two conditions must be satisfied:
the operating system must have stored characters in the buffer; this only happens when you hit ENTER
your code must try to read from the buffer; this only happens when you reach the (compiled) cin.get() statement.
Once both these conditions are satisfied, cin.get() knows that you are looking for a char type so it reads exactly one byte from the buffer. If you have only typed \n, that is what you will get and the buffer will be empty so if you immediately try to flush it your program will wait around for another character to flush. That's why I checked straight away to see if ENTER was the character received from the buffer.
Somewhere near the beginning of this thread I think I recommended codecademy. I think the way codecademy leads you through exercises would be useful. Please give it a try.
#291
yungman
5,741
294
jtbell said:
And of course your cin.ignore() ensures that, if you enter more than one character before pressing 'return', the program processes only the first one and skips over the rest.
A useful exercise for yungman: "comment out" the cin.ignore(), recompile, run, and then enter a word instead of a single character and see what happens.
Yes, I wrote a program with words reading in last name and first, then print out, then as to hit ENTER to quit or any other character to do it again:
C++:
// enter multiple data in one cin
#include <iostream>
using namespace std;
int main()
{
char LastName[21] = { '\n' }, FirstName[21] = { '\n' };
char userSelection = 'A';
do
{
cout << endl;
cout << "Enter LastName and FirstName with a space in between, then hit ENTER "<< "\n";
cin >> LastName >> FirstName;
cout << "\n";
cout << "You entered " << LastName << " " << FirstName << endl;
cout << "\n";
cin.ignore(255, '\n');// clear ENTER
cout << " Hit any character to repeat, hit ENTER to quit ";
cout << endl;
cin.get(userSelection);
} while (userSelection != '\n');
return 0;
}
It seems that in order to do exactly what you want (read a newline character from an input stream, just like any other char), C++ would have to allow for "unbuffered input streams." And C++ simply doesn't provide this capability. All I/O is via abstract streams, which could be connected to your keyboard and display, or to files, or to network sockets...
At least that's how I interpret the following discussion that I found with a Google search for "c++ unbuffered console input":
I think I remember reading similar things elsewhere years ago when I was more involved in C++ by teaching it.
There's at least one way to accomplish your ultimate goal, which is to allow the user to terminate an input loop by simply pressing <return>. You don't read to a single char, but to an std::string. And insted of using cin >>, you use the std::getline() function, which reads from an input stream (e.g. cin) until it encounters a newline. The chars up to (but not including) the newline go into the string, and the newline is discarded. To test whether the user simply pressed <return>, you test the string to see if it's empty.
Code:
#include <iostream>
#include <string>
int main ()
{
std::string choice = "go";
while (choice != "")
{
std::cout << "Enter a character, or <return> to exit: ";
std::getline (std::cin, choice);
std::cout << "You entered '" << choice << "'." << std::endl;
if (choice != "")
{
std::cout << "'" << choice[0] << "'"
<< " has the ASCII code " << int(choice[0]) << "."
<< std::endl;
}
}
return 0;
}
If the user enters more than one char before pressing <return>, this program displays all of them, but displays the ASCII code for only the first one. Exercise: modify the program so it displays the ASCII codes for all the chars that the user enters.
It seems that in order to do exactly what you want (read a newline character from an input stream, just like any other char), C++ would have to allow for "unbuffered input streams." And C++ simply doesn't provide this capability. All I/O is via abstract streams, which could be connected to your keyboard and display, or to files, or to network sockets...
No, there is no problem with reading a newline character from an input stream as you can see from my code in #278(!). The problem with @yungman's code was that after reading one character (which could be a newline) he was calling ignore() which was waiting around for another newline.
jtbell said:
There's at least one way to accomplish your ultimate goal, which is to allow the user to terminate an input loop by simply pressing <return>. You don't read to a single char, but to an std::string. And insted of using cin >>, you use the std::getline() function, which reads from an input stream (e.g. cin) until it encounters a newline. The chars up to (but not including) the newline go into the string, and the newline is discarded. To test whether the user simply pressed <return>, you test the string to see if it's empty.
Yes, std::getline() is generally more useful than cin >>. But actually neither of these are very useful - interactive console programs aren't really a thing in C++; if I were @yungman I'd drop it and move on.
#294
yungman
5,741
294
I run into problem building the solution. I got an error message
C++:
// Read and write to file
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ofstream outputFile;
outputFile.open("demofile.txt");
cout << "Now writing data to the demofile.txt" << endl;
outputFile << "Bach\n";
outputFile << "Beethoven\n";
outputFile << "Mozart\n";
outputFile << "Schubert\n";
outputFile.close();
cout << "Done " << endl;
cout << endl;
return 0;
}
I triple checked, I type everything right straight out from the book. Please help
Thanks
Last edited:
#295
sysprog
2,617
1,796
The error message says that your path name length plus the generated file name length exceeds the 250 character limit. You can reduce the length by reducing the number or lengths of the concatenated components. For example, the generated file name includes your project name, so using a shorter project name would contribute to staying within the limit.
The error message says that your path name length plus the generated file name length exceeds the 250 character limit. You can reduce the length by reducing the number or lengths of the concatenated components. For example, the generated file name includes your project name, so using a shorter project name would contribute to staying within the limit.
I don't understand, it is a new file as you see created by the program named "demofile.txt". It only contain 4 words( 4 names). It is less than 50 characters if you count them all including the name of the file.
thanks
EDIT: I went in and deleted 3 out of 4 names, still fail.
Last edited:
#297
sysprog
2,617
1,796
yungman said:
I don't understand, it is a new file as you see created by the program named "demofile.txt". It only contain 4 words( 4 names). It is less than 50 characters if you count them all including the name of the file.
thanks
Please look at the file name in the error message ##-## it's between quotation marks, and it's about 100 characters long. The file name that the message is reporting is the VS-generated name of a debug file. The fully-qualified name includes the path name, which includes everything in the directory structure from the drive letter to the most deeply nested current subdirectory. It also includes the whole of your project name, which lengthily describes the program, instead of just being something like P002. You can also rename directories to something shorter, e.g. abbreviate Microsoft to MS, and Visual Studio to VS. The full path character string from drive letter to current subdirectory doesn't appear in the message, so I can't see all the reductions you could do to reduce its length.
Please look at the file name in the error message it's between quotation marks, and it's about 100 characters long.
I think I copied it correctly here:
Debug\3.29 rea.63bf1643e.tlog\3.29 read write to file ifstream ofstream open close.lastbuildstate
The full path name is probably much longer, as sysprog described.
I suspect that "3.29 read write to file ifstream ofstream open close" is the name that yungman chose for the project or something related to it. It looks like an exercise number (3.29) followed by keywords describing the program to help him find it later. "lastbuildstate" looks like it might be a suffix generated by Visual Studio for internal purposes.
I suggest that he go to wherever he entered that name, and replace it with a much shorter one, maybe something like "3.29 fstream".
I'm just guessing here, because I've never used Visual Studio.
I copied and pasted the program as shown, into a .cpp file on my iMac. My compiler (g++) compiles it successfully, and it produces the expected output.
Debug\3.29 rea.63bf1643e.tlog\3.29 read write to file ifstream ofstream open close.lastbuildstate
The full path name is probably much longer, as sysprog described.
jtbell said:
I'm just guessing here, because I've never used Visual Studio.
I agree with @jtbell and @sysprog that the filename of the source code is the problem.
I copied the program verbatim and ran it through VS, and it worked as expected.
#300
yungman
5,741
294
I solved the problem. It is the name of my whole project I created! I tried to make it more descriptive on the name so in the future when I read the name, I can know what the program does. This is old age for you, can't remember after a while. 3.29 doesn't mean anything to me later on. I did a lot of exercise with the first book and I don't remember what they are until I open them. So for the Gaddi's book I give descriptions...AND it's too long!
Now, I deleted the whole project, saving only the source.cpp. Create a new project called 3.29 ofstream and it compiled.
VS has strange things, I found the demofile.txt that created by the program now. Also VS is strange, I before I end up deleting the whole project, I tried to change the name of EVERY file inside, it's like every time I navigate around, I see new names that I missed the first time! It just did not work trying to rename the files, finally, I had to take out the source.cpp, then try to delete. Then I had to close all the other projects ( I had the ifstream project opened in another VS program) in order to even create the new 3.29 ofstream.
Now my other ifstream doesn't read the demofile.txt. That's another story for another day. I want to work on that first.