- a. True: C-strings and the string class
- c or d. (b) creates an array of 20 characters, but the last array element must be reserved for the null-termination character to make the array into a C-string.
- a
- f
- a
cin.getline(name, 100);
where 100 (in this example) is the size of the character array.
getline(cin, name);
- c
- a
- The strcpy function (notice, no 'o' in the name) copies the second argument to the first argument; the secure version copies the third argument to the first:
strcpy(blank, name); // "common" version
strcpy_s(blank, 100, name); // Windows safe/secure version
- The string class supports many operators, including the assignment operator:
blank = name;
- b
- a
- c: Arrays are the exception to the rule that C and C++ pass arguments by value as the default. Arrays (in this case, arrays of characters) are passed-by-address, which appear as pointers in the documentation. C-strings are implemented as null-terminated arrays of characters but the destination, s1, must point (i.e., be the address of) a character array.
- b: It is quite easy to index a C-string out of bounds (less than 0 or greater than size - 1), and neither C nor C++ will catch the bug - but something bad is guaranteed to happen when we do it!
- b: The word "always" makes this a trick question. The index operator (the square brackets) doesn't validate the index, but the "at" member function does. For example, let s be an instance of the string class and i be a index. If i<0 or i≥s.length(), s[i] doesn't detect the error but s.at(i) does.
- d. The ASCII codes for the digit-characters form a contiguous sequence of integers beginning with '0' and ending with '9.' So, we can solve the problem without knowing the exact codes for each digit. Furthermore, C++ automatically converts the character '0' into an integer. All we need to know is if 0 ≤ n ≤ 9,
n + '0'
is the ASCII code for a character n places beyond '0.' The calculation fails of n is not with the specified range. The cast operator, (char), casts the ASCII code to a character.
- d. At first, it may seem like we need to know the ASCII character codes to solve the problem. But like the previous problem, all we need to know is the ASCII codes for letters form a contiguous sequence of integers beginning with 'A' and ending with 'Z.' To see how this organization works, let's assume that x is the ASCII code for 'A' and construct an ASCII table for the first few characters:
'A' = x
'B' = x + 1
'C' = x + 2
'D' = x + 3
We can now restate the problem and its solution as follows:
'D' - 'A' = x + 3 - x = 3
illustrating that the solution is independent of the actual ASCII codes.
- b. You way also specify the arguments as main(int argc, char** argv), but I believe that char* argv[] is easier to understand.
- Please begin by reviewing Processing command line input.
A program is named my_program is executed from the command line as
my_program file1 file2 file3 file4
If the program is written in C++ and the arguments are passed in to main, argc 5 and argv[2] is "file2"
Unlike Java, C++ counts the program name as a part of the command line arguments. There are five elements on the command line. So argc stores the value 5. But array indexes begin at zero as follows:
argv[0] is my_program
argv[1] is file1
argv[2] is file2
argv[3] is file3
argv[4] is file4
The example programs, name_box.cpp (version 2) and pyramid.cpp (version 2), demonstrate how to use the command line arguments.
- d: The function return type is a char pointer, but the name of an array (without any additional operators or syntax) IS a pointer. So the syntax IS correct. Not generally recommended but to simplify the question, the problem defines the array as a global variable. So, the array remains allocated and usable after the function returns, and the address (pointer) returned by the function still points to memory that remains allocated.
- b
- d or e
- c
- *itr
- itr++ or ++itr
Questions 27 - 30
When you answer questions like these, focus on what is given rather than speculating about code that is not given. This suggestion implies that it's also essential to read the question carefully and note all the information provided. For example, question 28 stated, "assume that the dynamic memory is deallocated elsewhere." So, answering that dynamic memory is not deleted or deallocated is incorrect. Questions like these make sense in the context of the assigned reading - these questions relate to a specific problem. If the question doesn't make sense, be sure you understand the related concepts from the reading assignment.
All four questions are about memory allocation, not scope. Scope is the place in a program where an identifier (i.e., a name), typically a variable, can be accessed or used. So, while it's true in the case of automatic or local variables that scope and memory allocation are tightly coupled, scope and memory allocation are not the same thing. We can easily see the distinction between scope and memory allocation in the case of "static" variables. When the function returns, the variable name goes out of scope, but the memory holding the variable is not deallocated.
Each solution described in the textbook comes with some consequences. I wouldn't call the consequences "errors" or even "problems." Much of the code that we write has advantages and disadvantages that we must match to the needs of the whole program and the specific problem that it solves.
- There is nothing wrong. The variable line does go out of scope when the function returns, but the variable's memory is not deallocated because it is static. So the returned address points to memory that remains allocated and available.
char* read()
{
static char line[100];
cin.getline(line, 100);
return line;
}
- There is nothing wrong. The variable pointer line goes out of scope when the function returns, but the memory it points to is allocated on the heap and is not deallocated. Again, the returned address points to memory that remains allocated and available.
char* read()
{
char* line = new char[100];
cin.getline(line, 100);
return line;
}
- There is nothing wrong. The variable line is a local read function variable and does go out of scope when the function ends. But line points data in my_function, which remains allocated when read returns.
char* read(char* line)
{
cin.getline(line, 100);
return line;
}
void my_function()
{
char data[100];
read(data);
// do something with line
}
my_function ignores the value read returns, which is perfectly legal in C++. Pass-by-pointer is both an input and an output passing mechanism, which means that read still works here if we rewrite it as
void read(char* line)
{
cin.getline(line, 100);
}
- The function is syntactically correct (it will compile), but it has a logical error. The function returns the address of the array line, which is a local, automatic variable. When the function returns, line will go out of scope. But the problem is that the memory allocated for line is deallocated when the function returns.
char* read()
{
char line[100];
cin.getline(line, 100);
return line;
}
Simply answering:
- it needs the keyword "static"
- memory must be allocated with "new"
- the array needs to be passed in as an argument
doesn't really answer the question, "What if anything is wrong with the code?" Giving one of the above as an answer doesn't explain what is wrong, and it stops us from thinking about the other possible solutions. Remember that each solution has its pros and cons and which solution is the best depends on the problem the program solves.
- Although syntactically correct, the program has a logical error: The array name is
static
, so it always has the same memory address and it retains the last name entered. Whenever the program calls get_name, getline overwrites the last name saved in name. The problem is illustrated in Consequences of static data (b). There are a couple of ways for the programmer to correct the problem:
#include <iostream>
using namespace std;
char* get_name()
{
static char name[100];
char* name = new char[100];
cout << "Please enter a name: ";
cin.getline(name, 100);
return name;
} |
int main()
{
char* array[3];
for (int i = 0; i < 3; i++)
array[i] = get_name();
for (int i = 0; i < 3; i++)
cout << array[i] << endl;
for (int i = 0; i < 3; i++)
delete array[i];
return 0;
} |
#include <iostream>
#include <cstring>
using namespace std;
char* get_name()
{
static char name[100];
cout << "Please enter a name: ";
cin.getline(name, 100);
return name;
}
|
int main()
{
char array[3][100];
for (int i = 0; i < 3; i++)
strcpy(array[i], get_name());
array[i] = get_name();
for (int i = 0; i < 3; i++)
cout << array[i] << endl;
return 0;
} |