dynamically created arrays - c++

My task consists of two parts. First I have to create globbal char array of 100 elements, and insert some text to it using cin. Afterwards calculate amount of chars, and create dedicated array with the length of the inputted text. I was thinking about following solution :
char[100]inputData;
int main()
{
cin >> inputData >> endl;
int length=0;
for(int i=0; i<100; i++)
{
while(inputData[i] == "\0")
{
++count;
}
}
char c = new char[count];
Am I thinking good ?
Second part of the task is to introduce in the first program dynamically created array of pointers to all inserted words. Adding a new word should print all the previous words and if there is no space for next words, size of the inputData array should be increased twice. And to be honest this is a bit too much for me. How I can create pointers to words specifically ? And how can I increase the size of global array without loosing its content ? With some temporary array ?

Regardless of the rest of your question, you appear to have some incorrect ideas about while loops. Let's look at this code.
for(int i=0; i<100; i++) {
while(inputData[i] == "\0") {
++count;
}
}
First, "\0" is not the NUL character. It is a pointer to a string containing only the terminating NUL byte. You want '\0' instead. Assuming this change, there are still problems. Let's work through what will happen:
How does a while loop work? It executes the body repeatedly, as long as the condition is true.
When does a while loop finish? When the condition is finally made false by executing the body.
What's the condition of your loop? inputData[i] == '\0', after correction.
What's the body? ++count.
Can ++count ever change the value of the condition? No, because it doesn't change i.
So, if inputData[i] is not the NUL byte, the while loop never executes.
But, if inputData[i] is the NUL byte, the while loop executes forever.
Assuming you've read a proper string into inputData, then at some point inputData[i] will be NUL, and you'll have an infinite loop.
To count the length of a standard C string, just do this
count = strlen(inputData);
If for some reason you really have to write a loop, then the following works:
int len = 0,
while (inputData[len] != '\0') {
len++;
}
After the loop, len holds the length of the string.

#include <iostream>
#include <string>
int main()
{
std::string input;
std::getline(std::cin, input);
}

Global arrays can't have the size changed dynamically unless they are a pointer to an array, in which case you can erase them and reallocate them.
Perhaps what you're after is an automatically resizing array, like a std::vector. You can see how many letters you have in the array by calling size() on the vector, and you can increase the size of the array by calling resize().
While not the most elegant solution, it might be a bit easier to use for the moment.

Related

Put an array in the end of another array C++

Normally it's a question about a buffer with a null-terminated string, but we can extrapolate it to a general case.
I have a big array of a fixed length, let's say 10:
char outputArray[10] = {'-','-','-','-','-','-','-','-','-','-'};
And I have some other (Edited: smaller) array (in my case it's a char buffer with null terminator) with a variable length. Let's say it's a buffer of 6 elements, but the actual length is indicated by another variable.
char inputArray[10] = {'h','i','/0',...some other values, i'm not interested in};
int arrLength = 2; // For my task it means a strlen(inputArray);
How to put a small array at the end of a big array, to get this:
outputArray = {'-','-','-','-','-','-','-','-','h','i'} // the null terminator isn't important, it's not about the strings, it's about arrays.
Constraints:
I can't use std, so only "native" solutions (it's for Arduino)
C++11
Code should be memory and time efficient (some elegant algorithm without too much loops and too much temporary variables or calculations please)
Thank you in advance
Edited:
Thank to #ThomasWeller for an answer. I have a small precision though. What if I need to clean all the elements before the inserted array?
For example I had some garbage
{'a','k','$','-','n','"','4','i','*','%'};
And I need to get
{'-','-','-','-','-','-','-','-','h','i'};
Do I need 2 loops? First to reset an array and the second one to set the actual result?
It can be done with a single for loop and a single variable:
for (char i=0; i<arrLength; i++)
{
outputArray[10-arrLength+i] = inputArray[i];
}
If you make arrLength a char instead of an int, this will even save you 2 bytes of memory ;-)
Use memset() to set all memory to an initial value and then memcpy() the contents at the end:
char output[10];
char input[10] = "hi\0------";
char arrLength = 2;
void setup() {
memset(output, '-', 10); // "----------"
memcpy(output+10-arrLength, input, arrLength);
Serial.begin(9600);
Serial.write(output, 10);
}
void loop() { }

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.

Length character count using recursive function

I'm trying to create a recursive function that could count the characters of a string, but I don't know why my code is crashing my system. I don't have any more ideas.
Any suggestions:
long slength (const char ntca[])
{
int length = 0;
if (ntca[length] == '\0'){
return 0;
}
else{
return slength(ntca)+1;
}
}
The current code calls slength for the same buffer recursively. This will continue until the stack overflows.
You need to reduce the buffer by one character as well as adding 1 to the length count for each recursive call
return slength(ntca+1)+1;
// ^^
You do not need to declare the local variable. The function can be written simpler
size_t slength( const char s[] )
{
return ( *s == '\0' ? 0 : 1 + slength( s + 1 ) );
}
It's crashing because you're not shortening the string. The line should read
return slength(ntca+1)+1;
Look at the recursive call. If the length of ntca is not zero, then this function calls itself with exactly the same argument. This causes an endless recursion which crashes the stack.
You should work through your algorithm with pencil and paper before you try it in code.
In general, if you use recursion, you have to make a recursive call on a smaller problem size. In your code, you call the function to the same array (or rather, the same pointer to the first element in the array), rather than the pointer to the next element in the array.
However, it's recommended you don't use recursion in C++. Also, since this is such a common thing, there is a strlen() defined in the <cstring> header. Don't define your own functions if there is already a known one in the C++ standard library.
You have to reduce the answer size in your recursion. In other words, try to reduce the size of your string (ntca) in order to stop infinite recursion. Or try to add a parameter to control the recursion like this:
long slength (const char ntca[], int n) //Look from n to the end of string for '\0'
{
if (ntca[n] == '\0')
return n; //the index of char '\0' indicates the length of string
else
return slength(ntca, n+1); //go, check the next char
}
So you always have to call this function as follows:
x = slength(s, 0)

Debug Assertion Failed! String manipulation using pointer arithmetic

EDIT: Pastebin links to the entirety of the code at the bottom
for my CS215 course, I was given a class called String215 which is a basic string class to help in the understanding of dynamic memory allocation and pointer arithmetic with char arrays.
The class was given to me in a very basic skeleton form with prototypes but no implementations, along with a test function to test my implementations. I CAN NOT use any C String functions in this assignment.
The part of the program which is troubling is the append function, which just appends a parameter string215 object to the end of the current string215 object.
// Add a suffix to the end of this string. Allocates and frees memory.
void string215::append(const string215 &suffix)
{
char *output = new char[str_len(data)+suffix.length()+1];
for(int x = 0; x < str_len(data); x++) {
*output = *data;
output++;
data++;
}
for(int x = 0; x < suffix.length(); x++) {
*output = suffix.getchar(x);
output++;
}
*output = '\0';
output -= (str_len(data)+suffix.length()+1);
delete[] data;
data = output;
}
This portion of the code is tested in the 13th test of the test function as shown here:
string215 str("testing");
...
// Test 13: test that append works in a simple case.
curr_test++;
string215 suffix("123");
str.append(suffix);
if (strcmp(str.c_str(), "testing123") != 0) {
cerr << "Test " << curr_test << " failed." << endl;
failed++;
}
Here is the description of the append class:
Add the suffix to the end of this string. Allocates a new, larger, array; copies the old contents, followed by the suffix, to the new array; then frees the old array and updates the pointer to the new one.
My program aborts at the very end of the append function execution with the error message:
Debug Assertion Failed!
Program: [Source path]\dbgdel.cpp
Line: 52
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
...
Abort || Retry || Ignore
I'm fairly certain it has something to do with my very poor memory management. I know it's not a lot to go on, but I've been struggling with this for hours on end and can't seem to figure it out.
Here's a pastebin of the .cpp and .h file for this program
string215.cpp: http://pastebin.com/Xh2SvDKJ
string215.h: http://pastebin.com/JfAJDEVN
Any help at all is greatly appreciated!
Thanks,
RAW-BERRY
You are changing data pointer before delete[]. You need to delete[] exactly the same value you got from new[].
Also, you are incrementing output pointer str_len(data)+suffix.length() times, and you take it back by str_len(data) + suffix.length() + 1.
I would use separate variables for iteration to solve these problems.
You increment output exactly str_len(data) + suffix.length() times. Note that you don't increment output after *output = '\0';.
So to go back to the start, you should use:
output -= (str_len(data) + suffix.length());
By the way, some of the code is not very efficient. For example, getchar uses a loop instead of simply returning data[index]. You use getchar in append, which means that the performance isn't great.
EDIT: As zch says, you use delete[] data after modifying data, but note that even before that you use str_len(data) after modifying data (when deciding how many bytes to go skip back), so the calculation is wrong (and my suggestion above is also wrong, because str_len(data) is now zero).
So I think your problem is with the line
for(int x = 0; x < str_len(data); x++) {
Notice that the size of 'data' is changing at each iteration of the loop. As you increment 'x', you are decreasing the length of 'data'. Suppose 'data' is a string holding "hello": in the first iteration of the loop x=0 and str_len(data)=5; in the second iteration x=1 and str_len(data)=4. Thus the for loop executes half as many times as you need it to and 'data' does not end up pointing to the end of the data string

trying to sort a simple string in c++

#include "stdio.h"
#include "conio.h"
#include <iostream>
using namespace std;
int main (void)
{
char my_char[] = "happy birthday";
int i;
bool j=false;
char my_char_temp[1];
do
{
for (i=0;i<sizeof(my_char)-2;i++)
{
j=false;
if (my_char[i+1] < my_char[i])
{
my_char_temp[0]=my_char[i+1];
my_char[i+1] = my_char[i];
my_char[i] = my_char_temp[0];
j=true;
}
}
}while (j);
cout << my_char;
}
What am I doing wrong?
I'm just trying to sort the letters within the char.
The output I get is completely wrong.
You want to use strlen() rather than sizeof.
You are resetting j to false each and every time you compare two characters.
This means that, if you swap two characters, and you are NOT at the end of your array, you will forget that you have swapped them.
Move the j=false; from inside the for-loop to just inside the do-loop.
And you owe me a bottle of Jack for saving your ass on a homework assignment on Sunday afternoon.
I don't know what are you trying to implement with your sizeof(...) - 2 and etc, but what you probably want to get can be done this way:
#include <iostream>
#include <algorithm>
int main() {
std::string s("happy birthday");
std::sort(s.begin(), s.end());
}
Consider what happens inside this loop:
for (i=0;i<sizeof(my_char)-2;i++)
If you find a pair of values to swap, setting j to true, you'll continue iterating through that loop, and set j back to false on the next iteration. As a result, the program is going to exit as soon as the last two characters in the string are in sorted order, regardless of whether the rest of the string is sorted.
Instead, as soon as you find a pair of characters to swap, you want to start over again at i=0. The simplest way to do that is add a break; statement after your j = true line. With that fix, this works correctly.
Alternately, you could move the initial j = false line outside the loop, which would solve the problem in a slightly different way.
You are actually very close. The only problem is that
j=false;
needs to be in the outer loop. As is, j is cleared every time the inner loop executes.
With this fix, your program works fine for me.
Stylistic errors, however, are another story.
I could be mistaken but it looks like you're trying to do a bubble sort?
And it's i < sizeof(my_char)-2 because he's using a 0-based, null terminated string, and he doesn't want to sort the null terminator.
Try just repeating the condition of the inner loop, using j instead of i, and see if that works? Note that this has a run time of O(n^2) and you can get sorts down much much faster than that if you need to. Alternately you can move the boolean out of the for and into the do loop.
for (i=0;i < sizeof(my_char)-2;i++)
for (i=0;i<sizeof(my_char)-2;i++)
{
if (my_char[i+1] < my_char[i])
{
my_char_temp[0]=my_char[i+1];
my_char[i+1] = my_char[i];
my_char[i] = my_char_temp[0];
}
}