getting 'std::out_of_range' what(): basic_string::substr even when pos is less than length of string - substr

I am running this code:
*
ifstream trace_file;
trace_file.open (argv[7]);
while (!trace_file.eof())
{
string line;
getline (trace_file,line);
string read_write = line.substr(0,1);
string address = line.substr(2);
cout << line << '\t' << read_write << "-->" << address<< "-->" << line.size() << '\n';
}
*
The file that I am reading through ifstream, has this content:
r 4fd
w f47
r 8d2
w f05
I get this output:
r 4fd r-->4fd-->5
w f47 w-->f47-->5
r 8d2 r-->8d2-->5
w f05 w-->f05-->5
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr
Abort (core dumped)
It runs fine if I remove this line:
string address = line.substr(2);
Length of each string is 5, so this should not throw this exception.
It runs fine if I keep pos=0
for pos = 1 or 2 or 3, I get this exception.
I do not understand what is wrong here. Any help will be appreciated.

Related

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

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

No suitable constructor exists to convert from "char" to "std::string"

I'm new to coding in C and C++, and I have a program with
an issue. When I (try) to run it, it gives me this error:
"No suitable constructor exists to convert from "char" to "std::string".
I'm not sure what it means. My code is an example of a simple
substitution cipher covered in the book "Cracking Codes with Python" by Al Sweigart.
I just want to replicate it in C++. Here's my code:
#include <iostream> // for communicating with user
#include <string>
using namespace std;
string symbols = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // all symbols
string encrypt(string msg, string key, string mode) {
string ca = symbols;
string cb = key;
string translated;
if (mode == "decrypt") {
ca, cb = cb, ca;
}
int index = 0;
for (index = 0; index < msg.length(); index++) {
cout << "index is " << index << endl;
int sindex = ca.find(msg[index]); // it works here
cout << "sindex is " << sindex << endl;
string cl = cb[sindex]; // the problem
translated += cl;
}
return translated;
}
int main() {
string msg = "";
string key = "";
string mode = "";
string ciphertext = ""; // our variables
cout << "Enter message: (no spaces please)\n";
cin >> msg;
cout << "Enter key (or \"none\" for using default):\n";
cin >> key;
if (key == "none") {
key = "QWERTYUIOPASDFGHJKLZXCVBNM";
}
cout << "Enter mode: (\"encrypt\" or \"decrypt\")\n";
cin >> mode;
ciphertext = encrypt(msg, key, mode);
cout << "The ciphertext is\n" << ciphertext;
}
For some reason it works with msg on line 17 but not with cb on line 19, even though
they're both std::string. The actual error is on line 19 with string cl = cb[sindex];.
Not even sure what's wrong. It works on line 17 int sindex = ca.find(/*The thing here*/msg[index]);.
(Maybe my Visual Studio 2019 has gone nuts.) If I replace cb with msg it still gives me the
same error. Maybe line 17 is a lucky line? Who knows? But please help, I'm so
confused!

Failure to read a string using cin

For this simple piece of code:
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::string;
bool are_uniq_chars(string const&);
int main(){
string s;
cout << "Enter string: ";
cin >> s;
auto flag = are_uniq_chars(s);
I get the following illegal value for s upon gdb debugging:
Thread 2 hit Breakpoint 1, main () at main.cpp:10
10 string s;
(gdb) n
11 cout << "Enter string: ";
(gdb) n
12 cin >> s;
(gdb) n
Enter string: vinod
13 auto flag = are_uniq_chars(s);
(gdb) p s
$1 = {<std::__1::__basic_string_common<true>> = {<No data fields>},
__r_ = {<std::__1::__libcpp_compressed_pair_imp<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, std::__1::allocator<char>, 2>> = {<std::__1::allocator<char>> = {<No data fields>},
__first_ = {{__l = {__cap_ = 110429756552714, __size_ = 0,
__data_ = 0x0}, __s = {{__size_ = 10 '\n', __lx = 10 '\n'},
__data_ = "vinod", '\000' <repeats 17 times>}, __r = {__words = {
110429756552714, 0, 0}}}}}, <No data fields>},
static npos = 18446744073709551615}
Not sure what is wrong? The code is being run on macOS High Sierra 10.13.2.
Any help would be appreciated.
TIA
Vinod
Guess this output is normal as the program started working as expected after fixing another error.

Cmd makes a "beep" every time I input 7

When I execute this, every time I input 7 the PC makes a "beep". Can someone explain me why? I use this header: http://www.stroustrup.com/Programming/std_lib_facilities.h
int main()
{
double d = 0;
while (cin >> d){
int i = d;
char c = i;
int i2 = c;
cout << "d==" << d
<< " i==" << i
<< " i2==" << i2
<< " char==(" << c << ")\n";
}
}
ASCII character 7 is the bell character dating back to the ancient days of teletype...

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