Why cout<<"Hello world" + 10; prints d in the output [duplicate] - string

The code successfully compiles it but I can't understand why, for certain values of number, the program crashes and for other values it doesn't. Could someone explain the behavior of adding a long int with a char* that the compiler uses?
#include <iostream>
int main()
{
long int number=255;
std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
number=15155;
std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
return 0;
}
Test results:
Value 1 : >
Value 2 : Segmentation fault
Note: I'm not looking for a solution on how to add a string with a number.

In C++, "" is a const char[1] array, which decays into a const char* pointer to the first element of the array (in this case, the string literal's '\0' nul terminator).
Adding an integer to a pointer performs pointer arithmetic, which will advance the memory address in the pointer by the specified number of elements of the type the pointer is declared as (in this case, char).
So, in your example, ... << ("" + number) << ... is equivalent to ... << &""[number] << ..., or more generically:
const char *ptr = &""[0];
ptr = reinterpret_cast<const char*>(
reinterpret_cast<const uintptr_t>(ptr)
+ (number * sizeof(char))
);
... << ptr << ...
Which means you are going out of bounds of the array when number is any value other than 0, thus your code has undefined behavior and anything could happen when operator<< tries to dereference the invalid pointer you give it.
Unlike in many scripting languages, ("" + number) is not the correct way to convert an integer to a string in C++. You need to use an explicit conversion function instead, such as std::to_string(), eg:
#include <iostream>
#include <string>
int main()
{
long int number = 255;
std::cout << "Value 1 : " << std::flush << std::to_string(number) << std::flush << std::endl;
number = 15155;
std::cout << "Value 2 : " << std::flush << std::to_string(number) << std::flush << std::endl;
return 0;
}
Or, you can simply let std::ostream::operator<< handle that conversion for you, eg:
#include <iostream>
int main()
{
long int number = 255;
std::cout<< "Value 1 : " << std::flush << number << std::flush << std::endl;
number = 15155;
std::cout<< "Value 2 : " << std::flush << number << std::flush << std::endl;
return 0;
}

Pointer arithmetic is the culprit.
A const char* is accepted by operator<<, but will not point to a valid memory address in your example.
If you switch on -Wall, you will see a compiler warning about that:
main.cpp: In function 'int main()':
main.cpp:6:59: warning: array subscript 255 is outside array bounds of 'const char [1]' [-Warray-bounds]
6 | std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
main.cpp:8:59: warning: array subscript 15155 is outside array bounds of 'const char [1]' [-Warray-bounds]
8 | std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
Value 1 : q
Live Demo

Related

in c++ how do I calculate tool path length?

I am dealing with generation of tool path where composed many points in three dimension and I am using CNC machine to generate them. One of the things that I want to calculate is tool path length which is defined the total length of path. So I tried this:
1.6760 3.7901 6.1955
1.2788 4.1872 5.3681
0.2832 5.1828 3.2939
0.1835 5.2173 3.0576
0.1097 5.1205 2.8292
0.0815 4.9185 2.6699
0.0812 4.8728 2.6491
0.0810 4.8270 2.6288
0.0807 4.7810 2.6089
The points are like these.
// math.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <vector>
#include<math.h>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::ostream;
using std::istream;
using std::ifstream;
using std::operator>>;
using std::operator<<;
struct point
{
float x ;
float y ;
float z ;
};
ostream& operator<< (ostream& out, const point &p)
{
out << "(" << p.x << "," << p.y << " ," << p.z << "," << ")";
return out;
}
istream& operator>> (istream& in, point& point)
{
in >> point.x >> point.y >> point.z;
return in;
}
struct line
{
point start;
point next;
float sqDistance()
{
float dx = start.x - next.x;
float dy = start.y - next.y;
float dz = start.z - next.z;
double distance = 0.0;
distance = sqrt(dx * dx + dy * dy + dz * dz);
return distance;
}
};
ostream& operator<< (ostream& out, const line &ln)
{
out << "From " << ln.start << " to " << ln.next;
return out;
}
istream& operator>> (istream& in, line ln)
{
cout << "Enter x y z start then x y z next: ";
in >> ln.start.x >> ln.start.y >> ln.start.z >> ln.next.x >> ln.next.y >> ln.next.z;
return in;
}
int main()
{
point origin, input;
line ray;
vector<line> side;
// READ POINTS FROM FILE
ifstream pointfile("concave.txt");
if (pointfile.is_open())
{
pointfile >> origin.x >> origin.y >> origin.z;
cout << "origin: " << origin << endl;
ray.start = origin;
while (pointfile >> ray.next)
{
cout
<< " GOTO/ " << ray.next
<< " The distance from point to the next is : "
<< ray.sqDistance() << endl;
side.push_back(ray);
}
}
else
cout << "Unable to open file";
pointfile.close();
vector<line>::iterator iter = side.begin();
line temp, closest = *iter;
float minimumDistance = closest.sqDistance(), distance = 0.0;
system("PAUSE");
return 0;
}
-I expect the distance between point and its next point.
-the total length of this line.
What about something like this - suppose you want distance between points and not from start (line 93 with comment):
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <vector>
#include<math.h>
#include <conio.h>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::ostream;
using std::istream;
using std::ifstream;
using std::operator>>;
using std::operator<<;
struct point
{
float x ;
float y ;
float z ;
};
ostream& operator<< (ostream& out, const point &p)
{
out << "(" << p.x << "," << p.y << " ," << p.z << "," << ")";
return out;
}
istream& operator>> (istream& in, point& point)
{
in >> point.x >> point.y >> point.z;
return in;
}
struct line
{
point start;
point next;
float sqDistance()
{
float dx = start.x - next.x;
float dy = start.y - next.y;
float dz = start.z - next.z;
double distance = 0.0;
distance = sqrt(dx * dx + dy * dy + dz * dz);
return distance;
}
};
ostream& operator<< (ostream& out, const line &ln)
{
out << "From " << ln.start << " to " << ln.next;
return out;
}
istream& operator>> (istream& in, line ln)
{
cout << "Enter x y z start then x y z next: ";
in >> ln.start.x >> ln.start.y >> ln.start.z >> ln.next.x >> ln.next.y >> ln.next.z;
return in;
}
int main()
{
point origin, input;
line ray;
vector<line> side;
// READ POINTS FROM FILE
ifstream pointfile("concave.txt");
if (pointfile.is_open())
{
pointfile >> origin.x >> origin.y >> origin.z;
cout << "origin: " << origin << endl;
ray.start = origin;
while (pointfile >> ray.next)
{
cout
<< " GOTO/ " << ray.next
<< " The distance from point to the next is : "
<< ray.sqDistance() << endl;
side.push_back(ray);
ray.start = ray.next; // set start to last end (?)
}
}
else
cout << "Unable to open file";
pointfile.close();
vector<line>::iterator iter = side.begin();
line temp, closest = *iter;
float minimumDistance = closest.sqDistance(), distance, sumDistance = 0.0;
cout << "Line coords" << endl << "distance, Sum of distances, minimum" << endl;
while(iter != side.end()) {
closest = *iter;
distance = closest.sqDistance();
sumDistance += distance;
if(minimumDistance > distance) minimumDistance = distance;
cout << closest << endl
<< distance << " | " << sumDistance << " | " << minimumDistance << endl;
sumDistance += distance;
iter++;
}
getch();
return 0;
}
Sorry for the bug - sum line was there twice - line after cout was an error, also noticed some precision warning - mixed double/float, so switched to double everywhere, now main loop looks like this:
vector<line>::iterator iter = side.begin();
line closest = *iter;
double distance, sumOfDistances = 0.0;
cout << "Line coords" << endl << "distance | Sum of distances" << endl;
while (iter != side.end()) {
closest = *iter;
distance = closest.sqDistance();
sumOfDistances += distance;
cout << closest << endl << distance << " | " << sumOfDistances << endl; // step info output
iter++;
}
Here complete, a bit shorter version including simple results.txt file output.
You can remove 2 lines with comment info output:
#include <iostream>
#include <fstream>
#include <vector>
#include <conio.h>
using namespace std;
struct point
{
float x;
float y;
float z;
};
ostream& operator<< (ostream& out, const point &p)
{
out << "(" << p.x << "," << p.y << " ," << p.z << "," << ")";
return out;
}
istream& operator>> (istream& in, point& point)
{
in >> point.x >> point.y >> point.z;
return in;
}
struct line
{
point start;
point next;
double sqDistance()
{
float dx = start.x - next.x;
float dy = start.y - next.y;
float dz = start.z - next.z;
double distance = 0.0;
distance = sqrt(dx * dx + dy * dy + dz * dz);
return distance;
}
};
ostream& operator<< (ostream& out, const line &ln)
{
out << "From " << ln.start << " to " << ln.next;
return out;
}
istream& operator>> (istream& in, line ln)
{
cout << "Enter x y z start then x y z next: ";
in >> ln.start.x >> ln.start.y >> ln.start.z >> ln.next.x >> ln.next.y >> ln.next.z;
return in;
}
int main()
{
point origin, input;
line ray;
vector<line> side;
// READ POINTS FROM FILE
ifstream pointfile("concave.txt");
if (pointfile.is_open())
{
pointfile >> origin.x >> origin.y >> origin.z;
cout << "origin: " << origin << endl;
ray.start = origin;
while (pointfile >> ray.next)
{
cout
<< " GOTO/ " << ray.next
<< " The distance from point to the next is : "
<< ray.sqDistance() << endl;
side.push_back(ray);
ray.start = ray.next; // set start to last end (?)
}
}
else
cout << "Unable to open file";
pointfile.close();
ofstream results("results.txt");
vector<line>::iterator iter = side.begin();
line closest = *iter;
double distance, sumOfDistances = 0.0;
cout << "Line coords" << endl << "distance | Sum of distances" << endl;
while (iter != side.end()) {
closest = *iter;
distance = closest.sqDistance();
sumOfDistances += distance;
results << distance << endl;
cout << closest << endl << distance << " | " << sumOfDistances << endl; // info output
iter++;
}
results << sumOfDistances << " << Sum" << endl;
results.close();
cout << "Complete path distance: " << sumOfDistances << endl; // info output
getch();
return 0;
}

Printing dynamically stored string in assembly mips32

I'm working on a mini-compiler and I reached the code generation level.
I want to store a string dynamically to the heap segment, so I wrote this C++ code (cg is the file I'm generating assembly code to) :
int length = strlen("abc");
cg << "\tori\t$a0,$0," << (length + 3) * 4 << endl; // reserve space for type + length + null + size
cg << "\tori\t$v0,$0,9" << endl;
cg << "\tsyscall" << endl;
increamentSP();
cg << "\tsw\t$v0,0($sp)" << endl;
cg << "\tori\t$t1,$0,1" << endl; // store the type
cg << "\tsw\t$t1,0($v0)" << endl;
cg << "\tori\t$t1,$0," << length << endl; // store the length
cg << "\tsw\t$t1," << 4 << "($v0)" << endl;
for (int i = 0; i < length; i++)
{
cg << "\tori\t$t1,$0," << (int)p->val[i] << endl; // store the char
cg << "\tsw\t$t1," << (2 + i) * 4 << "($v0)" << endl;
}
cg << "\tsw\t$0," << (2 + length) * 4 << "($v0)" << endl;
Basically, what I'm trying to do is :
First, I want to store a flag (1) referring that this type is a string to the first location.
Then, I want to store the size of my string to the second location.
After that, I want to store my strings chars to the next locations.
Finally, I want to store a null-terminating char to the last location.
My problem is that when I try to print my string using a code like this :
la $a0,8($t0)
ori $v0,$0,4
syscall
The result is that mips prints only the letter 'a', how can I print a string stored like this? or is there any better way to store my string?
p.s. I know I can use .asciiz in the .data segment, but the problem is that in my code I might edit the string, so I don't exactly know what my string would become.
Can any one help me with that?

cin unintentionally skipping user input

I am trying to write a loop that validates user input, and then repeats if the input is bad. The input must be either a binary number (as a string) or a decimal number (as an int). I have seperate functions to validate this input, but they are not causing any trouble.
The problem arises when I select 1 or 2, and then willingly enter an invalid binary or decimal number. At this point, the do-while loop repeats successfully. The program prints another request for user input to cout, But when it comes time for the user to enter input, the program thinks that there is input in the console before I even enter anything. I believe this is a problem with whitespace/control characters in the buffer, but I am not sure how to fix it. I have tried using std::cin >> std::ws to clear any straggling white space, but no luck.
#include <iostream>
#include <string>
#include <limits>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
using std::cout;
using std::cin;
using std::endl;
using std::numeric_limits;
using std::max;
using std::streamsize;
using std::string;
//int toDecimal;
//true is is binary
bool validateBinary(const string &binaryNumber){
for(int i = 0; i < binaryNumber.length(); i++){
if((binaryNumber[i] != 1) && (binaryNumber[i] != 0)){
return false;
}
}
return true;
}
//true if is decimal
bool validateDecimal(){
return cin;
}
int main() {
int conversionType = 0; //we initialize conversionType to a default value of 0 to ensure the copiler it will always have a value
bool isBinary = false;
bool isDecimal = false;
string binaryNumberInput;
int decimalNumberInput;
do {
if(conversionType == 0){
cout << "Enter 1 to convert binary to decimal," << endl;
cout << "2 to convert decimal to binary, " << endl;
cout << "or 3 to exit the program: ";
std::cin >> std::ws; //to clear any whitespace fron cin
cin >> conversionType; //upon a second iteration, this value is read in before a user input is given
}
if(!cin || (conversionType != 1 && conversionType != 2)){
cout << "Incorrect input." << endl;
cin.clear(); //clear the fail bit
cin.ignore(numeric_limits<streamsize>::max(), '\n'); //used to ignore not-numeric input
}
cout << "You have selected option " << conversionType << "." << endl;
if(conversionType == 1){
cout << "Please enter a binary number: ";
cin >> binaryNumberInput;
isBinary = validateBinary(binaryNumberInput);
if(!isBinary){
cout << "The numbered you entered is not a binary number!" << endl;
conversionType = 0;
}
}
if(conversionType == 2){
cout << "Please enter a decimal number: ";
cin >> decimalNumberInput;
isDecimal = validateDecimal(); //true if succeeded, meaning is a number
if(!isDecimal){
cout << "The numbered you entered is not a decimal number!" << endl;
conversionType = 0;
}
}
}
while((conversionType != 1 && conversionType != 2) || (isBinary == isDecimal));
return 0;
}
Rather than debug your current program you might want to consider using the standard library to simply things
#include <iostream>
#include <string>
#include <bitset>
#include <climits>
#include <limits>
template<typename T>
void get(T& value)
{
while (!(std::cin >> value)) {
std::cout << "Invalid input\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
int main()
{
std::cout << "Enter 1 to convert binary to decimal,\n" <<
"2 to convert decimal to binary\n";
int option;
if (std::cin >> option) {
switch (option) {
case 1: {
std::bitset<CHAR_BIT * sizeof(unsigned long long)> bits;
get(bits);
std::cout << bits.to_ullong() << '\n';
break;
}
case 2: {
unsigned long long i;
get(i);
std::cout << std::bitset<CHAR_BIT * sizeof i>(i) << '\n';
break;
}
}
}
}
If you want this to loop you should be able to add it back in again easily enough.

Why doesn't unsigned char* work with ifstream::read?

I am a beginner with C++. I have a new project at work where I have to learn it, so I'm trying some things just to test my understanding. For this problem, I'm trying to read a file and then print it on screen. Super simple, just trying to get good at it and understand the functions that I'm using. I copied some text from a MS Word document into a notepad (*.txt) file, and I'm trying to read this *.txt file. All of the text in the word document is bolded, but other than that there are no 'unusual' characters. Everything prints out on the screen as it appears in the document except the bolded " - " symbol. This character is printed as the "u" with a hat character ("so called extended ASCII" code 150). I try to print out the integer value of this character in my array (which should be 150) but I get -106. I realize this signed integer has the same bits as the unsigned integer 150. My question is how to get the output to say 150? Here's my code:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
unsigned char* input1;
int input1size = 57;
ifstream file("hello_world2.txt",ios::binary | ios::ate);
if (file.is_open()){
int size;
size = (int) file.tellg();
cout <<"This file is " << size << " bytes." << endl;
file.seekg(0,ios::beg);
input1 = new unsigned char[input1size];
file.read(input1, input1size);
cout << "The first " << input1size <<" characters of this file are:" << endl<<endl;
for (int i=0; i<input1size; i++) {
cout << input1[i];
}
cout<<endl;
}
else {
cout <<"Unable to open file" << endl;
int paus;
cin>>paus;
return 0;
}
file.close();
int charcheck = 25;
int a=0;
int a1=0;
int a2=0;
unsigned int a3=0;
unsigned short int a4=0;
short int a5=0;
a = input1[charcheck];
a1 = input1[charcheck-1];
a2 = input1[charcheck+1];
a3 = input1[charcheck];
a4 = input1[charcheck];
a5 = input1[charcheck];
cout <<endl<<"ASCII code for char in input1[" << charcheck-1 <<"] is: " << a1 << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck <<"] is: " << a << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck+1 <<"] is: " << a2 << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck <<"] as unsigned int: " << a3 << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck <<"] as unsigned short int: " << a4 << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck <<"] as short int: " << a5 << endl;
int paus;
cin>>paus;
return 0;
}
Output for all this looks like:
This file is 80 bytes.
The first 57 characters of this file are:
STATUS REPORT
PERIOD 01 u 31 JUL 09
TASK 310: APPLIC
ASCII code for char in input1[24] is: 32
ASCII code for char in input1[25] is: -106
ASCII code for char in input1[26] is: 32
ASCII code for char in input1[25] as unsigned int: 4294967190
ASCII code for char in input1[25] as unsigned short int: 65430
ASCII code for char in input1[25] as short int: -106
So it appears "int a" is always read as signed. When I try to make "a" unsigned, it turns all the bits left of the eight bits for the char to 1's. Why is this? Sorry for the length of the question, just trying to be detailed. Thanks!
What you're dealing with is the sign-extension that takes place when the char is promoted to int when you assign it to one of your a? variables.
All the higher order bits must be set to 1 to keep it the same negative value as was in the smaller storage of the char.

Why am I getting an assertion error?

#include <iostream>
using namespace std;
int main ()
{
int size = 0;
int* myArray = new int [size + 1];
cout << "Enter the exponent of the first term: ";
cin >> size;
cout << endl;
for (int i = size; i >= 0; --i)
{
cout << "Enter the coefficient of the term with exponent "
<< i << ": ";
cin >> myArray[i];
}
for (int i = size; i >= 0; --i)
{
cout << i << endl;
}
return 0;
}
Why am I getting an assertion error on input greater than 2? This is the precursor to a polynomial program where the subscript of the array is the power of each term and the element at array[subscript] is the coefficient.
Your array is allocated to be an int[1]. It needs to be allocated after you read in the size value.
You are initializing your array when size = 0, giving an array size of 1
You get your assertion error when you go outside of the array bounds (1).
myArray always has size 0 + 1 = 1. i starts out at whatever the user inputted, and the first array access you make is myArray[i]. So, say the user inputs 5, your array has size 1 and you access myArray[5]. It will fail!
I would allocate the array AFTER you input size.

Resources