Cstrings in C++ - c++

why this code gives the wrong output?? Output is 5 and 9, shouldn't it be 5 and 4.
Here is the code
int main
{
char a[10] ={'a','b','c','d','e'};
char c[] = {'q','t','y','t'};
cout<<strlen(c)<<endl<<strlen(a);
return 0;
}

You have undefined behaviour, because you're calling strlen with a pointer to a character array that is not null-terminated (c). You need to pass null-terminated strings for this to work. This is an example, fixing that and some other errors, and including the required headers:
#include <iostream> // std:cout, std::endl
#include <cstring> // std::strlen
int main()
{
char a[10] ={'a','b','c','d','e'}; // OK, all remaining elements
// initialized to '\0'.
// Alternative: char a[10] = "abcde"
char c[] = {'q','t','y','t', '\0'}; // or char c[] = "qtyt";
std::cout << std::strlen(c) << std::endl;
std::cout << std::strlen(a) << std::endl;
}

c needs a null character at the end for strlen to work.
You can use
char c[N] = {'q','t','y','t'};
where N is 5 or greater.
or
char c[] = {'q','t','y','t', '\0'};
or
char c[] = "qtyt";
to add a null character at the end of c.

Related

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;

strlen show wrong the number of array's elements

void main() {
char str1[4] = { 'A','B','C','D' };
char str2[3] = { 'A','B','D' };
cout << strlen(str2)
}
the results is 31, and I don't know why it happens
You need nul-terminators on your C-style strings.
#include <iostream>
#include <cstring>
int main() {
char str1[4+1] = { 'A','B','C','D', '\0' }; // same as = "ABCD"
char str2[3+1] = { 'A','B','D', '\0' }; // same as = "ABD"
std::cout << std::strlen(str2) << '\n';
}
C strings (as in arrays of chars) by standard are arrays which terminating character is '\0'.
When you assign a string like this:
char* a = "hello";
it's equivalent to:
char a[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
This kind of string works with strlen and similar (strcpy, strthis, strthat).
In C++ you should rather use the type String that you get including string. It's a class and you can use the functions of that class
#include <string>
...
std::string a = "hello";
int size = a.size();
When you do strlen of an array (actually the address for the first character), the strlen function iterates in your memory until it finds a \0, even if it goes out of your array and into whatever other data is in your memory.
The 31 you got means your strlen was going on for 31 times the size of a char in your memory before it finally met a \0 byte.

Reversing a string in C++ using pointers

void reverse(char[] x) {
char* pStart = x;
char* pEnd = pStart + sizeof(x) - 2;
while(pStart < pEnd) {
char temp = *pStart;
*pStart = *pEnd;
*pEnd = temp;
pStart++;
pEnd--;
}
}
int main() {
char text[] = ['h','e','l','l','o'];
reverse(text);
cout << text << endl;
return 0;
}
I am new to C++ and stack overflow.
I am trying to reverse a string using pointers... I don't quite understand what I did wrong. Please help me out.
Additional question: What is the difference between a string and an array of characters?
sizeof(x) with x being a parameter of type char[] of a function does not give you the number of characters in the string but the size of a char*, probably 8 on a 64 bit system. You need to pass a C-String and use strlen(x) instead. Write char text[] = {'h','e','l','l','o','\0'} or char text[] = "hello" in main.
Note that sizeof() needs to be evaluatable at compile time; this is not possible on arrays with undetermined size like char[]-typed function arguments. When using sizeof on a variables like your char text[] = {'h','e','l','l','o'}, however, sizeof(text) will result in the actual size of the array.
char x[] is the same as char* x and the sizeof(x) is therefore the size of a pointer. So, because you cannot calculate the size of an array outside of the block it is declared in, I would eliminate that part from your function.
It would be much easier to provide the function with pointers to the first and last characters to be replaced:
void reverse(char* pStart, char* pEnd)
{
while (pStart < pEnd)
{
char temp = *pStart;
*pStart = *pEnd;
*pEnd = temp;
pStart++;
pEnd--;
}
}
So now it is quite easy to call this function - take the address (using ampersand &) of the the relevant characters in the array: &text[0] and &text[4].
To display an array of characters, there is a rule, that such "strings" HAVE to have after the last character a NULL character. A NULL character can be written as 0 or '\0'. That is why it has to be added to the array here.
int main()
{
// char text[] = "hello"; // Same like below, also adds 0 at end BUT !!!in read-only memory!!
char text[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
reverse(&text[0], &text[4]);
std::cout << text << std::endl;
return 0;
}

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;
}

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.