increase array with char* [C++] - c++

I'm dealing with dynamic arrays in C++. Help with the following code.
I'm trying to read the characters one by one and make the C-string. If the array size is not enough, I increase it. But the function increaseArray works with an error and returns a string with other characters. What I am wrong?
void increaseArray(char* str, int &size){
char* newStr = new char[size * 2];
for (int i = 0; i < size; i++){
newStr[i] = str[i];
}
size *= 2;
delete[] str;
str = newStr;
}
char* getline()
{
int size = 8;
char* str = new char[size];
char c;
int index = 0;
while (c = getchar()) {
if (index == size) increaseArray(str, size);
if (c == '\n') {
str[index] = '\0';
break;
};
str[index] = c;
index++;
}
return str;
}

In function increaseArray you are assigning newStr to str however str is local copy of pointer in increaseArray function thus change is not visible outside it.
Simplest fix is to change increaseArray signature to:
void increaseArray(char*& str, int &size)
So reference to pointer will be passed, thus changes to str inside increaseArray will be visible outside it.

You could do that.
Its simple..
#include <string.h>
#include <stdlib.h>
using namespace std;
void increaseArray(char* &str, int size){
str = (char *)realloc(str,size*2);
}

Related

*char conversion to/from bool in call to strstr

I have code that is supposed to remove all characters in one C-string from another.
The problem arises when I try to use the function strstr: both an array and a char* get converted to bool. Obviously it doesn't work because strstr needs to receive 2 char* arguments.
#include <iostream>
#include <ctype.h>
#include <string.h>
#include <malloc.h>
using namespace std;
char* temp_char(char* orig,char* del)
{ char *str_temp, *temp, *p, *c;
char symbol[2];
int i=0;
int len = strlen(orig);
temp=(char *)calloc(len,1);
str_temp = (char *)calloc(len,1);
strcpy(str_temp,orig);
for(i=0;i<strlen(del);i++){
symbol[0]=del[i];
symbol[1]=0;
temp[0]=0;
while( p=strstr(str_temp,del)!=NULL){
strncat(temp,str_temp,p-str_temp);
p++;
str_temp=p;
}
strcat(temp,str_temp);
strcpy(str_temp,temp);
}
cout<<temp;
return temp;
}
int main () {
char a[]="stuccsess",b[]="test";
temp_char(a,b);}
Any help would be appreciated.
You have two errors in one line of your code. The first is not addressing the issue that the != operator has higher priority than =. Thus, in the following line:
while( p=strstr(str_temp,del)!=NULL) {
the comparison is actually:
while( p = ( strstr(str_temp,del)!=NULL ) ){
So, you are attempting to assign the result of the != test, which will be a bool value, to a char* variable (p).
You can fix this, easily, by putting the assignment expression in parentheses.
However, although that will fix the compiler error, it will not address the second error. Just a few lines above that while statement, you assign one of the characters of the del string to the first of the symbol string (and, properly, add a nul terminator to that) … but you never then actually use that symbol string. Instead, you pass the entire del string as the second argument in the call to strstr. You should be passing your created symbol as that second argument.
So, changing that while line to the following will make the code work:
while ((p = strstr(str_temp, symbol)) != nullptr) { // Use nullptr in C++
But that leaves other errors in your function. How will you ever be able to free the memory allocated in the str_temp = (char*)calloc(len, 1); call? Once you have subsequently modified that str_temp pointer (in the str_temp = p; line), you no longer have the original pointer value, which must be used when calling free(). So, you need to save that value, just after you have made the allocation. (The temp memory pointer is returned, so that can be freed in the main function.)
There are other issues in your code that could be improved, like using new[] and delete[] in C++, rather than the old, C-language calloc, and that your index and length variables should really be of size_t type, rather than int. Here's a version with the corrections and suggestions discussed applied:
#include <iostream>
#include <cstring>
using std::cout;
char* temp_char(char* orig, char* del)
{
size_t len = strlen(orig);
char* temp = new char[len + 1];
char* str_temp = new char[len + 1];
char* save_temp = temp; // Save it so we can call delete...
strcpy(str_temp, orig);
for (size_t i = 0; i < strlen(del); i++) {
char symbol[2];
symbol[0] = del[i];
symbol[1] = 0;
temp[0] = 0;
char* p;
while ((p = strstr(str_temp, symbol)) != nullptr) {
strncat(temp, str_temp, static_cast<size_t>(p - str_temp));
p++;
str_temp = p;
}
strcat(temp, str_temp);
strcpy(str_temp, temp);
}
cout << temp;
delete[] save_temp; // ... don't forget to free this.
return temp;
}
int main()
{
char a[] = "stuccsess", b[] = "test";
char* answer = temp_char(a, b);
delete[] answer; // We should free the memory allocated!
return 0;
}
But your approach is far more complicated than it need be. You can simply loop through the original string and check each character to see if it is in the 'delete' string (using the strchr function, for example); if it is not (i.e. that strchr returns nullptr), then append the character to the accumulated temp and increase the running length:
char* temp_char(char* orig, char* del)
{
size_t len = strlen(orig);
char* temp = new char[len + 1];
int newlen = 0;
for (char* cp = orig; *cp != '\0'; ++cp) {
if (strchr(del, *cp) == nullptr) temp[newlen++] = *cp;
}
temp[newlen] = '\0'; // Add null terminator
std::cout << temp;
return temp;
}

C++ Combining two zero terminated strings?

So I am doing a question where I have to join two zero terminated strings, the first contains a word, and the second is empty and twice the size of the original array. I was able to get this working using the following code
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
char str1[] = "test";
char str2[(sizeof(str1)-1)*2];
char *p;
int count = 0;
for(p = str1; *p != 0; p++) {
str2[count] = *p;
count++;
}
cout << str2;
}
However I have to use a function with the following prototype
char *combine(char *a);
So I tried this
#include <stdio.h>
#include <iostream>
using namespace std;
char *copy_and_reverse(char *a) {
char str2[8];
int count = 0;
char* b = str2;
for(a; *a != 0; a++) {
str2[count] = *a;
count++;
}
return b;
}
int main()
{
char str1[] = "test";
char *a;
a = str1;
char* b = copy_and_reverse(a);
for(b; *b != 0; b++) {
cout << *b;
}
}
But it does not work (it is printing the string but it's printing a few random characters after it), I'm getting so confused with the pointers, can anyone help me out with this?
Edit: here is the question I am trying to answer
Write a function in C++ that takes as a char * style zero terminated string and returns a char* string twice the length of the input. The first half of the returned string should contain a copy of the contents of the original array. The second half of the string should contain the contents of the original string in reverse order.
The function should have the following prototype:
char *copy_and_reverse(char* a);
Note: you should not use any library functions (e.g from string.h).
There are two big problems in your copy_and_reverse code.
After copying the input string, you are not terminating the result. This means str2 is not a valid string. Fix:
str2[count] = '\0'; // after the loop
copy_and_reverse returns a pointer to a local variable (str2). After the function returns, all its local variables are gone, and main is dealing with an invalid pointer. To fix this, either use static memory (e.g. by declaring str2 as static or making it a global variable) or dynamic memory (allocate storage with new[] (or malloc())). Both approaches have their disadvantages.
Minor stuff:
variable; does nothing (see for (a; ...), for (b; ...)).
str2 isn't big enough for the final result. str1 is 5 bytes long ('t', 'e', 's', 't', '\0'), so char str2[8] is sufficient for now, but in the end you want to allocate length * 2 + 1 bytes for your result.
I believe that this will suit your needs:
#include <stdio.h>
#include <stdlib.h>
static char* copy_and_reverse(char* a);
static int strlen(char *c); // self-implemented
int main(void) {
char *a = "some string";
char *b = copy_and_reverse(a);
printf("%s", b);
free(b);
return 0;
}
static char* copy_and_reverse(char* a) {
int n = strlen(a);
char *b = new char[n * 2 + 1]; // get twice the length of a and one more for \0
for (int i = 0; i < n; ++i) { // does copying and reversing
b[i] = a[i];
b[i+n] = a[n-i-1];
}
b[2 * n] = '\0'; // null out last one
return b;
}
static int strlen(char *c) {
char *s = c;
while( *s++ );
return s-c-1;
}

Swap 2 char of a C++ array

I have a problem with memory access. When i = 0, Visual Studio throws an exception with reference to a line as labelled in the following code.
Can't access at 0x00AD8B3B and 0x00AD8B3B equals scr+np-i
How can I fix the for-loop body so as to fix this issue?
int o_strrev(char* scr)
{
int np = strlen(scr) - 1;
char tmp;
if (!scr) return -1;
if (!*scr) return -1;
for (int i = 0; i < np / 2; i++)
{
tmp = scr[np-i];
scr[np-i] = scr[i]; # this line
scr[i] = tmp;
}
return 0;
}
As pointed out by #Revolver_Ocelot, you are probably passing a const char* from a string literal. Since these are, by definition, constant, you can't modify them in the way you're trying to. You need some way to convert const char* into a non constant char*. Something along these lines will work for you:
string str = "string";
char* cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
I've compiled your code in g++ using non constant char* and it works fine. Just remember to deallocate your char* when you're done with it. We don't want memory leaks ;)
I see you are trying to reverse a string.
Might I suggest a simpler way
void reverse(char *string_var)
{
int length, c;
char *begin, *end, temp;
length = strlen(string_var);
begin = string_var;
end = string_var;
for (c = 0; c < length - 1; c++)
end++;
for (c = 0; c < length/2; c++)
{
temp = *end;
*end = *begin;
*begin = temp;
begin++;
end--;
}
}
Make sure you pass character array of the form
char word[64]
Or maybe by recursion
void reverse(char *x, int begin, int end)
{
char c;
if (begin >= end)
return;
c = *(x+begin);
*(x+begin) = *(x+end);
*(x+end) = c;
reverse(x, ++begin, --end);
}
You're most likely calling o_strrev with a string literal, some thing like:
o_strrev("This ain't gonna work!");
This will compile with most compilers and at most generate a warning. Try cranking up your warning level.
Instead, you want to make a dynamic copy of your string on the heap and work with a char* pointer to that, something like:
string str = "This is gonna work!!"
size_t len = str.size();
char* my_string = new char[len + 1];
strncpy(my_string, str.data(), len)
my_string[len] = '\0';
o_strrev(my_string);
// ...
delete[] my_string;

c++ assign char values (by using stack pop) to char*

I am trying to reverse a char* by using a stack.
stack<char> scrabble;
char* str = "apple";
while(*str)
{
scrabble.push(*str);
str++;
count++;
}
while(!scrabble.empty())
{
// *str = scrabble.top();
// str++;
scrabble.pop();
}
In the second While-loop, I'm not sure how to assign each char from the stack's top to the char* str.
When you have a string defined using
char* str = "apple";
you are not supposed to change the value of the string. Changing such a string causes undefined behavior. Instead, use:
char str[] = "apple";
In the while loops, use an index to access the array instead of incrementing str.
int i = 0;
while(str[i])
{
scrabble.push(str[i]);
i++;
count++;
}
i = 0;
while(!scrabble.empty())
{
str[i] = scrabble.top();
i++;
scrabble.pop();
}
You can also iterate a pointer to the char[] if you'd like
char str[] = "apple";
char* str_p = str;
int count = 0;
while(*str_p)
{
scrabble.push(*str_p);
str_p++;
count++;
}
// Set str_p back to the beginning of the allocated char[]
str_p = str;
while(!scrabble.empty())
{
*str_p = scrabble.top();
str_p++;
scrabble.pop();
}

I get a number 2 when I reverse my string

I wrote this code to reverse strings. It works well, but when I enter short strings like "american beauty," it actually prints "ytuaeb nacirema2." This is my code. I would like to know what is wrong with my code that prints a random 2 at the end of the string. Thanks
// This program prompts the user to enter a string and displays it backwards.
#include <iostream>
#include <cstdlib>
using namespace std;
void printBackwards(char *strPtr); // Function prototype
int main() {
const int SIZE = 50;
char userString[SIZE];
char *strPtr;
cout << "Please enter a string (up to 49 characters)";
cin.getline(userString, SIZE);
printBackwards(userString);
}
//**************************************************************
// Definition of printBackwards. This function receives a *
// pointer to character and inverts the order of the characters*
// within it. *
//**************************************************************
void printBackwards(char *strPtr) {
const int SIZE = 50;
int length = 0;
char stringInverted[SIZE];
int count = 0;
char *strPtr1 = 0;
int stringSize;
int i = 0;
int sum = 0;
while (*strPtr != '\0') {
strPtr++; // Set the pointer at the end of the string.
sum++; // Add to sum.
}
strPtr--;
// Save the contents of strPtr on stringInverted on inverted order
while (count < sum) {
stringInverted[count] = *strPtr;
strPtr--;
count++;
}
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
cout << stringInverted << endl;
}
Thanks.
Your null termination is wrong. You're using == instead of =. You need to change:
stringInverted[count] == '\0';
into
stringInverted[count] = '\0';
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
Should use = here.
What is wrong with your code is that you do not even use strlen for counting the length of the string and you use fixed size strings (no malloc, or, gasp new[]), or the std::string (this is C++)! Even in plain C, not using strlen is always wrong because it is hand-optimized for the processor. What is worst, you have allocated the string to be returned (stringInverted) from the stack frame, which means when the function exits, the pointer is invalid and any time the code "works" is purely accidental.
To reverse a string on c++ you do this:
#include <iostream>
#include <string>
int main() {
std::string s = "asdfasdf";
std::string reversed (s.rbegin(), s.rend());
std::cout << reversed << std::endl;
}
To reverse a string in C99 you do this:
char *reverse(const char *string) {
int length = strlen(string);
char *rv = (char*)malloc(length + 1);
char *end = rv + length;
*end-- = 0;
for ( ; end >= rv; end --, string ++) {
*end = *string;
}
return rv;
}
and remember to free the returned pointer after use. All other answers so far are blatantly wrong :)