simple c++ program that adds a char byte to a string. The resulting length is wrong in the output.
#include <iostream>
#include <string>
int main(){
char x = 0x01;
std::string test;
test = x+"test";
std::cout << "length: " << test.length() << std::endl;
std::cout << "test: " << test << std::endl;
return 0;
}
the output:
length: 3
test: est
I am prepending a type byte to the string because I am going to be sending this data through a socket and the other side has a factory that needs to know the type of object to create.
1 + "test" = "est" // 1 offset from test
So you are getting the correct answer.
+---+---+---+---+---+
| t | e | s | t | \0|
+---+---+---+---+---+
+0 +1 +2 +3 +4
What you want is possibly:
std::string test;
test += x;
test += "test";
You are not concatenating a char with a std::string as you think you are. This is because "test" is actually a literal const char*, so you are just doing pointer arithmetic when you add x to it. You can replace
test = x + "test";
with
test = std::to_string(x) + "test";
Then your output will be
length: 5
test: 1test
Related
I can not understand why cout does not work in this code:
#include<iostream>
using namespace std;
int main() {
int v = 65;
int* q = &v;
char** o = (char**)&q;
cout << o << endl; // output: 012FFCAC
cout << *o << endl; // output: A
cout << **o << endl; // output: A
printf("%c",*o); // cause an error
printf("%p",*o); // works and the output=&v
And cout does not work else in this code
#include<iostream>
using namespace std;
int main() {
char v = 65;
cout << &v << endl; // output: A╠╠╠╠▀?╞«4°O
Because an int is (usually) 4 bytes 65 will fit quite neatly into just the first byte and the rest of the memory allocated for the int will be 0 this byte pattern happens to match up very closely to how strings are stored in memory.
So when the memory is accessed through a char* it will print A most of the time even though most of the prints were ill formed
int v = 65; // Byte pattern on most machines [65,0,0,0]
int* q = &v;
char** o = (char**)&q; // *o now points to [65,0,0,0] ==> ['A','\0','\0','\0'] ==> "A"
std::cout << o << std::endl;
// input: char**
// printed as: pointer
// result: 012FFCAC
std::cout << *o << std::endl; // Undefined Behaviour
// input: char*
// printed as: null terminated string
// result: "A"
std::cout << **o << std::endl; // Undefined Behaviour
// input: char
// printed as: single character
// result: 'A'
printf("%c",*o); // %c expects a [char] type but is given [pointer to char] ERROR
printf("%p",*o); // %p expects a [pointer] type and is given a [pointer to char] OK
Since a char is (usually) 1 byte there is no null terminand to stop the printing once it starts and it keeps printing whatever is around in memory until it runs into a 0 or an access violation
char v = 65;
std::cout << &v << std::endl; // &v is not a well-formed null terminated string: Undefined Behaviour
// input: char*
// printed as: null terminated string
// result: "A<whatever other data is around v in memory>"
I have a piece of code:
#include <bits/stdc++.h>
using namespace std;
int main() {
//ios_base::sync_with_stdio(false);
string s[5];
s[0] = "Hello";
s[1] = "12345";
cout << s[0] << " " << s[1] << "\n";
cout << s[0][0] << " " << s[1][1] << "\n";
int y = stoi(s[1]); //This does not show an error
cout <<"y is "<< y << "\n";
//int x = stoi(s[1][1]); //This shows error
//cout <<"x is "<< x << "\n";
return 0;
}
The output of this code is:
Hello 12345
H 2
y is 12345
But it shows an error when I uncomment
int x = stoi(s[1][0]);
cout <<"x is "<< x << "\n";
If in both the cases a string is being converted to int using stoi()
function then why do the later part of code gives an error?
I have tried the same using atoi(s[1][0].c_str()) but it also gives an error.
What is the alternative for this, if I want to convert the second type of elements to int?
s[1] is a std::string, so s[1][0] is a single char in that string.
Calling std::stoi() with a char as input doesn't work because it takes only a std::string as input, and std::string doesn't have a constructor that takes just a single char as input.
To do what you are attempting, you need to do this instead:
int x = stoi(string(1, s[1][0]));
Or
int x = stoi(string(&(s[1][0]), 1));
Your call to atoi() doesn't work because you are trying to call c_str() on a single char instead of the std::string it belongs to, eg:
int x = atoi(s[1].c_str());
stoi has as input a string not a char.
Try this:
string str(s[0][0]);
int y = stoi(str);
I am trying to write a line reader to populate a string array which is private member of the same class. I want the loader function called by constructor to dynamically resize member array and populate it. This didn't worked. Then I managed to populate a local array in the loader function. But I couldn't copy these values to private member of the class.
I think there must be a way of copying values from local "ReadLines" array to class private member "Lines" array.
I have already read how vector class implemented internally. But I still think dynamically populating a string array must be achievable by some other simple way, similar to which I used to resize local array in Read() function.
I searched the net, but couldn't find any answer without standart or self implemented vector classes. Has old methods before vectors (if any) completely forgotten? Is vector class that magical?
Isn't there any other way than vectors?
linereader.h :
class LineReader
{
public:
LineReader();
void Read();
private:
string Lines[];
int LineCount;
};
linereader.cpp :
#include <string>
#include <iostream>
using namespace std;
#include <fstream>
#include "linereader.h"
LineReader::LineReader()
{
Read();
cout << "Line Count : " << LineCount << endl;
cout << "Lines Size : " << sizeof(Lines) << endl;
cout << "Lines 0 : ";
cout << Lines[0] << endl; //Gives segmantation fault
}
void LineReader::Read()
{
std::ifstream infile("lines.txt");
string *ReadLines = new string[1];
string line;
int linenumber = 0;
while (infile >> line)
{
cout << endl << linenumber << " :: " << line << " ";
string* temp_Lines = new string[linenumber + 1];
for(int i = 0; i < linenumber; i++){
cout << i << ",";
temp_Lines[i] = ReadLines[i];
}
cout << "[" << linenumber << "]";
delete [] ReadLines;
ReadLines = temp_Lines;
ReadLines[linenumber] = line;
linenumber++;
}
infile.close();
cout << endl << "----------------------------------" << endl;
cout << "ReadLines Count : " << linenumber << endl;
LineCount = linenumber;
for(int i = 0; i < linenumber; i++){
cout << "ReadLines "<< i + 1 << " " << ReadLines[i] << endl;
}
/////////////////////////////////////
// HERE IS THE PROBLEM //
// how to copy ReadLines to Lines? //
/////////////////////////////////////
//string *Lines = new string[linenumber + 1]; // FLOODING TERMINAL WITH EMPTY LINES
// Lines = ReadLines; // not working
// Lines = *ReadLines; // error: cannot convert
// Lines = **ReadLines; // error: no match for ‘operator*’
// *Lines = ReadLines; // error: invalid conversion from
// *Lines = *ReadLines; // FLOODING TERMINAL WHEN RUN
// *Lines = **ReadLines; // error: no match for ‘operator*’
// **Lines = ReadLines; // error: no match for ‘operator*’
// **Lines = *ReadLines; // error: no match for ‘operator*
// **Lines = **ReadLines; // error: no match for ‘operator*
}
int main(int argc, char* argv[])
{
LineReader linereader;
return 0;
}
lines.txt :
AAA
BBB
CCC
DDD
EEE
FFF
GGG
compilation :
g++ linereader.cpp -o linereader
OUTPUT :
0 :: AAA [0]
1 :: BBB 0,[1]
2 :: CCC 0,1,[2]
3 :: DDD 0,1,2,[3]
4 :: EEE 0,1,2,3,[4]
5 :: FFF 0,1,2,3,4,[5]
6 :: GGG 0,1,2,3,4,5,[6]
----------------------------------
ReadLines Count : 7
ReadLines 1 AAA
ReadLines 2 BBB
ReadLines 3 CCC
ReadLines 4 DDD
ReadLines 5 EEE
ReadLines 6 FFF
ReadLines 7 GGG
Line Count : 7
Lines Size : 0
Segmentation fault
The problem lies here:
string Lines[];
You declare an empty array. More exactly, you declare an incomplete array that is commonly implemented as a 0 size array. That is what the line Lines Size : 0 indicates. It used (mainly in C) when you create an object at a place where the memory for the array has already been allocated, and only as last element of a struct or class - in short never use it in your own code. It should at least raise a warning because it is not the last element of the class.
But once you have declared it that way, nothing can be done. The less poor way IMHO is to declare a pointer: as you already know the length in the following member it is enough:
private:
string *Lines;
int LineCount;
You can then safely do:
Lines = ReadLines;
But what you do is close to non sense. You avoid to use a (well optimized and well tested) vector object, to play with allocation, copy and deallocation of arrays. That means that your code will give a much less efficient program than what you would get with a vector. In addition, as C++ has no garbage collection, this kink of code is likely to fragment the heap.
Said differently, there is nothing bad in exploring the low level constructs, but please be aware that this one should never go in production code.
Try to call read from the main function. Then it should have no problems with modifying a private value.
If you also add a print function to the main file, then you can add the following code to your linereader.cpp, note that the constructor is now an empty implementation.
ineReader::print()
{
cout << "Line Count : " << LineCount << endl;
cout << "Lines Size : " << sizeof(Lines) << endl;
cout << "Lines 0 : ";
cout << Lines[0] << endl; //Gives segmantation fault
}
LineReader::LineReader() { }
int main(int argc, char* argv[])
{
LineReader linereader;
linereader.read();
linereader.print();
return 0;
}
I was just reviewing my C++. I tried to do this:
#include <iostream>
using std::cout;
using std::endl;
void printStuff(int x);
int main() {
printStuff(10);
return 0;
}
void printStuff(int x) {
cout << "My favorite number is " + x << endl;
}
The problem happens in the printStuff function. When I run it, the first 10 characters from "My favorite number is ", is omitted from the output. The output is "e number is ". The number does not even show up.
The way to fix this is to do
void printStuff(int x) {
cout << "My favorite number is " << x << endl;
}
I am wondering what the computer/compiler is doing behind the scenes.
The + overloaded operator in this case is not concatenating any string since x is an integer. The output is moved by rvalue times in this case. So the first 10 characters are not printed. Check this reference.
if you will write
cout << "My favorite number is " + std::to_string(x) << endl;
it will work
It's simple pointer arithmetic. The string literal is an array or chars and will be presented as a pointer. You add 10 to the pointer telling you want to output starting from the 11th character.
There is no + operator that would convert a number into a string and concatenate it to a char array.
adding or incrementing a string doesn't increment the value it contains but it's address:
it's not problem of msvc 2015 or cout but instead it's moving in memory back/forward:
to prove to you that cout is innocent:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
char* str = "My favorite number is ";
int a = 10;
for(int i(0); i < strlen(str); i++)
std::cout << str + i << std::endl;
char* ptrTxt = "Hello";
while(strlen(ptrTxt++))
std::cout << ptrTxt << std::endl;
// proving that cout is innocent:
char* str2 = str + 10; // copying from element 10 to the end of str to stre. like strncpy()
std::cout << str2 << std::endl; // cout prints what is exactly in str2
return 0;
}
I've been struggling with this for too long.
Let's say i have this minimal code:
test.cxx
#include <iostream>
#include <cstdio>
int main (int argc, char *argv[])
{
const char *text = "1.01 foo";
float value = 0;
char other[8];
int code = sscanf(text, "%f %7s", &value, other);
std::cout << code << " | " << text << " | => | " << value << " | " << other << " | " << std::endl;
return 0;
}
$ g++ test.cxx; ./a.out produces this output, as expected:
$ 2 | 1.01 foo | => | 1.01 | foo |
Now I have these 5 lines embedded into a project with several thousand lines, and lots of includes ...
Compiling, running, and the output is now:
$ 2 | 1.01 foo | => | 1 | .01 |
What strategy could I use to locate the source of this inconsistency ?
EDIT:
export LC_ALL=C (or LC_NUMERIC=C); ./a.out seems to solve my problem
It might be caused by a different locale in your test and in your destination application. I was able to reproduce it on coliru:
by using:
setlocale(LC_ALL, "cs_CZ.utf8");
http://coliru.stacked-crooked.com/a/5a8f2ea7ac330d66
You can find some solutions in this SO:
sscanf() and locales. How does one really parse things like "3.14"?
[edit]
Solution with uselocale, but since you tagged this question with C++ then why not use std::stringstream and imbue it with proper locale (see link to SO above).
http://coliru.stacked-crooked.com/a/dc0fac7d2533d95c
const char *text = "1.01 foo";
float value = 0;
char other[8];
// set for testing, sscanf will assume floating point numbers use comma instead of dots
setlocale(LC_ALL, "cs_CZ.utf8");
// Temporarily use C locale (uses dot in floats) on current thread
locale_t locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
locale_t old_locale = uselocale(locale);
int code = sscanf(text, "%f %7s", &value, other);
std::cout << code << " | " << text << " | => | " << value << " | " << other << " | " << std::endl;
// Go back to original locale
uselocale(old_locale);
freelocale(locale);