Skip to main content
GameDev.net gamedev.net
📌 Pinned 🔒 Locked

C++ Workshop - Arrays & Strings (Ch. 13)

Started by JWalsh Sep 4, 2006 at 3:08 PM 35 replies 34.8k views
Original Post
JWalsh
JWalsh

Welcome to the GDNet C++ Workshop – Ch. 13

For a complete introduction to this workshop, please look here. Workshop Overview This workshop is designed to aid people in their journey to learn beginning C++. This workshop is targeted at highly motivated individuals who are interested in learning C++ or who have attempted to learn C++ in the past, but found that without sufficient support and mentoring they were unable to connect all the pieces of this highly complex but powerful programming language. This is a 'guided' self-teaching C++ workshop. Each student is responsible for taking the time to read the material and learn the information. The community and tutors that arise out of this workshop are here for making the learning process run more smoothly, but are not obligated to baby-sit a person's progress. Because everyone will be working from the same textbook (Teach Yourself C++ in 21 days 5th Ed.), students may find it easier to get answers to the specific questions they might have. There is no minimum age requirement, and there is no previous programming experience required. Additionally, this workshop does not attempt to defend C++ as a language, nor does it attempt to demonstrate that C++ is either more or less useful then other programming languages for any particular purpose. People who intend to start a discussion about the differences between C++ and ANY other languages (except as are relevant to a particular discussion), are encouraged to do so elsewhere. This workshop is for educational, not philosophical discussions. Quizzes & Exercises Each week will have quizzes and exercises posted in the weekly threads. Please try and answer them by yourself. As well, please DO NOT post the answers to Quizzes and Exercises within this thread. Once it becomes acceptable to post the answers to quizzes and exercises, an additional thread will be created each week specifically for the purpose of posting quiz answers. If you try with reasonable effort but are unable to answer the questions or complete the exercises, feel free to post a clarification question here on the thread. Tutors, myself, or others will do the best we can to point you in the right direction for finding the answer.

Chapter 13 – Managing Arrays and Strings

Introduction Welcome back everyone! We took a week off so that people would have a chance to make headway on their projects, but alas we're back. We've now completed over 50% of the workshop and there will be no more breaks between now and the end. We've got roughly 9 weeks left (including this week) and 2 more projects to do...plus a final project, so we'll be busy up until the end. This week we'll be covering arrays and strings - one of the most controversial topics amongst seasoned programmers. Historically, strings were handled as an array of characters, or as a pointer to a an array of characters. This often lead to confusing out of bounds issues (due to needing a terminating null character), dangling pointers, and memory leaks. Modern programming languages, C++ included, provide helper string classes which encapsulate the messiness of dealing with pointers when wanting to use strings. One of the unique things about this book is it gives the readers an opportunity to write their OWN string class, so you'll have an idea of what's happening under the hood when using the Standard Library's string class; std::string. Additionally, you'll all get a chance to work with arrays, the basic container objects for storing sets of objects in C++. This might come in handy during development of your projects! And speaking of projects, there's just under two weeks left to complete Project 1. So don’t forget to check out Project 1. This project is designed to test everything you've learned so far. Expressions, branching, functions, pointers, classes, loops, and object oriented design. I'm looking forward to seeing what each person following the tutorial can come up with. If you find you're having technical questions about how to do something, you might want to go back and re-read a chapter or 2. If you're having questions about design, and where to get started, well...welcome to the wonderful world of problem solving. Please feel free to post questions in the Project 1 thread on how to design the program. Please remember to use OPINION and WARNING tags whenever applicable. As well, feel free to post your own insights, and review questions or exercises beginning Wednesday or Thursday. Outline of the Reading - Chapter 13
  1. What is an Array?
  2. Using Arrays of Objects
  3. Building Arrays of Pointers
  4. A Look at Pointer Arithmetic - An Advanced Topic
  5. Declaring Arrays on the Free Store
  6. char Arrays and Strings
  7. Using the strcpy() and strncpy() Methods
  8. String Classes
  9. Linked Lists and Other Structures
  10. Creating Array Classes

Good Luck!

[Edited by - jwalsh on May 30, 2007 1:04:02 PM]
gparali
gparali
Not related to this chapter.More of a general question.

Should we avoid using global variables.And if we should, are there exceptions?
Under what circumstances is using a global variable a good idea.
samanime
samanime
[opinion]
Usually you want to avoid global variables all together. If you have to use one, there is probably room for improvement in your code.

A common good use for a global variable would be to define something. In those cases, you would use the #define precompiler command instead of calling it like a normal variable. One common one you might see is something like:

#define DEBUGint main(){#ifdef DEBUG//output some debug info#endif}


Whether it is a good idea or bad idea is really up to you, but knowing when to use them is more important. You should only use a global variable when it is something common that needs to be shared throughout your program and the value won't change.

Another good use would be to define some constants instead of having to use numbers. So you could have something like:

#define THROW_BALL 1#define CATCH_BALL 2#define DROP_BALL 3int main(){switch(action){case THROW_BALL:  //...  break;case CATCH_BALL:  //...  break;case DROP_BALL;  //...  break;}} 

[/opinion]
me22
me22
[opinion]( It's a shame the book feels it's nessesary to introduce char* strings before std::string and new[]/delete[] before std::vector. )[/opinion]

Quote:
Original post by samanime
[opinion]
A common good use for a global variable would be to define something. In those cases, you would use the #define precompiler command instead of calling it like a normal variable. One common one you might see is something like:

*** Source Snippet Removed ***
[/opinion]

C++ added const so that this would no longer be nessesary.

[opinion]const variables at global scope are acceptable[/opinion] and const variables at namespace scope are certainly alright.

Quote:
Original post by samanime
[opinion]
Another good use would be to define some constants instead of having to use numbers. So you could have something like:

*** Source Snippet Removed ***
[/opinion]

In that situation an enum would be preferable.
Deyja
Deyja
[opinion]And if an enum were not available, use const ints. Do not use #define for constants, and do not use macros to avoid function call overhead (use inline functions instead)

The only time you should be using #define in C++ is for include guards and conditional compilation. (And code generation, if you really know what you're doing)
[/opinion]
RinusMaximus
RinusMaximus
In the book the writer gives the following example:

Cat* catArray[500];Cat* pCat;for(int i = 0; i < 500; i++){   pCat = new Cat;   catArray = pCat;}


In the end he does not delete any of the elements in the array. This is a memory leak right? Or am I missing something?
Emmanuel Deloget
Emmanuel Deloget
Quote:
Original post by RinusMaximus
In the book the writer gives the following example:

Cat* catArray[500];Cat* pCat;for(int i = 0; i < 500; i++){   pCat = new Cat;   catArray = pCat;}


In the end he does not delete any of the elements in the array. This is a memory leak right? Or am I missing something?


Indeed, it is a memory leak.
RinusMaximus
RinusMaximus
Quote:
Original post by Emmanuel Deloget
Quote:
Original post by RinusMaximus
In the book the writer gives the following example:

Cat* catArray[500];Cat* pCat;for(int i = 0; i < 500; i++){   pCat = new Cat;   catArray = pCat;}


In the end he does not delete any of the elements in the array. This is a memory leak right? Or am I missing something?


Indeed, it is a memory leak.


Ok good. I was doubting my own understanding of the subject when I saw this.

Afr0m@n
Afr0m@n
Quote:
Original post by samanime
[opinion]
Usually you want to avoid global variables all together. If you have to use one, there is probably room for improvement in your code.

A common good use for a global variable would be to define something. In those cases, you would use the #define precompiler command instead of calling it like a normal variable. One common one you might see is something like:
[/opinion]


#define doesn't declare *real* project wide global variables, does it? O_O

I usually do like this when making a global:

[Header]
class myClass{};
extern myClass myClassGlobal;
[/Header]

[SourceFile]#include "stdafx.h"myClass myClassGlobal;[/SourceFile]
_______________________Afr0Games
me22
me22
Quote:
Original post by Afr0m@n
#define doesn't declare *real* project wide global variables, does it? O_O

It's textual substitution, which is even worse than a global variable because it's not affected by scopes.

For example, certain common headers (windows.h) define a macro called min, which then makes it exceedingly annoying to call the std::min function which is just as fast and doesn't suffer from multipule-evaluation-of-argument gotchas.

( There's such things as Boost's BOOST_PREVENT_MACRO_SUBSTITUTION that can be used to get around it, but it's a pain. )

Quote:
Original post by Afr0m@n
I usually do like this when making a global:
[snip]

That looks correct.
willhemm
willhemm
Just wanted to say Hello and thank you guys for this workshop. I just started last week so I'm playing catch up. I in chapter 6 right now... I am moving so quickly I don't think it is all sticking but it is so much better then learning on my own. Also thanks to all of you that are asking questions, they are some of the same ones I have had.

will
schwa
schwa
I have a question regarding multidimensional array and its equivalent single array representation.

As mentioned in the book, we can declare SQUARE board[8][8] as SQUARE Board[64].

Apart from being more intuitive in the multidimensional array, is it true that a multidimensional array performs slower than a single dimensional array.

If so, should we use the one-dimensional representation for multidimensional array if performance is an issue?
ph33r
ph33r
Quote:
Original post by schwa
I have a question regarding multidimensional array and its equivalent single array representation.

As mentioned in the book, we can declare SQUARE board[8][8] as SQUARE Board[64].

Apart from being more intuitive in the multidimensional array, is it true that a multidimensional array performs slower than a single dimensional array.

If so, should we use the one-dimensional representation for multidimensional array if performance is an issue?


The answer depends on the size of your cache. The compiler flattens the multi-dimensional array to a single array in memory. This means that its a long section of memory 8*8 long. If you iterate through the array [row][col] or [col][row] it will traverse the memory differently. One will jump 8 at a time while another will increment 1 at a time. If your cache can handle loading in the size of the entire array into cache either traversals will be just as quick.

It seems on my compiler the compiler will lay out the array by [row][col](y,x) so if you increment one by x or col each time then you'll only be moving forward one in memory.

Looking at my dissasembly in debug shows that to access an array in [r][c] format takes two pointer dereferences but with optimizations on its one look up.

So no I can't see how it would be any faster to use a single array yourself. Unless you write some obscure code and the compiler doesn't know how to optimize it.



Zahlman
Zahlman
AFAIK, the "ordering" of a multi-dimensional array's memory layout is well-defined, specified by the standard, such that the first dimension takes the "big" stride and the last dimension iterates sequentially through memory. As long as your nested loops are in the right order, there is no performance difference; it really is just syntactic sugar. And even if you had nested loops in the wrong order, in *some* circumstances an optimizing compiler can fix it for you. (The actual restructuring is normally straightforward; the hard part is checking if it's "safe". And yes, I took an optimizing-compilers course in university :) )
Zaris
Zaris
Was a quiz posted for this chapter?
Zaris
Zaris
A two month old baby would definally take a lot of time. I been putting all the information together in a packet. It has help give me a much more complete understanding of C++.
RinusMaximus
RinusMaximus
Quote:
Original post by jwalsh
Not yet. I'm behind schedule on my quizzes due to my 2 month old baby. =) I'll go back and post some retroactively, but very few were answering the quizzes anyways.


I would love to see some quiz questions for the past chapters though. I don't need tons of questions for each chapter, but just a few, to test if I understood the chapter would be nice.
JWalsh
JWalsh
Greetings All!

It's once again QUIZ TIME!!! That's right, listed below are a set of quiz questions to help you test your knowledge and understanding of the material contained in chapters 13.

In addition to the questions and exercises below, make sure that as you're reading the book you enter the examples into your compiler, build the program, and run the executable. I know this is a time consuming process, but the repeat use of keywords, syntax, and semantics will help ingrain the information into your long-term memory. My advice is to create a simple "driver" project with a function main. As you read, enter the examples into function main, test it, and then erase it for use again in the next example.

PLEASE DO NOT POST THE ANSWERS TO THESE QUESTIONS OR EXERCISES. If you are unable to answer these questions, please ask for assistance, but DO NOT POST THE ANSWERS. Any question which is not marked with [Extra Credit] can be answered by reading your textbook. Questions which are marked [Extra Credit] either have been answered in the thread previously, or can be answered by doing a bit of research.

I will create an answer thread for these questions immediately, so that people will have a chance to get the answers more quickly.

Chapter 13 Quiz

1. What is an array?
2. How do you access an element in an array?
3. Are offsets (indexes) numbered starting from 0 or from 1?
4. What happens if you write to an index that is outside the range of your array?
5. What are fence post errors?
6. How do you initialize arrays with simple data types?
7. If you initialize an array with values, are you required to specify the size? Should you?
8. When using an array of objects, which constructor gets called when the array is created?
9. Is it possible to have multi-dimensional arrays?
10. Is there a maximum number of dimensions which are supported by C++?
11. In C++, what is another way of thinking about an array name, as it pertains to pointers?
12. Is it legal to use array names as replacements for the construct in question? How about vice-versa?
13. What happens if you allocate a dynamic array of memory and don’t delete it, including the [] operator?
14. Can you set the size of an array created on the stack at run-time?
15. Can you set the size of an array created on the heap at run-time?
kingIZZZY
kingIZZZY
How do I pass an array of strings into a function?

example of what i tried:

#include <string>....int main(){  string myStringArray[] = {"hello", "whatsup", "howdy"};  doMyFunc(myString);}void doMyFunc(string theArray){  cout << endl << theArray[0]; // please print the first full string,                                // not the first character of tfist string  cout << endl << theArray[1]; // please print the second full string,   cout << endl << theArray[2]; // please print the third full string, }


ive tried this and other varieties, which generate a compiler error:
"conversion from std::string*' to non-scalar type std::string' requested"
(depending which variety i try, the std::string*' could also be std::string**' etc.)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.