Edit string by calling it using concatenation in C++ - c++

I'm a very new C++ user (and a new StackOverflow user at that), and I'm trying to code a very basic Tic-Tac-Toe (Naughts and Crosses) game. I'm not sure how to render the board as it is updated.
My main question is if it is possible to call a string using concatenation. I have an array set up that indexes the states of the 9 spaces of the board using a 0 for empty, a 1 for an X, and a 2 for an O. If I set up 9 variables in a user-defined renderBoard() function named bit1, bit2, etc; Can I call them this way:
void renderBoard()
{
int i = 1;
string bit1;
string bit2;
string bit3;
string bit4;
string bit5;
string bit6;
string bit7;
string bit8;
string bit9;
while (i < 10)
{
if (Spaces[i] = 0)
{
(bit + i) = * //This is the main bit I'm wondering about
}
else
{
//Check for 1, 2, and edit the string bits accordingly
}
++i;
}
//Put all of the strings together, as well as some more strings for adding the grid
//Output the whole concatenated string to the command line
}
If anyone knows of a better way to do this, please let me know. I've tried Googling and rifling through various C++ help websites, but I find it difficult to express my particular case through anything other than a long-winded and specific explanation.
Thanks for you help!!

If I correctly understood your problem, your problem is that you want to access the strings named bit1, bit2, etc using a variable i like bit + i.
And no, you cannot do that!
It will throw a compile time error.
Please correct me if I didn't get what you are looking for.
But one question is still in my mind that why are you using string variables bit1, bit2 etc?
I think you just want to store single digit value in those strings. If this is the case, you can just use a single string of length 9.
You can do this as follows:
int i = 0; //because string indices start from 0 and also array indices.
string bit(9, ' '); //declare a string of length 9 with default value of a space (you can modify it with your default value)
while (i < 9) { // i < 9 because highest index will be 8
if (Spaces[i] == 0) {
bit[i] = '*';
} else {
}
++i;
}

Declaring 9 variables like this is apparently wrong. What you are looking for is an array.
std::array<std::string, 9> bits;
(You need #include <array> and #include <string>.)
Then, you can traverse the string using a for-loop: (in C++, arrays are indexed starting from zero, not one)
for (std::size_t i = 0; i < 9; ++i) {
// operate on bits[i]
}
In the for-loop, you can use the subscript operator to access the element: bits[i].
Finally, to put all the strings together, use std::accumulate:
std::accumulate(bits.begin(), bits.end(), std::string{})
(You need #include <numeric>.)

Related

while every value in array is different than specific int value

I have an array of values e.g. 1, 4, 7, 2.
I also have another array of values and I want to add its values to this first array, but only when they all are different from all values that are already in this array. How can I check it? I've tried many types of loops, but I always ended with an iteration problem.
Could you please tell me how to solve this problem? I code in c++.
int array1[7] = {2,3,7,1,0};
int val1 = rand() % 10;
int val2 = rand() % 10;
int array2[2] = {val1, val2};
and I am trying to put every value from array2 into array1. I tried loop
for (int x:array2)
{
while((val1 && val2) == x)
{
val1 = rand() % 10;
val2 = rand() % 10;
}
}
and many more, but still cannot figure it out. I have this problem because I may have various number of elements for array2. So it makes this "&&" solution infinite.
It is just a sample to show it more clearly, my code has much more lines.
Okay, you have a few problems here. If I understand the problem, here's what you want:
A. You have array1 already populated with several values but with space at the end.
1. How do you identify the number of entries in the array already versus the extras?
B. You have a second array you made from two random values. No problem.
You want to append the values from B to A.
2. If initial length of A plus initial length of B is greater than total space allocated for A, you have a new problem.
Now, other people will tell you to use the standard template library, but if you're having problems at this level, you should know how to do this yourself without the extra help from a confusing library. So this is one solution.
class MyArray {
public:
int * data;
int count;
int allocated;
MyArray() : data(nullptr), count(0), allocated(0) {}
~MyArray() { if (data != nullptr) free(data); }
// Appends value to the list, making more space if necessary
void add(int value) {
if (count >= allocated) {
// Not enough space, so make some.
allocated += 10;
data = (data == nullptr) malloc(allocated * sizeof(int))
: realloc)data, allocated * sizeof(int));
}
data[count++] = value;
}
// Adds value only if not already present.
void addUnique(int value) {
if (indexOf(value) < 0) {
add(value);
}
}
// Returns the index of the value, if found, else -1
int indexOf(int value) {
for (int index = 0; index < count; ++index) {
if (data[index] == value) {
return index;
}
}
return -1;
}
}
This class provides you a dynamic array of integers. It's REALLY basic, but it teaches you the basics. It helps you understand about allocation / reallocating space using old-style C-style malloc/realloc/free. It's the sort of code I was writing back in the 80s.
Now, your main code:
MyArray array;
array.add(2);
array.add(3);
array.add(7);
// etc. Yes, you could write a better initializer, but this is easy to understand
MyArray newValues;
newValues.add(rand() % 10);
newValues.add(rand() % 10);
for (int index = 0; index < newValues.count; ++index) {
array.addUnique(newValues.data[index]);
}
Done.
The key part of this is the addUnique function, which simply checks first whether the value you're adding already is in the array. If not, it appends the value to the array and keeps track of the new count.
Ultimately, when using integer arrays like this instead of the fancier classes available in C++, you HAVE TO keep track of the size of the array yourself. There is no magic .length method on int[]. You can use some magic value that indicates the end of the list, if you want. Or you can do what I did and keep two values, one that holds the current length and one that holds the amount of space you've allocated.
With programming, there are always multiple ways to do this.
Now, this is a lot of code. Using standard libraries, you can reduce all of this to about 4 or 5 lines of code. But you're not ready for that, and you need to understand what's going on under the hood. Don't use the fancy libraries until you can do it manually. That's my belief.

Why does my array element retrieval function return random value?

I am trying to make an own simple string implementation in C++. My implementation is not \0 delimited, but uses the first element in my character array (the data structure I have chosen to implement the string) as the length of the string.
In essence, I have this as my data structure: typedef char * arrayString; and I have got the following as the implementation of some primal string manipulating routines:
#include "stdafx.h"
#include <iostream>
#include "new_string.h"
// Our string implementation will store the
// length of the string in the first byte of
// the string.
int getLength(const arrayString &s1) {
return s1[0] - '0';
}
void append_str(arrayString &s, char c) {
int length = getLength(s); // get the length of our current string
length++; // account for the new character
arrayString newString = new char[length]; // create a new heap allocated string
newString[0] = length;
// fill the string with the old contents
for (int counter = 1; counter < length; counter++) {
newString[counter] = s[counter];
}
// append the new character
newString[length - 1] = c;
delete[] s; // prevent a memory leak
s = newString;
}
void display(const arrayString &s1) {
int max = getLength(s1);
for (int counter = 1; counter <= max; counter++) {
std::cout << s1[counter];
}
}
void appendTest() {
arrayString a = new char[5];
a[0] = '5'; a[1] = 'f'; a[2] = 'o'; a[3] = 't'; a[4] = 'i';
append_str(a, 's');
display(a);
}
My issue is with the implementation of my function getLength(). I have tried to debug my program inside Visual Studio, and all seems nice and well in the beginning.
The first time getLength() is called, inside the append_str() function, it returns the correct value for the string length (5). When it get's called inside the display(), my own custom string displaying function (to prevent a bug with std::cout), it reads the value (6) correctly, but returns -42? What's going on?
NOTES
Ignore my comments in the code. It's purely educational and it's just me trying to see what level of commenting improves the code and what level reduces its quality.
In get_length(), I had to do first_element - '0' because otherwise, the function would return the ascii value of the arithmetic value inside. For instance, for decimal 6, it returned 54.
This is an educational endeavour, so if you see anything else worth commenting on, or fixing, by all means, let me know.
Since you are getting the length as return s1[0] - '0'; in getLength() you should set then length as newString[0] = length + '0'; instead of newString[0] = length;
As a side why are you storing the size of the string in the array? why not have some sort of integer member that you store the size in. A couple of bytes really isn't going to hurt and now you have a string that can be more than 256 characters long.
You are accessing your array out of bounds at couple of places.
In append_str
for (int counter = 1; counter < length; counter++) {
newString[counter] = s[counter];
}
In the example you presented, the starting string is "5foti" -- without the terminating null character. The maximum valid index is 4. In the above function, length has already been set to 6 and you are accessing s[5].
This can be fixed by changing the conditional in the for statement to counter < length-1;
And in display.
int max = getLength(s1);
for (int counter = 1; counter <= max; counter++) {
std::cout << s1[counter];
}
Here again, you are accessing the array out of bounds by using counter <= max in the loop.
This can be fixed by changing the conditional in the for statement to counter < max;
Here are some improvements, that should also cover your question:
Instead of a typedef, define a class for your string. The class should have an int for the length and a char* for the string data itself.
Use operator overloads in your class "string" so you can append them with + etc.
The - '0' gives me pain. You subtract the ASCII value of 42 from the length, but you do not add it as a character. Also, the length can be 127 at maximum, because char goes from -128 to +127. See point #1.
append_str changes the pointer of your object. That's very bad practice!
Ok, thank you everyone for helping me out.
The problem appeared to be inside the appendTest() function, where I was storing in the first element of the array the character code for the value I wanted to have as a size (i.e storing '5' instead of just 5). It seems that I didn't edit previous code that I had correctly, and that's what caused me the issues.
As an aside to what many of you are asking, why am I not using classes or better design, it's because I want to implement a basic string structure having many constraints, such as no classes, etc. I basically want to use only arrays, and the most I am affording myself is to make them dynamically allocated, i.e resizable.

Key Value Pair implementation C

I have a .txt file that stores student names along with two of their best marks. If a student for some reason, i.e. dropping out of course, fails to pass a course, then no marks are recorded.
My file looks like this
Samuel= 90.5, 95.9
Bill= 25.2, 45.3
Tim
Anthony= 99.9, 12.5
Mark
Rob
Basically, Tim, Mark and Rob failed the course and hence their marks are not stored. Also to differentiate between a failed mark and a pass mark, I have used the = symbol. Basically, I want to store all the names into memory alongside their associated values.
This is my implementation, however it is flawed in the sense that I have declared a double *marks[2] array to store all six marks, when clearly it will only store 3. I am having trouble storing the values into the double array.
This is my code...
istream& operator>> (istream& is, Students& student)
{
student.names = new char*[6];
for (int i=0; i<10; i++)
{
student.names[i] = new char[256];
student.marks[i] = new double[2];
is.getline(student.names[i], sizeof(student.names));
for (int j=0; j < 256; j++)
{
if((student.names[i][j] == '='))
{
int newPos = j + 1;
for (int k = newPos; k < 256; k++)
{
student.names[i][k - newPos] = student.names[k];
}
}
}
}
}
How can I go about storing the values of the students with the valid marks? Please, no use of vectors or stringstreams, just pure C/C++ char arrays
You have a few options, you could use a struct like so
struct Record {
std::string name;
double marks[2];
};
And then stick that into something like std::vector<Record> or an array of them like
Records *r = new Records[1000];
You could also keep three different arrays (either automatically allocated or dynamically allocated or even std::vector), one to hold the name, two to hold the marks.
In each case you would just indicate a fail by some thing like the marks being zero.
Also, you can use
std::string name;
double first, second;
std::cin >> name;
if (name[name.size() - 1] == '=')
std::cin >> first >> second;
And this will parse the input like you want it to for a single line. Once you've done that you can wrap the whole thing in a loop while sticking the values you get into some sort of data structure that I already described.
Hope that gives you a few ideas on where to go!
Here's a strategy:
First of all you need to implement a struct to hold the key-value pair, I suggest the following:
struct Student {
char name[30];
double marks[2];
};
Note that you can give the dimension of the char array inside the struct if you know that the length will never be higher. (which is given here)
Now what you need is to know how many lines are in your ifstream, you could make a loop of is.getline() calls to get there. (don't forget to call is.clear() and is.seekg(0) when finished, to be at the beginning for the real loop)
When you know how many lines are in your ifstream you can use dynamically cast the Array of your struct with the actual length of your file:
Student * students = new Student[lineCount]; // line count of is
As you can see, there's no need to have a std::vector to hold the values. Consider that the getline() loop may be an overkill just to get the line count, alternatively you could give a length to Students at compile-time by making an array with a length that will never be overpassed.
(e.g. Student students[128];)
Now you need to parse the lines, i'd suggest you make a loop like the following (line by line):
// int parseLine ( char* line, char* name, double* marks ) { ...
bool hasMarks=false;
int iLine=0; // Line pos iterator
int iName=0; // Name pos iterator
char mk1Str[4]; // String buffer, Mark 1
char mk2Str[4]; // String buffer, Mark 2
while(line[iLine]!='\0')
{
if(line[iLine]=='=')
{
hasMarks=true;
name[iLine]='\0';
for(int iMark=0;iMark<4;iMark++)
{
mk1Str[iMark]=line[iLine+iMark+2];
mk2Str[iMark]=line[iLine+iMark+8];
// ^^ You can harcode the offsets (2,8) since they don't change
}
break;
}
name[iName++]=line[iLine];
iLine++;
}
Now what you need is to parse the marks to double values, for this you could use the atof() function that works with char*. The bool hasMarks helps you know if a student has defined marks, if not, you could define dummy values like -1 for the mark fields of your struct.
I think this works quite well for your case...

grabbing data sets from a file with an arbitrary amount of spaces

**No direct answers or code examples please, this is my homework which i need to learn from. I'm looking for help concerning the algorithm i need to develop.
I seem to be having a logic error in coming up with a solution for a portion of my class work, the program involves multiple files, but here is the only relevant portion:
I have a file PlayerStats that holds the stats for a basketball player in:
rebounds
points
assists
uniform #
my initial reaction would be to create a while loop and read these into a temporary struct that holds these values, then create a merge function that merges the values of the temp struct with the inital array of records, simple enough?
struct Baller
{
//other information on baller
int rebounds;
int assists;
int uniform;
int points;
void merge(Baller tmp); //merge the data with the array of records
}
//in my read function..
Baller tmp;
int j = 0;
inFile << tmp.uniform << tmp.assists << tmp.points << tmp.rebounds
while(inFile){
ArrayRecords[j].merge(tmp);
j++;
//read in from infile again
}
The catch:
The file can have an arbitrary number of spaces between the identifiers, and the information can be in any order(leaving out the uniform number, that is always first). e.g.
PlayerStats could be
11 p3 a12 r5 //uniform 11, 3 points 12 assists 5 rebounds
//other info
OR
11 p 3 r 5 a 12 //same exact values
What I've come up with
can't seem to think of an algorithm to grab these values from the file in the correct order, i was thinking of something along these lines:
inFile << tmp.uniform; //uniform is ALWAYS first
getline(inFile,str); //get the remaining line
int i = 0;
while(str[i] == " ") //keep going until i find something that isnt space
i++;
if(str[i] == 'p') //heres where i get stuck, how do i find that number now?
else if(str[i] == 'a')
eles if(str[i] = 'r'
If you're only going to check one letter, you could use a switch statement instead of if / else, that would make it easier to read.
You know where the number starts at that point, (hint: str[i+1]), so depending on what type your str[] is, you can either use atoi if its a char array, or std::stringstream if it's an std::string.
I'm tempted to give you some code, but you said not too. If you do want some, let me know and I'll edit the answer with some code.
Instead of using a 'merge' function, try using an std::vector so you can just push_back your structure instead of doing any 'merging'. Besides, your merge function is basically a copy assignment operator, which is created by the compiler by default (you don't need to create a 'merge' function), you just need to use = to copy the data across. If you wanted to do something special in your 'merge' function, then you should overload the copy assignment operator instead of a 'merge' function. Simples.
Do something like that:
int readNumber () {
while isdigit (nextchar) -> collect in numberstring or directly build number
return that number;
}
lineEater () {
Read line
skip over spaces
uniform=readNumber ();
haveNum=false;
haveWhat=false;
Loop until eol {
skip over spaces
if (isdigit)
number=readNumber ();
skip over spaces
haveNum=true;
else
char=nextChar;
haveWhat=true;
if (haveChar and haveNum) {
switch (char) {
case 'p' : points=number; break;
...
}
haveNum=false;
haveWhat=false;
}
}
or, if you are more ambitous, write a grammar for your input and use lex/yacc.

C++ exam on string class implementation

I just took an exam where I was asked the following:
Write the function body of each of the methods GenStrLen, InsertChar and StrReverse for the given code below. You must take into consideration the following;
How strings are constructed in C++
The string must not overflow
Insertion of character increases its length by 1
An empty string is indicated by StrLen = 0
class Strings {
private:
char str[80];
int StrLen;
public:
// Constructor
Strings() {
StrLen=0;
};
// A function for returning the length of the string 'str'
int GetStrLen(void) {
};
// A function to inser a character 'ch' at the end of the string 'str'
void InsertChar(char ch) {
};
// A function to reverse the content of the string 'str'
void StrReverse(void) {
};
};
The answer I gave was something like this (see bellow). My one of problem is that used many extra variables and that makes me believe am not doing it the best possible way, and the other thing is that is not working....
class Strings {
private:
char str[80];
int StrLen;
int index; // *** Had to add this ***
public:
Strings(){
StrLen=0;
}
int GetStrLen(void){
for (int i=0 ; str[i]!='\0' ; i++)
index++;
return index; // *** Here am getting a weird value, something like 1829584505306 ***
}
void InsertChar(char ch){
str[index] = ch; // *** Not sure if this is correct cuz I was not given int index ***
}
void StrRevrse(void){
GetStrLen();
char revStr[index+1];
for (int i=0 ; str[i]!='\0' ; i++){
for (int r=index ; r>0 ; r--)
revStr[r] = str[i];
}
}
};
I would appreciate if anyone could explain me roughly what is the best way to have answered the question and why. Also how come my professor closes each class function like " }; ", I thought that was only used for ending classes and constructors only.
Thanks a lot for your help.
First, the trivial }; question is just a matter of style. I do that too when I put function bodies inside class declarations. In that case the ; is just an empty statement and doesn't change the meaning of the program. It can be left out of the end of the functions (but not the end of the class).
Here's some major problems with what you wrote:
You never initialize the contents of str. It's not guaranteed to start out with \0 bytes.
You never initialize index, you only set it within GetStrLen. It could have value -19281281 when the program starts. What if someone calls InsertChar before they call GetStrLen?
You never update index in InsertChar. What if someone calls InsertChar twice in a row?
In StrReverse, you create a reversed string called revStr, but then you never do anything with it. The string in str stays the same afterwords.
The confusing part to me is why you created a new variable called index, presumably to track the index of one-past-the-last character the string, when there was already a variable called StrLen for this purpose, which you totally ignored. The index of of one-past-the-last character is the length of the string, so you should just have kept the length of the string up to date, and used that, e.g.
int GetStrLen(void){
return StrLen;
}
void InsertChar(char ch){
if (StrLen < 80) {
str[StrLen] = ch;
StrLen = StrLen + 1; // Update the length of the string
} else {
// Do not allow the string to overflow. Normally, you would throw an exception here
// but if you don't know what that is, you instructor was probably just expecting
// you to return without trying to insert the character.
throw std::overflow_error();
}
}
Your algorithm for string reversal, however, is just completely wrong. Think through what that code says (assuming index is initialized and updated correctly elsewhere). It says "for every character in str, overwrite the entirety of revStr, backwards, with this character". If str started out as "Hello World", revStr would end up as "ddddddddddd", since d is the last character in str.
What you should do is something like this:
void StrReverse() {
char revStr[80];
for (int i = 0; i < StrLen; ++i) {
revStr[(StrLen - 1) - i] = str[i];
}
}
Take note of how that works. Say that StrLen = 10. Then we're copying position 0 of str into position 9 of revStr, and then position 1 of str into position 9 of revStr, etc, etc, until we copy position StrLen - 1 of str into position 0 of revStr.
But then you've got a reversed string in revStr and you're still missing the part where you put that back into str, so the complete method would look like
void StrReverse() {
char revStr[80];
for (int i = 0; i < StrLen; ++i) {
revStr[(StrLen - 1) - i] = str[i];
}
for (int i = 0; i < StrLen; ++i) {
str[i] = revStr[i];
}
}
And there are cleverer ways to do this where you don't have to have a temporary string revStr, but the above is perfectly functional and would be a correct answer to the problem.
By the way, you really don't need to worry about NULL bytes (\0s) at all in this code. The fact that you are (or at least you should be) tracking the length of the string with the StrLen variable makes the end sentinel unnecessary since using StrLen you already know the point beyond which the contents of str should be ignored.
int GetStrLen(void){
for (int i=0 ; str[i]!='\0' ; i++)
index++;
return index; // *** Here am getting a weird value, something like 1829584505306 ***
}
You are getting a weird value because you never initialized index, you just started incrementing it.
Your GetStrLen() function doesn't work because the str array is uninitialized. It probably doesn't contain any zero elements.
You don't need the index member. Just use StrLen to keep track of the current string length.
There are lots of interesting lessons to learn by this exam question. Firstly the examiner is does not appear to a fluent C++ programmer themselves! You might want to look at the style of the code, including whether the variables and method names are meaningful as well as some of the other comments you've been given about usage of (void), const, etc... Do the method names really need "Str" in them? We are operating with a "Strings" class, after all!
For "How strings are constructed in C++", well (like in C) these are null-terminated and don't store the length with them, like Pascal (and this class) does. [#Gustavo, strlen() will not work here, since the string is not a null-terminated one.] In the "real world" we'd use the std::string class.
"The string must not overflow", but how does the user of the class know if they try to overflow the string. #Tyler's suggestion of throwing a std::overflow_exception (perhaps with a message) would work, but if you are writing your own string class (purely as an exercise, you're very unlikely to need to do so in real life) then you should probably provide your own exception class.
"Insertion of character increases its length by 1", this implies that GetStrLen() doesn't calculate the length of the string, but purely returns the value of StrLen initialised at construction and updated with insertion.
You might also want to think about how you're going to test your class. For illustrative purposes, I added a Print() method so that you can look at the contents of the class, but you should probably take a look at something like Cpp Unit Lite.
For what it's worth, I'm including my own implementation. Unlike the other implementations so far, I have chosen to use raw-pointers in the reverse function and its swap helper. I have presumed that using things like std::swap and std::reverse are outside the scope of this examination, but you will want to familiarise yourself with the Standard Library so that you can get on and program without re-inventing wheels.
#include <iostream>
void swap_chars(char* left, char* right) {
char temp = *left;
*left = *right;
*right = temp;
}
class Strings {
private:
char m_buffer[80];
int m_length;
public:
// Constructor
Strings()
:m_length(0)
{
}
// A function for returning the length of the string 'm_buffer'
int GetLength() const {
return m_length;
}
// A function to inser a character 'ch' at the end of the string 'm_buffer'
void InsertChar(char ch) {
if (m_length < sizeof m_buffer) {
m_buffer[m_length++] = ch;
}
}
// A function to reverse the content of the string 'm_buffer'
void Reverse() {
char* left = &m_buffer[0];
char* right = &m_buffer[m_length - 1];
for (; left < right; ++left, --right) {
swap_chars(left, right);
}
}
void Print() const {
for (int index = 0; index < m_length; ++index) {
std::cout << m_buffer[index];
}
std::cout << std::endl;
}
};
int main(int, char**) {
Strings test_string;
char test[] = "This is a test string!This is a test string!This is a test string!This is a test string!\000";
for (char* c = test; *c; ++c) {
test_string.InsertChar(*c);
}
test_string.Print();
test_string.Reverse();
test_string.Print();
// The output of this program should look like this...
// This is a test string!This is a test string!This is a test string!This is a test
// tset a si sihT!gnirts tset a si sihT!gnirts tset a si sihT!gnirts tset a si sihT
return 0;
}
Good luck with the rest of your studies!
void InsertChar(char ch){
str[index] = ch; // *** Not sure if this is correct cuz I was not given int index ***
}
This should be something more like
str[strlen-1]=ch; //overwrite the null with ch
str[strlen]='\0'; //re-add the null
strlen++;
Your teacher gave you very good hints on the question, read it again and try answering yourself. Here's my untested solution:
class Strings {
private:
char str[80];
int StrLen;
public:
// Constructor
Strings() {
StrLen=0;
str[0]=0;
};
// A function for returning the length of the string 'str'
int GetStrLen(void) {
return StrLen;
};
// A function to inser a character 'ch' at the end of the string 'str'
void InsertChar(char ch) {
if(StrLen < 80)
str[StrLen++]=ch;
};
// A function to reverse the content of the string 'str'
void StrReverse(void) {
for(int i=0; i<StrLen / 2; ++i) {
char aux = str[i];
str[i] = str[StrLen - i - 1];
str[StrLen - i - 1] = aux;
}
};
};
When you init the char array, you should set its first element to 0, and the same for index. Thus you get a weird length in GetStrLen since it is up to the gods when you find the 0 you are looking for.
[Update] In C/C++ if you do not explicitly initialize your variables, you usually get them filled with random garbage (the content of the raw memory allocated to them). There are some exceptions to this rule, but the best practice is to always initialize your variables explicitly. [/Update]
In InsertChar, you should (after checking for overflow) use StrLen to index the array (as the comment specifies "inser a character 'ch' at the end of the string 'str'"), then set the new terminating 0 character and increment StrLen.
You don't need index as a member data. You can have it a local variable if you so please in GetStrLen(): just declare it there rather than in the class body. The reason you get a weird value when you return index is because you never initialized it. To fix that, initialize index to zero in GetStrLen().
But there's a better way to do things: when you insert a character via InsertChar() increment the value of StrLen, so that GetStrLen() need only return that value. This will make GetStrLen() much faster: it will run in constant time (the same performance regardless of the length of string).
In InsertChar() you can use StrLen as you index rather than index, which we already determined is redundant. But remember that you must make sure the string terminates with a '\0' value. Also remember to maintain StrLen by incrementing it to make GetStrLen()'s life easier. In addition, you must take the extra step in InsertChar() to avoid a buffer overflow. This happens when the user inserts a character to the string when the length of the string is alreay 79 characters. (Yes, 79: you must spend one character on the terminating null).
I don't see an instruction as to how to behave when that happens, so it must be up to your good judgment call. If the user tries to add the 80th character you might ignore the request and return, or you might set an error flag -- it's up to you.
In your StrReverse() function you have a few mistakes. First, you call GetStrLen() but ignore its return value. Then why call it? Second, you're creating a temporary string and work on that, rather than on the string member of the class. So your function doesn't change the string member, when it should in fact reverse it. And last, you could reverse the string faster by iterating through half of it only.
Work on the member data string. To reverse a string you can swap the first element (character) of the string with its last (not the terminating null, the character just before that!), the second element with the second-to-last and so on. You're done when you arrive at the middle of the string. Don't forget that the string must terminate with a '\0' character.
While you were solving the exam it would also be a good opportunity to teach your instructor a think or two about C++: we don't say f(void) because that belongs to the old days of C89. In C++ we say f(). We also strive in C++ to use class initializer lists whenever we can. Also remind your instructor how important const-correctness is: when a function shouldn't change the object is should be marked as such. int GetStrLen(void) should be int GetStrLen() const.
You don't need to figure out the length. You already know it it is strLen. Also there was nothing in the original question to indicate that the buffer should contain a null terminated string.
int GetStrLen(void){
return strLen;
}
Just using an assertion here but another option is to throw an exception.
void InsertChar(char ch){
assert(strLen < 80);
str[strLen++] = ch;
}
Reversing the string is just a matter of swapping the elements in the str buffer.
void StrRevrse(void){
int n = strLen >> 1;
for (int i = 0; i < n; i++) {
char c = str[i];
str[i] = str[strLen - i];
str[strLen - i] = c;
}
}
I would use StrLen to track the length of the string. Since the length also indicates the end of the string, we can use that for inserting:
int GetStrLen(void) {
return StrLen;
}
int InsertChar(char ch)
{
if (strLen < sizeof(str))
{
str[StrLen] = ch;
++strLen;
}
}
void StrReverse(void) {
for (int n = 0; n < StrLen / 2; ++n)
{
char tmp = str[n];
str[n] = str[StrLen - n - 1];
str[StrLen - n - 1] = tmp;
}
}
first of all why on you use String.h for the string length?
strlen(char[] array) returns the Lenght or any char array to a int.
Your function return a werid value because you never initialize index, and the array has zero values, first initilize then execute your method.