C++ not printing as expected with my own string copy function - c++

sorry for another string copy question.. but I really can't find the reason why in my code, strTo can be printed, but strFinal can't in neither way.
cout << strTo << endl;
cout << strFinal << endl;
while (*strFinal != '\0') {
cout << *strFinal++;
}
Appreciated if someone can point it out where I misunderstood about pointers and arrays! Thanks!
#include <iostream>
using namespace std;
char *str_copy (const char *strFrom, char *strTo)
{
while (*strFrom != '\0') {
*strTo++ = *strFrom++;
}
*strTo = '\0';
return strTo;
}
int main()
{
char strFrom[]="abc123";
char strTo[10];
char *strFinal = str_copy(strFrom, strTo);
cout << strTo << endl;
cout << strFinal << endl;
while (*strFinal != '\0') {
cout << *strFinal++;
}
return 0;
}
Additional Question:
I don't know the reason when I put the code in main function like this:
char strFrom[]="abc123";
char strTo[10];
strTo = str_copy(strFrom, strTo);
Then complier said:
main.cpp:18: error: array type 'char [10]' is not assignable
strTo = str_copy(strFrom, strTo);
~~~~~ ^
How should I correct in this way? Thanks!

The function returns a pointer to the terminating zero.
char *str_copy (const char *strFrom, char *strTo)
{
//...
*strTo = '\0';
return strTo;
}
Change it the following way
char *str_copy (const char *strFrom, char *strTo)
{
char *p = strTo;
while ( *p++ = *strFrom++ );
return strTo;
}
Also I would declare it the same way as standard C function strcpy is declared
char *str_copy( char *strTo, const char *strFrom );
As for your additional question then you may not assign a pointer or even other array to an array. So the compiler issues the error.
Arrays have no the assignment operator. You can only copy their elements.
Otherwise use standard class std::array.

After returning from str_copy you strTo does not point to the beginning of your copied string. In main strTo is ok, because it was passed by value (address of pointer after returning from str_copy is not changed even though you were using strTo++). But returned value of strFinal points to last character of copied string - '\0'.
For second part - char[10] has unchangeable addres, so you can't assign anything to variable of this type, like you tried in strTo = str_copy(...);.

Your second question : you are trying to assing char[10] with char* which is not possible
&strTo[0] = str_copy(strFrom, strTo);
But it's not usefull since the copy is done inside

In ur code, after calling str_copy() function:
char *strFinal = str_copy(strFrom, strTo);
strFinal points to the '\0', which is at the end of "abc123".
strTo in main() function can display correctly, because it is not THE SAME strTo
in str_copy() function, but points to strTo[10]. strTo in str_copy() still points to the terminating zero.

Related

Pass char array on to a function C++

My goal is to take in a character array and replace specific words such as "class" with the word "video". However, the data in buf array is coming from a web server that has unicode in it, so to my knowledge, I am not allowed to convert the char array into a string because it will mess up much of the data in it (I think).
So, my main question is, how do I pass buf in as an argument to the replaceWords function. Right now I get an error that says,
error: incompatible types in assignment of ‘char*’ to ‘char [256]’
char buf[256];
buf = replaceWords(buf);
char * replaceWords(char* buf) {
char badWord1[] = "class";
char * occurrence = strstr(buf, badWord1);
strncpy(occurrence, "video", 5);
return buf;
}
The error is caused by buf = replaceWords(buf);. This tries to assign the function return value (char*) to an array and that's not valid syntax.
Your code passes the array to the function and the function changes the character string in-place. You don't need the return value from the function. In fact, the function could just be defined as returning void and then you can remove the return statement.
Note: you should probably add some error checking. What happens if the badWord1 string is not found and strstr() returns NULL?
Look at this code:
#include <bits/stdc++.h>
using namespace std;
void replaceWords(char buf[]) {
char badWord1[] = "class";
char * occurrence = strstr(buf, badWord1);
strncpy(occurrence, "video", 5);
}
int main() {
char temp[5];
temp[0] = 'c';
temp[1] = 'l';
temp[2] = 'a';
temp[3] = 's';
temp[4] = 's';
replaceWords(temp);
cout << temp << endl;
return 0;
}
It will work as you intend. When you pass char buf[] you are passing a reference to the array you want to modify. That way you can modify it in the function and it will be modified everywhere else in the program. There's not need to do additional assignment.

Combine sizeof string and chararcter

The last 2 cout statements have the same size. why?
int main()
{
char ch=127;
cout<<sizeof(ch)<<endl; //Size=1
cout<<sizeof("Hello")<<endl; //Size=6
cout<<sizeof("Hello"+ch)<<endl; //Size=8
cout<<sizeof("HelloWorld"+ch)<<endl; //Size=8
return 0;
}
Please explain.
Thanks
When you do "Hello"+ch the array containing the string "Hello" decays to a pointer to its first element, and you add ch to this pointer.
The result of pointer arithmetic is a pointer, which is what you get the size of.
Equivalent code would be something like
char const hello[] = "Hello";
char const* phello = hello; // equivalent to &hello[0]
char const* result = phello + ch;
cout << sizeof(result) << endl;

Is there a way I can use a function to return the memory location of an array element?

I just started learning about pointers so I'd thought I'd share what I'm trying to do. Of a character array (let's call it c and it's equal to "Hello"), I'm trying to return the memory location of a certain element. Say the memory of location of 'l'. Here's what I have so far:
#include <iostream>
using namespace std;
char* str_char(char* c_ptr, char c);
int main()
{
char *c = "Hello";
cout << str_char(c, 'l') << endl;
return 0;
}
char* str_char(char* c_ptr, char c)
{
for (int i = 0; i < sizeof(c_ptr); i++)
{
if (*(c_ptr + i) == c)
{
return (c_ptr + i);
break;
}
}
}
After I use the function, it outputs "llo".
You are on the right track. However, there are a few things that are not right.
Use of sizeof(c_ptr) is not right. It works for your case due to happy coincidence.
sizeof(c_ptr) is equal to sizeof(char*). It is not equal to the size of the array from the calling function.
There is a missing return statement at end of the function -- the case where c is not found in c_ptr.
There is no need of the break; after the return;.
Also, you can simplify the function a little bit.
Here's an updated version:
char* str_char(char* c_ptr, char c)
{
for (char* cp = c_ptr; *cp != '\0'; ++cp )
{
if (*cp == c)
{
return cp;
}
}
return nullptr;
}
The earlier answer has covered the bugs, so I'll just answer the actual question...
The function does return the location of an array element.
The << operator treats every char* as a pointer to a zero-terminated string, and outputting the result of str_char works exactly like outputting c; it prints every character after that location until it encounters a zero.
If you want to output the value of the location itself, you need to cast it to a different type:
cout << static_cast<void*>(str_char(c, 'l')) << endl;
as << has an overload for void* that outputs the address itself.
R Sahu gave you answer that is slightly modified version of your function . That is legal code, but that is basicly a C code, except use of nullptr. Returning nullptr is non-canon and if nupllptr will be returned, what << operator would do? That's undefined behavior.
it is often agreed pattern to leave iterator (pointer) pointing at end of line (at the terminating zero) to avoid crash you may cause by returning nullptr.
char* str_char(char* c_ptr, char c)
{
char* cp = c_ptr;
for (; *cp != '\0'; ++cp )
{
if (*cp == c)
{
return cp;
}
}
return cp;
// if cp was declared inside scope , we can't retirn it's value
}
Normally you do not need to write own string functions.. bth C library and C++ got them already covered. C++ got set of abstract algorithmic functions, in your case a strchr, find or find_if is prudent:
#include <algorithm>
#include <iostream>
using std::cout;
int main()
{
char *c = "Hello";
cout << std::strchr(c, 'l') << '\n';
// with pointer to null-terminated string, strlen searches
// for zero char and returns the count of characters before it
cout << std::find(c, c + strlen(c), 'l') << '\n';
// with declared array we can use std:begin and std::end
char carr[] = "Hello";
cout << std::find(std::begin(carr),std::end(carr) , 'l') << '\n';
// with pointer to null-terminated string a lambda expression
// can be used to stop at 0 as well as at first key
const char key = 'l';
cout << std::find_if(c, c + strlen(c),[=](const char& item)
{
return (item == key) || (item == '\0');
}) << '\n';
return 0;
}
An std::vector or ::array or other containers can be used with those templates as well.
The <algorithms> header would save tons of time you need to debug your custom-tailored functions for search, iteration, etc.
P.S. cout and cin deal with char and char* in special way.. char* is always pointer at string, char is always a character, not a number, so casts are required if you mean otherwise.

Passing structure by reference and assign string

Here is a simple program where I am trying to pass a structure to a function by reference and a string. The function is supposed to detect the length of the string and assign it a member of the structure. Here is the program:
#include <iostream>
#include <string.h>
struct stringy // structure definition
{
char *str;
int ct;
};
void set(stringy &beany, const char *testing); // function definition
int main()
{
stringy beany;
char testing[] = "Reality isn't what it used to be.";
set(beany, testing); // function call
return 0;
}
void set(stringy &beany, const char *testing) // function prototype
{
int i=0;
while (*(testing+i) != '\0') // this loop counts the number of characters
{
i++;
std::cout << i << "\n";
}
beany.str = new char[i]; // dynamic storage allocation
std::cout << strlen(beany.str); // printing the length of the string
}
For some reason the output of the last line in the function set() is 47 while the value of "i" is 33. The last 15 bytes are filled with garbage value. I want that the length of beany.str should be equal to the length of *testing.
You allocate memory for beany.str but you don't initialize that memory. The contents of the allocated memory, without any initialization, is indeterminate (and in practice will be seemingly random).
Also don't forget that old C-style strings needs to be terminated by the special '\0' character (or functions like strlen will not work).
Both of these problems, using uninitialized memory and forgetting the terminator, will lead to undefined behavior.
beany.str = new char[i]; // dynamic storage allocation
std::cout << strlen(beany.str); // printing the length of the string
strlen looks for the terminating null character '\0'. There is no guaranteed one in beany.str, because you assign it the result of new char[i], which does not zero-initialize the elements. It allocates space for i characters that are not initialized to zero.
Even if they were, strlen would return 0, because it would immediately find '\0' at the first position. If you don't somehow remember i yourself, the size information will be lost.
Look at the output of the following program:
#include <iostream>
int main()
{
char *str = new char[100];
for (int i = 0; i < 100; ++i)
{
std::cout << str[i] << "\n";
}
}
The behaviour is undefined. What you will probably see are some seemingly random characters.
If you want zero-initialization, use new char[i]().
But still, strlen will be 0:
#include <iostream>
#include <string.h>
int main()
{
char *str = new char[100]();
for (int i = 0; i < 100; ++i)
{
std::cout << str[i] << "\n";
}
std::cout << strlen(str) << "\n";
}
You should just get rid of array-new and array-delete. Use std::string.

Dynamic Object in c++ doesn't work

#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
class STRING {
private:
char *S[10];
public:
STRING();
void set_str(int n, const char* str1);
char* get_str(int n);
};
STRING :: STRING(){
for (int i=0; (i < 9); i ++ ){
S[i] = '\0';
cout << S[i];
}
}
void STRING :: set_str(int n,const char*str1) {
S[n] = (char*)malloc(strlen(str1 + 1));
strcpy(S[n], str1);
cout << S[n];
}
char* STRING :: get_str(int n){
return S[n];
}
int main () {
cout << " Init \n";
STRING* str = new STRING();
cout << "Error \n";
return 0;
This program compiles successfully, runs, but when it runs it only works before the inicialization of object STRING* str = new STRING();. So I can't see in this case Error message. Could someone point me my mistake, please?
And if there is a better way to initialize the array of strings, I would be happy to know.
My goal is to initialize tha array of stings. And initially set values of the whole array to NULL.
Regards
Assuming STRING means "a collection of 10 strings", then it's your constructor. You are setting the pointers to the value of the character '\0' and not to a null pointer. You're assigning a char type to a char* type. Now that may work, but then you have the cout statement. And it tries to DEREFERENCE the pointer. But the pointer is pointing to wherever in memory '\0' is, not a null character at that point.
Edit: In response to the OP's question, here's how I think it should be done for initializing to 10 empty char arrays. Your constructor will change to:
STRING :: STRING(){
for (int i=0; i < 10; i ++ ){ // changed to 10. 9 would miss the 10th element
S[i] = new char[1]; // Length-1 char array
S[i][0] = 0; // or '/0' or whatever
cout << S[i]; // Prints nothing
}
}
Also you need a destructor to free the memory:
STRING::STRING~()
{
for(int i = 0; i < 10; i++) {
delete [] S[i];
}
And change your "set" method to use "new" and not "malloc". Or everything to malloc and free. But don't mix them. And remember to use "array delete" and not just delete.
And FTLOG, go to and bookmark this link. Use the built-in string class.
The correct declaration of the member should be:
char S[10];
The way you have it
char *S[10];
declares an array of 10 char *. So when you do S[i] = '\0';, you're initializing S[i], which is a pointer to a char, to '\0', which is probably NULL, so you're basically calling cout << NULL on the next line.