Why doesn't while (*s++=*t++); work for me? - c++

I came across this function on a blog and I found it really cool. I understand how it works conceptually since C++ was my first language.
However, when I tried actually writing it out in a program of mine, it doesn't seem to work. I've googled all over but I've only found explanations as to how it works so I've been really stumped.
Instead of copying the NULL char[5] (which should evaluate to false, copy nothing and break the loop), it gives two compilation errors, saying that "I can't increment value of type char[6]" (out-of-bounds error for both arrays).
Why doesn't my loop break at char[5]?
I'm guessing it's something to do with the subtleties of char and string, I tried initialising strings instead with cstring included, that didn't work either, the similar error of "cannot increment type string" shows up.
#include <iostream>
using namespace std;
int main () {
char s[] = "hello";
char t[] = "house";
while (*s++ = *t++);
cout << s;
return 0;
}

You can't increment an array. What would that even mean?
Try this:
#include <iostream>
using namespace std;
int main ()
{
char s[] = "hello";
char t[] = "house";
char *ss = s;
char *tt = t;
while (*ss++ = *tt++);
cout << s << endl;
}

The line " while (*ss++ = *tt++) " is always going to be true, because = is the assignment operator. You probably want " while (*ss++ == *tt"")", which compares equality.

Related

Vector of an array of structs resets strings to be blank. C++

So I'm having a very confusing issue where I'm attempting to print a string from a vector of arrays of structs to the console. Integers print just fine however strings stored within these structs get set to "". I have no idea what's going on here but after setting up a test as shown bellow this issue is still persisting. Any help figuring this out would be greatly apricated.
Should also mention I'm still new to c++ so I apologise if the issue here is something simple.
#include <iostream>
#include <string>
#include <vector>
#include "Header.h"
//Test struct
struct testStruct
{
string testString;
int testInt;
};
testStruct testArray[1] = {
testArray[0] = {"String works", 69}
};
int main()
{
srand(time(NULL));
vector < testStruct > test;
test.push_back({ testArray[0] });
cout << test[0].testString << "\n"; // prints "", should print "String works"
cout << test[0].testInt << "\n"; // prints 69
characterCreation();
checkPlayerStats();
introduction();
return 0;
}
This surprised me. The following code is legal (syntactically at least)
testStruct testArray[1] = {
testArray[0] = {"String works", 69}
};
but if you replace it with the sensible version
testStruct testArray[1] = {
{"String works", 69}
};
then your program works as expected.
I expect your version has undefined behaviour because you are assigning (here testArray[0] = ...) to an array element that has not yet been created.
testStruct testArray[1] = {
This defines this array. This array, then, gets constructed. At what point, exactly, this array gets constructed is immaterial for the purposes of this question. It's sufficient to note that what goes inside { ... } gets evaluated and used to construct this array.
testArray[0] = {"String works", 69}
This expression constructs the first value of the array. This expression assigns a value to testArray[0].
The problem is that testArray[0] is not constructed yet, this is what's going on right now. This is undefined behavior. Just like what came first: the chicken or the egg. This is undefined.
You are seeing the results of undefined behavior, in the results of your program. The results of the program can be anything, and this just happens to be what shakes down, due to what your compiler and C++ library happen to produce, in terms of the executable code, before the dust settles.
So first of all you need to use std::vector, and std::cout as you havent used using namespace std.
But your main problem is:
testStruct testArray[1] = {
testArray[0] = {"String works", 69}
};
First of all it shouldnt be global as it does not need to be.
Second of all this is not correct:
testArray[0] = {"String works", 69}
You should not do this inside an array. What you probably meant to do is this:
testStruct testArray[1] = {{"String works", 69}}; // uses aggragate initialization.
So now this will have the correct output, with the following program:
#include <iostream>
#include <string>
#include <vector>
#include "Header.h"
//Test struct
struct testStruct
{
string testString;
int testInt;
};
int main()
{
testStruct testArray[1] = {{"String works", 69}};
srand(time(NULL));
vector < testStruct > test;
test.push_back({ testArray[0] });
cout << test[0].testString << "\n"; // prints "String works".
cout << test[0].testInt << "\n"; // prints 69.
characterCreation();
checkPlayerStats();
introduction();
return 0;
}
Assuming you have the Header.h header file

Using hardcoded char array pointer outside its scope, why no crashes

#include <iostream>
using namespace std;
int main()
{
char * a = nullptr;
{
char * b = (char *) "hello";
a = b;
}
cout << a << endl; // prints hello
return 0;
}
I have the code above. I am having hard time understanding why the code doesnt crash. My reasoning is I expected a crash because I am passing pointer b to upper scope with pointer a and using it to cout. Since "hello" was created within b's scope and new keywords isnt used, I expected it to clean itself automatically like a variable in a scope. What am I thinking wrong??
C-style string literal like "hello" has static storage duration; it exists in the life of the program. Then it's still valid for cout << a << endl; (while a is pointing to it) after the scope where b is defined.
String literals have static storage duration, and thus exist in memory for the life of the program.

When does character and int concatenation result in seg fault?

#include <iostream>
#include <string>
using namespace std;
int main()
{
int number = 900;
cout << std::string("Hello, World!" + number) << std::endl;
return 0;
}
I know the correct solution will be to use std::to_string(number). But the question here is, why do I not get a segmentation fault? I even ran it through valgrind. The string length is around 13 and I move the pointer 900.
The expression "Hello, World!" + number is a const char[] literal added to an int. The former decays to a const char* pointer and you add number to it by pointer arithmetic.
Since that final pointer is not in the original string constant, you are passing an invalid const char* pointer to a std::string constructor, and the behaviour of your program is undefined. Anything can happen at that point, including a runtime crash. An aggressively optimising compiler might omit the undefined expression altogether; that's getting progressively more common.
Boom!
If you wanted to concatenate 900 to the string, then you could have written
std::cout << std::string("Hello, World!" + std::to_string(number)) << std::endl;

Wrong code about c++ char*. Any body view?

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define attr_size 3
int main(){
const char* attr[attr_size];
int i=0;
for(i=0;i<attr_size;i++){
char* t=(char*)malloc(sizeof(int));
sprintf(t,"%d",i);
string temp="attr";
temp+=t;
attr[i]=temp.c_str();
cout<<attr[i]<<endl;
free(t);
}
for(i=0;i<attr_size;i++){
cout<<attr[i]<<endl;
}
}
And the result is:
attr0
attr1
attr2
attr2
attr
attr2
Actually, I want to get the result that:
attr0
attr1
attr2
attr0
attr1
attr2
Maybe something wrong with loop. Anybody help me?
The problem is that the c_str return a pointer that is temporary. So when the loop continue it's iteration the object you got the pointer from is destructed and the pointer is no longer valid, leading to undefined behavior when you later dereference that pointer.
If you want an array of strings, why not declare it as an array of strings?
There are also other problems with your code, like you only allocating four bytes for a string that can be 12 (with sign and string terminator) characters.
I would suggest you remake your program like this:
#include <iostream>
#include <array>
#include <sstream>
const size_t ATTR_SIZE = 3;
int main()
{
std::array<std::string, ATTR_SIZE> attr;
for (int i = 0; i < ATTR_SIZE; ++i)
{
std::istringstream is;
is << "attr" << i;
attr[i] = is.str();
}
for (const std::string& s : attr)
std::cout << s << '\n';
}
The above uses some C++11 features like std::array (you can use std::vector instead) and range-base for loop (you can use normal iteration instead).

String reverse error

Can anyone explain to me why im getting a ".exe has encountered a problem and needs close"error, it compiles and works sometimes when i fiddle with the char array, but when it does work i sometimes get strange characters at the end of the string.
#include <iostream>
using namespace std;
char* StrReverse3(char*);
char* StrReverse3(char* str)
{
char *p;
int length=0,start=0,end=0;
length=strlen(str);
for(start=0,end=length-1;end>= 0,start<=length-1;end--,start++)
{
p[start]=str[end];
}
return p;
}
int main()
{
char str[100]="Saw my reflection in snow covered hills";
StrReverse3(str);
cin.get();
return 0;
}
You are not initializing p. It's an uninitialized pointer that you are writing to.
Since you are writing this in C++, not C, I'd suggest using std::string and std::reverse:
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string str = "Saw my reflection in snow covered hills";
std::reverse(str.begin(), str.end());
std::cout << str;
return 0;
}
Output:
sllih derevoc wons ni noitcelfer ym waS
See it working online at ideone
char *p; is never initialized, yet p[start] is used as the destination of an assignment. Don't you get compiler warnings from this? I'm amazed it even "works sometimes".
You are accessing memory that wasn't allocated by your program (p can point anywhere!). This is the reason for the problems you have.
I strongly encourage you to
read into the topic of dynamically allocating memory with new and delete to understand a very important topic
read into the standard template library, especially std::string. You should not use raw pointers like char*, always use standard types when possible.
#include <iostream>
#include <cstring>
using namespace std;
char* StrReverse3(char* str){
int length=0,start=0,end=0;
length=strlen(str);
for(start=0,end=length-1;end > start;end--,start++){
char temp;
temp = str[start];
str[start]=str[end];
str[end]=temp;
}
return str;
}
int main(){
char str[100]="Saw my reflection in snow covered hills";
cout << StrReverse3(str);
cin.get();
return 0;
}