The discussion centers on the efficiency of using arrays versus individual boolean variables in programming. It suggests that individual variables may offer faster access due to direct addressing, while arrays may benefit from memory caching. The initialization of an array with multiple values is clarified, explaining that using a single initializer only sets the first element, leaving others at zero. Additionally, the conversation highlights the limitations of fixed-size arrays, advocating for dynamic arrays or vectors for user-defined sizes. The complexities of user input handling for dynamic arrays are also addressed, suggesting the use of sentinel values for easier input management.
No, it isn't. After the assignment int *ptr = List, the variable ptr points to the first int in the array. So *ptr at that point is not List; it's the first int in the array, which is of type int, not type "array of int", which is the type of List.
List has type "array of int", which the compiler treats as a pointer to the initial item in the array, so it's the same type to the compiler as "pointer to int",
More precisely, I would say "const pointer to int", because, as you note,
PeterDonis said:
the address List points to can't be changed--it always points to the first int in the array.
This is where I am confused. *ptr=List=&List[0] which is the starting address of List[]. ptr is not equal to &List[0].
Yes, you are confused, as well as mistaken. In its declaration ptr is initialized with List, which is the same as &List[0].
The initialization could just as well have been [B]int * ptr = &List[0];[/B], but I chose the shorter form.
yungman said:
passAddr() passing the ADDRESS of ptr in line 4 in main.
A pointer represents an address, so the address of a pointer is a pointer to a pointer to an int, in this case.
yungman said:
BUT in the function definition: void passAddr(int**); that means it is passing a pointer to pointer variable ( like int**pptr). But in main, it pass as &ptr, the address of ptr. they are not the same type even thought at the end, it is the same. Can you explain?
The type of &ptr is pointer to pointer to int.
yungman said:
Actually I prefer to pass pointer as reference ( or pass reference pointer, I still not quite sure) to function. This is more in line with passing any variable as reference to function by declaring void func(int&). It is easier than func(int**).
Like I said before, I've never seen any C++ book with function parameters that mix references and pointers. This should suggest something to you. Sure, you could probably do it, and get something to work, but why? You're mixing together two concepts that really don't belong together, and are obviously confusing to you.
yungman said:
It just declare int func() to return the int pointer.
No. int func() means that func returns an int value, not a pointer.
yungman said:
I insisted in learning passing pointer as reference and/or pointer to pointer.
It's really not a good idea to pass a pointer as a reference parameter. You haven't been able to make it work, so that should be a clue to you. I've shown you an example with double indirection with a parameter of type int**. Before going off into weirdness as you are trying to do, see if you can grasp what my example is doing.
#205
yungman
5,741
294
PeterDonis said:
No, it isn't. After the assignment int *ptr = List, the variable ptr points to the first int in the array. So *ptr at that point is not List; it's the first int in the array, which is of type int, not type "array of int", which is the type of List.
I tried and broke up int *ptr = List to int*ptr;
Mark44 said:
Yes, you are confused, as well as mistaken. In its declaration ptr is initialized with List, which is the same as &List[0].
The initialization could just as well have been [B]int * ptr = &List[0];[/B], but I chose the shorter form.
A pointer represents an address, so the address of a pointer is a pointer to a pointer to an int, in this case.
The type of &ptr is pointer to pointer to int.
Like I said before, I've never seen any C++ book with function parameters that mix references and pointers. This should suggest something to you. Sure, you could probably do it, and get something to work, but why? You're mixing together two concepts that really don't belong together, and are obviously confusing to you.
No. int func() means that func returns an int value, not a pointer.
It's really not a good idea to pass a pointer as a reference parameter. You haven't been able to make it work, so that should be a clue to you. I've shown you an example with double indirection with a parameter of type int**. Before going off into weirdness as you are trying to do, see if you can grasp what my example is doing.
So it's really not advisable to pass pointer as reference pointer, just use function to return the pointer instead as in the book?
the programs that pass pointer as reference seems to work, but they are just funky. I never feel comfortable. It's one thing that it's hard, but if it's not advisable to use at all, then it's no point to pursue anymore.
The first code snippet first declares ptr, and then assigns the address that List represents to it.
The second code snippet declares and initializes ptr to that same address.
The first code snippet is a declaration; the second is a definition.
yungman said:
So it's really not advisable to pass pointer as reference pointer, just use function to return the pointer instead as in the book?
1) It's really not advisable to have a function parameter that is the reference of a pointer.
2) Technically, a void function does not return a value. In the example I posted (post # 196), passAddr() is a void function, so it doesn't "return" anything. If you want a function the modify the value of a pointer, use double indirection; i.e., <type>**, as in that example.
It would be good for you to play with that example, and see what it does using the VS debugger.
#207
yungman
5,741
294
Mark44 said:
There's no real difference between this:
C++:
int * ptr;
ptr = List;
and this:
C++:
int * ptr = List;
The first code snippet first declares ptr, and then assigns the address that List represents to it.
The second code snippet declares and initializes ptr to that same address.
The first code snippet is a declaration; the second is a definition.
1) It's really not advisable to have a function parameter that is the reference of a pointer.
2) Technically, a void function does not return a value. In the example I posted (post # 196), passAddr() is a void function, so it doesn't "return" anything. If you want a function the modify the value of a pointer, use double indirection; i.e., <type>**, as in that example.
It would be good for you to play with that example, and see what it does using the VS debugger.
Another word I have no idea what you mean....indirection.
Honest, my biggest problem learning C++ is the names. I have no idea what the names meant. Also, I don't get use to the symbols, like '&' that really tripped me up. In calculus, physics and electronics, each symbol is chosen to have very specific meaning and they don't use one symbol for totally different meanings ( at least not I can think of this moment). When I see '&', I take it very literal. Until pointers, I really have no issue understanding all the chapters, everything I got tripped are names.
I learned early on int x; &x is the address of x. immediately when I saw void func(int& x) it made sense you pass the address of x as parameter so you can change the value of x in the function. It actually worked for all this time until today you mentioned it.
Like I could have guessed 100 times and I still won't get the meaning of dereferencing. Where did people come up with all these words, it's like C++ has it's only lingo. I hope other languages like Java or Python don't have their own unique lingo, I'd be in trouble learning CS and I might as well give up before I waste too much time.
I might be getting old now compare to before. I studied electronics, RF, electromagnetics, multi-variable calculus, partial differentiations all on my own. I never took classes in any of these, all studied on my own and used in my career. Some are really hard to understand, but I never got tripped up this bad like in C++. About '&' today, it's eye opening. Never even stop and think when it worked so right as address and made sense until today. That's scary. Things look so right and it's so wrong.
Another word I have no idea what you mean....indirection.
Indirection means using a pointer to get access indirectly, to some memory location. If you have a pointer to a pointer to an int (the type int **), that is double indirection.
yungman said:
Honest, my biggest problem learning C++ is the names. I have no idea what the names meant.
In any field of study, there is some basic terminology that is used. If you don't know what the basic terms mean, you won't get far in that field.
yungman said:
I learned early on int x; &x is the address of x. immediately when I saw void func(int& x) it made sense you pass the address of x as parameter so you can change the value of x in the function.
No, that's not what the parameter declaration int& x means. It is not the address of x: it is a reference to x. A function with this signature, void func2(int * x), is passing the address of x. This is why several people have told you that you aren't understanding the difference between a reference parameter and a pointer parameter.
This goes back to the importance of "learning the names," understanding the meaning of basic terms.
yungman said:
It actually worked for all this time until today you mentioned it.
Except when it didn't work, in several examples of your code that wasn't working.
#209
yungman
5,741
294
ha ha, before today, I looked at pointer of a pointer **ptr as *(*ptr) where it makes sense it's *(...) pointer of (*ptr) pointer. I bet it's dead wrong again!
No, the really hard subjects like electromagnetics, RF and partial differentiation do NOT have confusing symbols and names that I know of after years of studying and working. It's the concept that is so hard to understand, not the English. English wise, it's high school level. You don't get tripped by the words.
ha ha, before today, I looked at pointer of a pointer **ptr as *(*ptr) where it makes sense it's *(...) pointer of (*ptr) pointer. I bet it's dead wrong again!
**ptr and *(*ptr) mean exactly the same thing, although the name you chose is somewhat confusing.
Here's an example that uses double indirection, with names that are more suggestive of the values they will hold.
C++:
#include <iostream>
using std::cout;
using std::endl;int main()
{
int val = 23;
int* pInt = &val; // pInt is a pointer to an int
int** ppInt = &pInt; // ppInt is a pointer to a pointer to an int
cout << "ppInt == " << ppInt << endl;
cout << "*ppInt == " << *ppInt << endl;
cout << "**ppInt == " << **ppInt << endl;
}
Here's the output from one run. Different runs will usually list different addresses.
If I dereference ppInt, I get the address of val. If I dereference ppInt twice, I get the number stored in val. Access via a pointer is called indirection. If you dereference a pointer twice, this is called double indirection.
Here's a graphical representation of the pointers and their relationships. Each box represents one of the variables. In each box are the variable's name (upper left), its address in memory (upper right), and the value stored at the memory location (bottom).
The ? in the ppInt box means that I don't know its address, although it would be easy enough to add a line of code in the program to get it. Notice that the value in the ppInt box is the same as the address in the pInt box, and that the value in the pInt box is the same as the address of val. So ppInt "points to" pInt, and pInt "points to" val.
BTW, this scheme of representing variables with boxes that contain their names, addresses, and values is something that I came up with independently, early on in teaching C and C++, although I've noticed one or two books that use something similar since then.
It's worth mentioning that one application of double indirection is a binary search of an ordered list. A function that is passed two pointers to different locations in the list can find the midpoint of the list, and determine whether the search target is in one or the other half of the list. The function can modify one of the passed pointers, and then call itself recursively to resume the search.
This is one of the things that you would learn in studying data structures and algorithms.
#212
yungman
5,741
294
Hi Mark44
Thank you so much to have the patience to explain these. I actually copied your last few posts and print it out to read line by line and correct my notes. Still working on these. Just want to acknowledge you first, I'll be back.
#213
yungman
5,741
294
Hi
I am still going through the chapter, I even read the chapter of pointers from my former book to look at another perspective. I have a program that runs. I just want to verify whether I am correct:
C++:
// Dynamic memory with pointer in function
#include <iostream>
using namespace std;
void getValue(int**, int);// function receive pointer to a pointer.
int main()
{
int count, size = 5;
int* ptr;// Initialize point ptr.
getValue(&ptr, size); // Pass the ADDRESS of pointer ptr.
cout << " Back in main, array pointed by ptr = {";
for (count = 0; count < (size - 1); count++)
{
cout << *(ptr + count) << " ";
}
cout << *(ptr + (size - 1)) << " }\n\n";
delete[] ptr;
return 0;
}
void getValue(int** pt, int size)//receive pointer to pointer pt.
{
int count;
int *Ar = new int[size];//Ar is a pointer to allocate memory
//Ar is the address of the first element
for (count = 0; count < size; count++)
{
cout << " Enter number " << (count + 1) << " = ";
cin >> *(Ar + count); cout << "\n";
}
*pt = Ar;//pt is a pointer to pointer, *pt dereference pt which is a pointer.
cout << " In getValue, array pointed by pt = {";
for (count = 0; count < (size - 1); count++)
{
cout << *(*pt + count) << " ";// first * dereference, *pt is address of the start of array.
// count is to go the number of element down from first element.
}
cout << *(*pt + (size - 1)) << " }\n\n";
}
I want to verify whether my understanding is correct 1) when declare int**pt. This declare pt is a pointer to pointer. In line 30, *pt means dereference the pointer-to-pointer ptr, which give the address of the int variable that it is pointing to(in this case is the first element of the 5 element memory). in another words, '*' is dereference of ( pointer-to-pointer ptr).
2) Line 34, *(*pt + count) means dereferencing (*pt+count ). (*pt+count ) is the address of the first element of the memory + number of elements down in address(count). eg, if count =2, then (*pt + count) points to the 3rd element of the memory.
3) Line 10: getValue(&ptr, size) is to pass the ADDRESS of the pointer ptr to the function. Which is the same kind as pointer to a pointer declared in the function.
4) Line 14, *(ptr + count) is dereference (ptr + count). ptr is a pointer to the first element of the memory allocated. (ptr + count) points the the number of elements down from the first element specified by count.
I hope I got these correct, please let me know.
My biggest confusion is for int**pt, pt without any '*' actually mean pt is a pointer-to-pointer variable. The *pt is DEREFERENCING the pointer-to-pointer pt. Which is the address it's pointing to.
Your program looks pretty good, but there are a couple of very minor nits.
Line 8: count is a misleading name. You're actually using it as an index in your array. The name i would be perfectly fine in this case, or idx, or index.
Line 9: int* ptr;// Initialize point ptr.
The comment is not correct. All that's happening here is that ptr is being declared, not initialized. When a variable is initialized, it is given a value. At this point ptr contains some random address.
yungman said:
1) when declare int**pt. This declare pt is a pointer to pointer. In line 30, *pt means dereference the pointer-to-pointer ptr, which give the address of the int variable that it is pointing to(in this case is the first element of the 5 element memory). in another words, '*' is dereference of ( pointer-to-pointer ptr).
Yes. To help you out, think of the declaration int**pt in two parts -- the type being declared: int**, pointer to pointer to int, and the name for that type: pt. It's important to keep in mind the type that the pointers ultimately point to - omitting this was the source of much confusion for you earlier.
After the name ptr has been declared, you can dereference it once or twice. ptr -- pointer to pointer to an int (i.e., the address of the address of an int) *ptr - pointer to an int (i.e., the address of an int) **ptr - the int being pointed to.
See the drawing I attached in post #210.
yungman said:
2) Line 34, *(*pt + count) means dereferencing (*pt+count ). (*pt+count ) is the address of the first element of the memory + number of elements down in address(count). eg, if count =2, then (*pt + count) points to the 3rd element of the memory.
Yes, although as mentioned already, I would write this as *(*pt + index) or similar name.
It's important to understand that pointer arithmetic is being used here, so if index happens to be 2, for example, the above actually adds 8 (= 2 * sizeof(int)) to the address in *pt.
yungman said:
3) Line 10: getValue(&ptr, size) is to pass the ADDRESS of the pointer ptr to the function. Which is the same kind as pointer to a pointer declared in the function.
Right
yungman said:
4) Line 14, *(ptr + count) is dereference (ptr + count). ptr is a pointer to the first element of the memory allocated. (ptr + count) points the the number of elements down from the first element specified by count.
Yes.
yungman said:
My biggest confusion is for int**pt, pt without any '*' actually mean pt is a pointer-to-pointer variable.
See my explanation in item 1.
#215
yungman
5,741
294
Thank you Mark44. I spent two days reading from another book, copied your response and read them line by line. I think I finally got it. It is very tricky, it's the names and meaning of symbols that tricked me. It's so easy to interpret it wrong and they work "most" of the time, so close but totally wrong. I even copied your program and called it Mark44 to play with it and add something more in it.
C++:
//Mark44 pointers
#include <iostream>
using namespace std;
void passAddr(int**);
int main()
{
int List[] = { 1, 3, 5, 7, 9 };
int* ptr; // Initialize ptr with the address of List, which is itself a kind of pointer.
ptr = List;
cout << " address of ptr = " << ptr << "\n\n";
cout << "Before call to passAddr(), *ptr == " << *ptr << "\n\n";
passAddr(&ptr); // Pass the address of the pointer to the first element of the array.
cout << "After call to passAddr(), *ptr == " << *ptr << " *(List + 2) = " << *(List + 2) << "\n\n";
ptr = ptr + 2; // from passAddr() and ptr +2, total is ptr + 4. therefore *ptr = 9
cout << "After ptr = ptr + 2, *ptr == " << *ptr << "\n\n";
char vec = 'A';
char* ptc; ptc = &vec;
cout << " *ptc = " << *ptc << " ptc = " << ptc << " &vec = " << &vec << "\n\n";
// somehow, cout << ptc and cout &vec give funny display.
return 0;
}
void passAddr(int** pptr)
{
cout << " address of pptr = " << pptr << " *pptr = " << *pptr << "\n\n";
*pptr += 2; // pptr is a pointer to a pointer. *pptr = address of first element of array
// +2 move pptr to point to 3rd element of array
cout << " **pptr = " << **pptr << "\n\n";// after *pptr +=2, **pptr = *(*pptr) = 5, double indirection
}
Attached is my corrected notes on Chapter 9.
Well, I want to stimulate my mind studying C++, this sure shake out a lot of rust! I am glad to pick learning computer language instead of staying in the comfort zone of electronics. No matter what project I pick to do in electronics, it's just add onto the experience, it doesn't really challenge the mind. This is turning everything up side down and really shake it up.
I believe that it's very important as I get old to keep both my mind and body in shape. You don't use it, you lose it. The older you get, the faster you lose it and you need to work harder to keep it. I spend a lot of time on both now a days, no point of living long if I am disable and lost my mind. This is my way of keeping young!
I believe that it's very important as I get old to keep both my mind and body in shape.
Absolutely. Part of the reason I'm still teaching is to help keep my mind in shape. And I still regularly go on strenuous backpack trips even though I just turned 76.
Here are a few comments on your code.
Lines 9 and 10:
int* ptr; // Initialize ptr with the address of List, which is itself a kind of pointer.
ptr = List;
The above is fine, but instead of doing a declaration (line 9) followed by an assignment (line 10), you could do it with a definition (declaration + initialization), like this:
C++:
int* ptr = List;
Same for line line 19, which you could do like this:
C++:
char* ptc = &vec;
In line 21 you have this comment:
Code:
// somehow, cout << ptc and cout &vec give funny display.
You asked about this before. It's because the << operator assumes from your declarations, that *ptc and &vec are not just single characters, but the first characters of C-style strings. However, they are not C-style strings because they aren't null-terminated. When inserted into the cout stream, you get the first character plus all the characters until a null is encountered.
#217
Jarvis323
1,247
988
If you want to use the C way to print, you can do this:
C:
#include <cstdio>
int main() {
const char * cs = "hello";
std::printf( "%p \n", cs ); // %p is a placeholder with format specifier to print as a pointer, \n means newline
std::printf( "%s \n", cs ); // %s specifies print as a c-string
}
It's probably more common to print c-strings than char pointers, and C++ hides the format specifier which would let you differentiate.
#218
yungman
5,741
294
Mark44 said:
Absolutely. Part of the reason I'm still teaching is to help keep my mind in shape. And I still regularly go on strenuous backpack trips even though I just turned 76.
Here are a few comments on your code.
Lines 9 and 10:
The above is fine, but instead of doing a declaration (line 9) followed by an assignment (line 10), you could do it with a definition (declaration + initialization), like this:
C++:
int* ptr = List;
Same for line line 19, which you could do like this:
C++:
char* ptc = &vec;
In line 21 you have this comment:
Code:
// somehow, cout << ptc and cout &vec give funny display.
You asked about this before. It's because the << operator assumes from your declarations, that *ptc and &vec are not just single characters, but the first characters of C-style strings. However, they are not C-style strings because they aren't null-terminated. When inserted into the cout stream, you get the first character plus all the characters until a null is encountered.
Thanks for the reply.
I thought even though declaration char*ptc, ptc and &vec are all addresses that can be displayed as Hex.
Good for you in staying active physically too. It makes a huge difference. People are like cars, when the car is new, it can take a lot of neglect and it will run perfect for a few years, but after 5 or 6 years, everything will catch up. A 40 years old car can run like new if it is well maintained. Me and my wife spend a lot of time exercise in the gym, she is 75, she just had the second hip replaced 3 weeks ago, she's off the cain, up and down the stairs and out shopping already. It's because she is in shape. She like to walk, that really did her in on her hips, her walk was like slow jogging and she walk 2 miles 6days a week. That's why she had two hip replacement...Too much of a good thing! Kept telling her don't do it 6 days a week, she didn't listen. As I get old, I do it hard, but with plenty of rest in between. 2 days of weight lifting and 2 days of kick boxing on heavy bags at home, with plenty of rest in between...Now is C++ for the brain! good thing with the brain, it doesn't need rest and day off.
#219
yungman
5,741
294
Jarvis323 said:
If you want to use the C way to print, you can do this:
C:
#include <cstdio>
int main() {
const char * cs = "hello";
std::printf( "%p \n", cs ); // %p is a placeholder with format specifier to print as a pointer, \n means newline
std::printf( "%s \n", cs ); // %s specifies print as a c-string
}
It's probably more common to print c-strings than char pointers, and C++ hides the format specifier which would let you differentiate.
thanks, I have not learn this yet. I'll learn it when the time comes.
Now I move on to chapter 10, characters, strings. the Character part is so boring! Checking inalpha, inlower, indigit.....I am falling asleep just typing the program!
I am sighting myself up to go through how to change from lower case to upper case! That's the reason I am here shooting the breeze instead of working on the program!
These are actually isalpha(), islower(), isdigit() and so on. They are all holdovers from C, where their declarations were in ctype.h
yungman said:
I am sighting myself up to go through how to change from lower case to upper case!
That's easy to do without any library functions. To convert from lower case to upper case, just subtract 32 from each character's ASCII code. To go the other way, from upper case to lower case, just add 32.
Of course, this assumes that you're using the code page for English, and one-byte characters. Changing from upper- to lower case in other languages (and code pages) and vice-versa is more complicated.
#221
yungman
5,741
294
I am glad those upper and lower case stuffs only lasted 5 or 6 pages. I am moving onto String Literal, C-Strings. I have a question I am no able to nail it. What is String Literal and C string?
C++:
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
char St[] = "This is a test";//String Literal, length = 15
cout << " Enter sentence: "; cin.get(St, 15);//can have space.
cout << St << "\n\n";
return 0;
}
You see I declare and initialized a String Literal with "This is a test". BUT as you see, I can change the sentence as long as I don't get over 14 characters ( + '\0'). What is the point of String Literal, I might as well declare St[20] = {'\0'} and then cin.get(St, 20) to put in the sentence. Only thing advantage is you can use cout << "This is a test"; that doesn't involve one extra array St[].
I am still looking for difference between cin.get(St,20) vs cin.getline(St,20). They work same so far for me.
I am glad those upper and lower case stuffs only lasted 5 or 6 pages. I am moving onto String Literal, C-Strings. I have a question I am no able to nail it. What is String Literal and C string?
A string literal is an array of characters surrounded by double quotes -- e.g., "This is a test" is a string literal. The word literal is a synonym of constant.
A C-string is a null terminated array of characters.
yungman said:
C++:
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
char St[] = "This is a test";//String Literal, length = 15
cout << " Enter sentence: "; cin.get(St, 15);//can have space.
cout << St << "\n\n";
return 0;
}
You see I declare and initialized a String Literal with "This is a test". BUT as you see, I can change the sentence as long as I don't get over 14 characters ( + '\0'). What is the point of String Literal, I might as well declare St[20] = {'\0'} and then cin.get(St, 20) to put in the sentence. Only thing advantage is you can use cout << "This is a test"; that doesn't involve one extra array St[].
There's no point in initializing St.
It would be clearer to do this:
C++:
char St[15];
cout << " Enter sentence of 14 or fewer characters: ";
cin.get(St, 15);//can have space.
yungman said:
I am still looking for difference between cin.get(St,20) vs cin.getline(St,20). They work same so far for me.
Both functions have multiple overloads, with six overloads for get() and two overloads for getline(). The basic difference between the two as I understand things is that get() doesn't store the termination character (which you can specify), while getline() does store this character.
By default, the termination character is \n, but you can specify something different as a 3rd parameter in either function.
A string literal is an array of characters surrounded by double quotes -- e.g., "This is a test" is a string literal. The word literal is a synonym of constant.
A C-string is a null terminated array of characters.
There's no point in initializing St.
It would be clearer to do this:
C++:
char St[15];
cout << " Enter sentence of 14 or fewer characters: ";
cin.get(St, 15);//can have space.
yungman said:
I am still looking for difference between cin.get(St,20) vs cin.getline(St,20). They work same so far for me.
Both functions have multiple overloads, with six overloads for get() and two overloads for getline(). The basic difference between the two as I understand things is that get() doesn't store the termination character (which you can specify), while getline() does store this character.
By default, the termination character is \n, but you can specify something different as a 3rd parameter in either function.
I have to fix your post to be readable, I don't understand what is overload and when I follow the link, I have not learn istream yet, so the link doesn't help me in understand better.
I put in a quote end tag where I should have put in a code end tag. I've fixed things in my post and in what you quoted.
yungman said:
I don't understand what is overload
In C++, but not C, you can have multiple functions with the same name, but with different sets of arguments. For example, you could have multiple functions named print, with each designed to print a different type of value.
This saves you from having to come up with a unique name for each function. At compile time, the compiler chooses amongst these functions based on the type of the argument.
#225
yungman
5,741
294
Mark44 said:
I put in a quote end tag where I should have put in a code end tag. I've fixed things in my post and in what you quoted.
In C++, but not C, you can have multiple functions with the same name, but with different sets of arguments. For example, you could have multiple functions named print, with each designed to print a different type of value.
This saves you from having to come up with a unique name for each function. At compile time, the compiler chooses amongst these functions based on the type of the argument.
I did not know that!
So overload is how many times you can use the same name with different sets of arguments?
So overload is how many times you can use the same name with different sets of arguments?
Sort of. It's not how many times. In my example the print function had four overloads.
#227
yungman
5,741
294
I have an issue with this program that I can't fix. I copied the code from the book, everything looks right. I got an warning error and it won't run. I only typed in "This is " into St1 and "A test" into St2, way under the size. At the beginning, I chose to run it anyway and it print out the input but not after strncat. Now, it won't even do anything.
C++:
//Function for strings
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
int maxCh;
char St1[50], St2[50];
cout << " Enter a sentence 1: ";
cin.getline(St1, 50); cout << "\n\n";
cout << " You entered " << St1 << "\n\n";
cout << " Enter a sentence 2: ";
cin.getline(St2, 50); cout << "\n\n";
cout << " You entered " << St2 << "\n\n";
maxCh = sizeof(St1) - (strlen(St1) + 1);
strncat(St1, St2, maxCh);
cout << " After strncat, St1 = " << St1 << "\n\n";
return 0;
}
Here's what's wrong with your code.
Microsoft deprecated several of the string manipulation functions several versions of VS ago. Among them are strcpy(), strcat(), and others, including strncat(). The reason for this is that they are unsafe, and using them could lead to buffer overruns, which hackers could use to hack into a computer that is running a program using these functions. Back in about 2004, Microsoft spent a lot of money on training for everyone , and I mean everyone, in the Windows division (about 7500) people to take training to raise awareness on the problems with security.
In your program, this will work - strncat_s(St1, 50, St2, 25);
Here, St1 is the destination - it has to have enough space to hold both strings.
50 is the size of the destination buffer.
St2 is the source string.
25 is the number of characters to concatenate onto the source.
Normally it's bad practice to have "magic numbers" like 50 and 25 above. It's much better to use constants or variables that get computed, but I put something together in a hurry.
C++:
//Function for strings
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
int maxCh;
char St1[50], St2[50];
cout << " Enter a sentence 1: ";
cin.getline(St1, 50); cout << "\n\n";
cout << " You entered " << St1 << "\n\n";
cout << " Enter a sentence 2: ";
cin.getline(St2, 50); cout << "\n\n";
cout << " You entered " << St2 << "\n\n";
maxCh = sizeof(St1) - (strlen(St1) + 1);
strncat(St1, St2, maxCh);
cout << " After strncat, St1 = " << St1 << "\n\n";
return 0;
}
Last edited:
#229
yungman
5,741
294
Mark44 said:
Here's what's wrong with your code. 1. Your definition of maxCh is wrong. As you have it, maxCh will be set to -1.
Microsoft deprecated several of the string manipulation functions several versions of VS ago. Among them are strcpy(), strcat(), and others, including strncat(). The reason for this is that they are unsafe, and using them could lead to buffer overruns, which hackers could use to hack into a computer that is running a program using these functions. Back in about 2004, Microsoft spent a lot of money on training for everyone , and I mean everyone, in the Windows division (about 7500) people to take training to raise awareness on the problems with security.
In your program, this will work - strncat_s(St1, 50, St2, 25);
Here, St1 is the destination - it has to have enough space to hold both strings.
50 is the size of the destination buffer.
St2 is the source string.
25 is the number of characters to concatenate onto the source.
Normally it's bad practice to have "magic numbers" like 50 and 25 above. It's much better to use constants or variables that get computed, but I put something together in a hurry.
C++:
//Function for strings
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
int maxCh;
char St1[50], St2[50];
cout << " Enter a sentence 1: ";
cin.getline(St1, 50); cout << "\n\n";
cout << " You entered " << St1 << "\n\n";
cout << " Enter a sentence 2: ";
cin.getline(St2, 50); cout << "\n\n";
cout << " You entered " << St2 << "\n\n";
maxCh = sizeof(St1) - (strlen(St1) + 1);
strncat(St1, St2, maxCh);
cout << " After strncat, St1 = " << St1 << "\n\n";
return 0;
}
Thanks for the reply. I have to read the rest in detail.
I don't understand your first point that maxCh will be set to -1.
in maxCh = sizeof(St1) - (strlen(St1) + 1);sizeof(St1) = 50. strlen(St1) depends on what I enter into St1. Like I said in my post, I enter "This is " for St1. This is 8 characters total ( including space). With the '\0', it's 9 character. maxCh should equal to 50 - 8 -1 = 41. I input to St2 = "a test". Total of St2 is 6characters. There should be plenty of room and not a chance to overrun.
Note that std::string automatically allocates enough new memory to accommodate the result of any string operation. There's no need to deal with buffer-overrun issues.
(Note getline() for std::string is different than for char arrays.)
Code:
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string St1, St2;
cout << " Enter a sentence 1: ";
getline (cin, St1); cout << "\n\n";
cout << " You entered " << St1 << "\n\n";
cout << " Enter a sentence 2: ";
getline (cin, St2); cout << "\n\n";
cout << " You entered " << St2 << "\n\n";
St1 = St1 + St2; // St1 automatically expands as needed
// Or you can use St1 += St2;
cout << " After concatenation, St1 = " << St1 << "\n\n";
return 0;
}
Last edited:
#232
yungman
5,741
294
jtbell said:
Note that std::string automatically allocates enough new memory to accommodate the result of any string operation. There's no need to deal with buffer-overrun issues.
(Note getline() for std::string is different than for char arrays.)
Code:
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string St1, St2;
cout << " Enter a sentence 1: ";
getline (cin, St1); cout << "\n\n";
cout << " You entered " << St1 << "\n\n";
cout << " Enter a sentence 2: ";
getline (cin, St2); cout << "\n\n";
cout << " You entered " << St2 << "\n\n";
St1 = St1 + St2; // St1 automatically expands as needed
// Or you can use St1 += St2;
cout << " After concatenation, St1 = " << St1 << "\n\n";
return 0;
}
Thanks, I am reading strings right now, I just want to follow the book, learn as much as I can of each topic.
#233
yungman
5,741
294
Mark44 said:
My mistake -- I read your code too quickly, thinking it said sizeof(St1) - (sizeof(St2 + 1)).
It's gettin' late for me...
I made that mistake when I first read this in the book also.
I read your link on strncat_s, it is difficult to understand as they use stuffs I don't know. I actually followed your explanation and it works. This is the program after changing to strncat_s.
C++:
//Function for strings
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
int maxCh;
const int size1 = 50;
char St1[size1+21], St2[size1];
cout << " Enter a sentence 1: ";
cin.getline(St1, size1); cout << "\n\n";
cout << " You entered " << St1 << "\n\n";
cout << " Enter a sentence 2: ";
cin.getline(St2, size1); cout << "\n\n";
cout << " You entered " << St2 << "\n\n";
maxCh = sizeof(St1) - (strlen(St1) + 1);
strncat_s(St1, size1, St2, 20);
cout << " After strncat, St1 = " << St1 << "\n\n";
strcpy_s(St1, 5, St2);
cout << " St1 after copying from St2 to St1 when set max copy 5 char = " << St1 << "\n\n";
return 0;
}
I changed using const int size1 instead of a number and I change the size of St1 = (size1+21) in line 10 and use strncat_s(St1, size1, St2, 20);
I even experimented with strncpy_s. This one can still gives warning when I set the middle integer to 5 and St2 is larger. In my case St2="a test"(6 char). It will copy the whole "a test" over, but gave me a warning:
Like I said, I searched on line, There are very few and I couldn't understand them. So I just kind of guessing how strncpy_s works.
These must not be that popular as Jtbell said, use string instead to avoid all these problems.
thanks
#234
yungman
5,741
294
I want to confirm is C=String actually a string of characters stored in character array. That it is NOT a String. That C-String is subject to a lot of limitation like the size and all seen in strcat, strcpy. Even strncat_s and strncpy_s is NOT very convenient. Why are we still using C-String given all these limitation. Just use String Class.
I have been trying to search on line, what is size_t? I read on line and I still don't understand, they said it's like sizeof but with unlimited size. What is that? I looked at the index of two books and couldn't find it.
It is found in size_t found = St1.find(St2); where I want to find string St2 inside St1. I want to do the same thing like strstr in C-String.
Also what is errno_t? Couldn't find it in both books. A lot of this and size_t pop up around the search of strcat, strcpy. like the following code, I have no idea what these mean. Thereby not very fruitful searching on web.
:
errno_t _strncat_s_l(
char *strDest,
size_t numberOfElements,
const char *strSource,
size_t count,
_locale_t locale
);
I want to confirm is C=String actually a string of characters stored in character array.
I wrote this in post #222:
Mark44 said:
A C-string is a null terminated array of characters.
yungman said:
That it is NOT a String. That C-String is subject to a lot of limitation like the size and all seen in strcat, strcpy. Even strncat_s and strncpy_s is NOT very convenient. Why are we still using C-String given all these limitation. Just use String Class.
A C string is different from a C++ Standard Template Library string. This is one of the more confusing aspects in C++, as it combines how character strings are dealt with in C together with a completely new and different concept in C++.
yungman said:
I have been trying to search on line, what is size_t? I read on line and I still don't understand, they said it's like sizeof but with unlimited size.
It's a type that is Microsoft-specific, that represents the type of return value. As far as I know, it's just an int. The important thing is to recognize from the return value whether the function call succeeded or not.
This thread has grown very long, so I'm closing it. @yungman, when you have more questions about a specific topic, please start a new thread, but don't make the thread a grab-bag of questions about different topics.
I'm sure that a lot of your questions have been answered in this thread, but a thread with 236 posts is of very limited usefulness to someone wanting to learn C++.