Inserted in set and received Segmentation fault - c++

I created code to convert graph representation (A list of edges -> the adjacency list)
How can i fix error?
I have Segmentation fault in line res[cur.first - 1].insert(cur.second);for input
4 3
3 2
2 1
4 2
My code
#include <bits/stdc++.h>
using namespace std;
pair<int, int> strToSotredPair(const string& s) {
int a = 0, b = 0;
int pos = 0;
while (s[pos] != ' ') {
a = a * 10 + s[pos] - '0';
++pos;
}
while (pos < s.size()) {
b = b * 10 + s[pos] - '0';
++pos;
}
return {min(a, b), max(a, b)};
}
int main() {
int n, m;
string input;
cin >> n;
cin >> m;
vector<set<int>> res(n, set<int>());
for (int i = 0; i < m; ++i) {
cin >> input;
auto cur = strToSotredPair(input);
res[cur.first - 1].insert(cur.second); // error in this line
}
for (int i = 0; i < res.size(); ++i) {
cout << res[i].size() << ' ';
for (auto item : res[i]) {
cout << item << ' ';
}
cout << endl;
}
}

There are a couple of error's in your code because of which you were getting that error.
You wanted the graph edges as strings. So you need to take edge inputs as strings. For that, you would be required to use getline(cin,input) and cin.ignore().
(My suggestion: Do not take inputs as strings because as it is you are converting them to integers afterwards. By default if you just write cin<<node1<<node2; the two nodes of an edge would have come as integers and function strToSotredPair would not be needed).
In function strToSotredPair after you get the integer a, pos variable is pointing to the space. So you need to increase it by 1 to point to the starting position to 2nd number. Hence a pos++ was needed.
#include <bits/stdc++.h>
using namespace std;
pair<int, int> strToSotredPair(const string& s) {
int a = 0, b = 0;
int pos = 0;
while (s[pos] != ' ') {
a = a * 10 + s[pos] - '0';
++pos;
}
pos++;
while (pos < s.size()) {
b = b * 10 + s[pos] - '0';
++pos;
}
return {min(a, b), max(a, b)};
}
int main() {
int n, m;
string input;
cin >> n;
cin >> m;
vector<set<int>> res(n, set<int>());
cin.ignore(); // To clear the input buffer
for (int i = 0; i < m; ++i) {
getline(cin, input); // to get line by line string inputs
auto cur = strToSotredPair(input);
res[cur.first - 1].insert(cur.second);
}
for (int i = 0; i < res.size(); ++i) {
cout << res[i].size() << ' ';
for (auto item : res[i]) {
cout << item << ' ';
}
cout << endl;
}
}

Related

c++ assertion string iterator offset out of reange

I am getting Assertion Failed. It show it after cin. I have checked also the file whose path it shows, but no solution.
"string iterator + offset out of range" is the massage it shows. It happens after I use "cin >> a" at line 65. Can anyone help me? Thanks in advance.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
int gcd(int a, int b){
cout << "gcd" << endl;
if (b == 0) return a;
else return gcd(b, a % b);
}
int gcd_n(vector<int>nums){
int g;
size_t n = nums.size();
g = nums.at(0);
cout << "son" << endl;
for (int i = 1; i < n; i++){
g = gcd(nums.at(i), g);
}
return g;
}
long long int multi_vect(vector<int> v){
long long int m = 1;
for (size_t i = 0; i < v.size(); i++)
m *= v.at(i);
return m;
}
int main() {
int a;
vector <vector<int>> all_vects;
cin >> a;
string input, sub;
getline(cin, input);
int n = input.find(' ');
vector<int> vect;
while(true){
int num;
sub = input.substr(0, n);
istringstream(sub) >> num;
vect.push_back(num);
input = input.substr(n+1, input.back()+1);
n = input.find(' ');
if (n == -1){
istringstream(input) >> num;
vect.push_back(num);
break;
}
}
all_vects.push_back(vect);
}
When I tested this code, I found that n=-1 needs to be judged in advance. Suppose that input. Assuming that the string input has no ' ', then n will become -1, And the sub = input.substr(0, n); is not true. So, the vector vect will be empty. That is why string iterator + offset out of range will appear.
The following are my changes to this code. And you could refer to it.
if (n == -1)
{
istringstream(input) >> num;
vect.push_back(num);
break;
}
else {
sub = input.substr(0, n);
istringstream(sub) >> num;
vect.push_back(num);
input = input.substr(n + 1, input.back() + 1);
n = input.find(' ');
}

Why does the code below causes Segmentation Fault (SIGSEGV)?

PROBLEM STATEMENT
You are given a strictly increasing sequence of integers A1,A2,…,AN. Your task is to compress this sequence.
The compressed form of this sequence is a sequence of ranges separated by commas (characters ','). A range is either an integer or a pair of integers separated by three dots (the string "..."). When each range a...b in the compressed form is decompressed into the subsequence (a,a+1,…,b), we should obtain the (comma-separated) sequence A again.
For each maximal contiguous subsequence (a,a+1,…,b) of A such that b≥a+2, the compressed form of A must contain the range a...b; if b≤a+1, such a sequence should not be compressed into a range. A contiguous subsequence is maximal if it cannot be extended by at least one element of A next to it. It can be proved that the compressed form of any sequence is unique (i.e. well-defined).
Input
The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains a single integer N.
The second line contains N space-separated integers A1,A2,…,AN.
Output
For each test case, print a single line containing one string ― the compressed form of the given sequence.
Constraints
1≤T≤100
1≤N≤100
1 ≤ Ai ≤ 1000 for each valid i
A1 < A2 < …... <AN
Subtasks
Subtask #1 (100 points): Original constraints
Example Input
3
12
1 2 3 5 6 8 9 10 11 12 15 17
4
4 5 7 8
1
4
Example Output
1...3,5,6,8...12,15,17
4,5,7,8
4
MY Code:
#include <bits/stdc++.h>
using namespace std;
bool b[1005];
int a[1005];
int main()
{
int test, i, j, size, count;
cin >> test;
while (test--)
{
for (i = 0; i < 1005; i++)
b[i] = false;
cin >> size;
for (i = 0; i < size; i++)
{
cin >> a[i];
b[a[i]] = true;
}
for (i = 0; i < 1005; i++)
{
if (b[i] == true)
{
cout << i;
j = i;
count = 0;
while (b[j] == true)
{
count++;
j++;
}
if (count > 2)
{
i = j;
if ((j - 1) != a[size - 1])
cout << "..." << i - 1 << ",";
else
cout << "..." << i - 1;
}
if (count == 2)
{
i = j;
if ((j - 1) != a[size - 1])
cout << "," << i - 1 << ",";
else
cout << "," << i - 1;
}
if (count == 1 && ((j - 1) != a[size - 1]))
cout << ",";
}
}
}
return 0;
}
}
MY Question:
Above code runs perfectly on my device giving desired output. But when I am submitting this solution to
Online Judge , it says segmentation fault. It's sure that fundamentally I am accessing the memory incorrectly. Could you please show me where it is?
b is defined a bool[1005]
In this part
for(i=0 ; i<4000 ; i++)
b[i] = false;
You are writing false value 4000 times, exceeding the array size.
Overwriting past the array is allowed on the compiler but will have undefined behaviour in runtime.
In short: it can or can not cause a segfault.
Here is another approach given that the input data is in a file input.txt:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
class Reader {
public:
Reader(const std::string& filename) :
filename_(std::move(filename)), is_(filename_)
{
is_.exceptions( std::ifstream::failbit | std::ifstream::badbit );
}
int get_N() {
int N;
is_ >> N;
return N;
}
std::vector<int> get_ints(int N) {
std::vector<int> v;
v.reserve(N);
for (int i = 0; i < N; i++ ) {
int value;
is_ >> value;
v.push_back(value);
}
return v;
}
int get_num_cases() {
int num_cases;
is_ >> num_cases;
return num_cases;
}
private:
std::string filename_;
std::ifstream is_;
};
bool start_range_cur( std::vector<int> &v, int j, int N )
{
if ( j>= (N - 2) ) return false;
return ((v[j+1] - v[j]) == 1) && ((v[j+2] - v[j+1]) == 1);
}
bool in_range_cur( std::vector<int> &v, int j )
{
return (v[j+1] - v[j]) == 1;
}
void print_range( int min, int max, bool print_comma)
{
std::cout << min << ".." << max;
if (print_comma) std::cout << ",";
}
void print_single(int val, bool print_comma)
{
std::cout << val;
if (print_comma) {
std::cout << ",";
}
}
int main() {
Reader is {"input.txt"};
int num_cases = is.get_num_cases();
for (int i = 0; i < num_cases; i++) {
int N = is.get_N();
std::vector<int> v = is.get_ints(N);
bool in_range = false;
int range_start;
for( int j = 0; j< N; j++ ) {
if (in_range) {
if (j == (N - 1)) {
print_range(range_start, v[j], false);
}
else if (in_range_cur(v, j)) {
continue;
}
else {
print_range(range_start, v[j], true);
in_range = false;
}
}
else {
if (j == (N - 1)) {
print_single(v[j], false);
}
else if (start_range_cur(v, j, N)) {
in_range = true;
range_start = v[j];
}
else {
print_single(v[j], true);
}
}
}
std::cout << '\n';
}
return 0;
}

Program producing funky output

I am writing a program that takes in an input stream from std::cin and then fills a map container with all of the words(after removing all punctuation and making them lowercase) from the input along with their frequency.
here is my code...
#include "prog4.h"
void clean_entry(const string& s1, string& s2) {
for (int i = 0; i < s2.size(); i++) {//loop through the string
s2[i] = tolower(s2[i]);
}
}
void get_words(map < string, int >& map1) {
string input;
getline(cin, input);
string s1;
for (int i = 0; i < input.size(); i++ , s1 = "") {//loop through
entire input
if (isalnum(input[i]) == 0) {//if its a alphanumeric char
for (int d = i; isalnum(input[d]) == 0;d++) {//make s1 the
next set of characters between punctuation
s1 += input[d];
if (isalnum(input[d]) != 0)//update i to the next non
alfanumeric character position
i = d;
}
}
clean_entry(s1, s1);
map1[s1]++;
}
}
void print_words(const map < string, int >& m1) {
map<string, int>::const_iterator it;
cout << "Number of non-empty words: " << m1.size() << '\n';
int count = 0;
for (it = m1.begin(); it != m1.end(); it++) {
if (it->second == 1)
count++;
}
cout << "Number of distinct words: " << count << '\n';
it = m1.begin();
for (int y = 0; it != m1.end(); it++,y++) {
if (y % 3 == 0) {
cout << '\n';
}
cout << setw(20) << it->first << setw(10) << it->second;
}
}
int main() {
map <string, int> m1;
get_words(m1);
print_words(m1);
return 0;
}
I have tested the print and clean methods and they both work as expected. The problem I am getting is when I use the get_words method undoubtedly.
As an example when I use the input "Huge Muge Cuge luge" this is what I get as an output...
Number of non-empty words: 2
Number of distinct words: 0
16 3
I'm not sure what is causing this to happen and after reviewing the code I cant seem to find the problem which is why i'm posting here
Let me list out few problems which I can observe in your code.
The isalnum function returns non-zero value for alphanumeric characters.
That means the statement
if (isalnum(input[i]) == 0) { in function get_words should be changed to
if (isalnum(input[i]) != 0) {
Also, statement for (int d = i; isalnum(input[d]) == 0;d++) { should be changed to for (int d = i; isalnum(input[d]) != 0;d++) {
Another problem is that statement i = d; will not be executed as when for loop break it will skip those lines since conditions are just opposite. You can fix that by moving declaration of d out of for loop. The modified function should be:
=>
void get_words(map < string, int >& map1)
{
string input;
getline(cin, input);
string s1;
for (int i = 0; i < input.size(); i++ , s1 = "")
{
if (isalnum(input[i]) != 0)
{//if its a alphanumeric char
int d;
for (d = i; isalnum(input[d]) != 0;d++)
{
s1 += input[d];
}
if (isalnum(input[d]) == 0)
i = d;
}
clean_entry(s1, s1);
map1[s1]++;
}
}

Time limit exceed

The system said: my code was time limit exceed. Is there away to shortcut my code?
I'm using vector to save nails to graph.
Input: e,n
Output: checkcase=1 => Check u adjacent with i
checkcase=2 => find nails that around u
#include <iostream>
#include <vector>
#include <list>
#include <string>
using namespace std;
int main()
{
int e, n;
string u, i;
//using vectors
vector<string> graph;
//use list
list<string>listElementsInCase2;
cin >> e;
cin >> n;
//loop for e
for (long index = 0; index < e; index++)
{
cin>>u>> i;
//add u to graph
graph.push_back(u);
//add i to graph
graph.push_back(i);
}
//Option
int checkCase;
long index;
//loop for n
while(sizeof(n))
{
cin >> checkCase;
if (checkCase == 1)
{
cin >> u >> i;
for (index = 0; index < 2 * e; index += 2)
{ //Check u adjacent ? i
if ((graph.at(index) == u) && (graph.at(index + 1) == i))
{
cout << "TRUE" << endl;
break;
}
}
if (index == 2 * e)
cout << "FALSE" << endl;
}
//checkCase=2
if (checkCase == 2)
{
cin >> u;
for (long index = 0; index < 2 * e; index += 2)
{
if (graph.at(index) == u)
listElementsInCase2.push_back(graph.at(index + 1));
}
// return 0
if (listElementsInCase2.empty() == true)
cout << "0";
else
{
while (0 < listElementsInCase2.size())
{ //find nails that around u
cout << listElementsInCase2.front();
listElementsInCase2.pop_front();
cout << " ";
}
}
cout << endl;
}
n--;
}
}
//end
You seem to have an infinite while loop in your code.
Your statement while(sizeof(n)) will never stop repeating the loop since sizeof(n) always returns the byte size of the type integer, which is always a positive number and thus always evaluates as true.
A shortcut for your code would be to replace the while loop with a for or while loop that actually ends at some point. Also sizeof is probably not the function you want.
for(int i=0; i<n; i++){ might be what you are looking for.

C++ Error: Line 1440 Expression: string subscript out of range

The program builds and runs, however after entering the first integer and pressing enter then the error pop up box appears, then after pressing ignore and entering the second integer and pressing enter the pop up box appears and after pressing ignore it returns the correct answer. I am at my wits end with this can somebody help me fix the pop up box thing.
#include "stdafx.h"
#include <iostream>
#include <cctype>
#include <string>
using namespace std;
#define numbers 100
class largeintegers {
public:
largeintegers();
void
Input();
void
Output();
largeintegers
operator+(largeintegers);
largeintegers
operator-(largeintegers);
largeintegers
operator*(largeintegers);
int
operator==(largeintegers);
private:
int integer[numbers];
int len;
};
void largeintegers::Output() {
int i;
for (i = len - 1; i >= 0; i--)
cout << integer[i];
}
void largeintegers::Input() {
string in;
int i, j, k;
cout << "Enter any number:";
cin >> in;
for (i = 0; in[i] != '\0'; i++)
;
len = i;
k = 0;
for (j = i - 1; j >= 0; j--)
integer[j] = in[k++] - 48;
}
largeintegers::largeintegers() {
for (int i = 0; i < numbers; i++)
integer[i] = 0;
len = numbers - 1;
}
int largeintegers::operator==(largeintegers op2) {
int i;
if (len < op2.len) return -1;
if (op2.len < len) return 1;
for (i = len - 1; i >= 0; i--)
if (integer[i] < op2.integer[i])
return -1;
else if (op2.integer[i] < integer[i]) return 1;
return 0;
}
largeintegers largeintegers::operator+(largeintegers op2) {
largeintegers temp;
int carry = 0;
int c, i;
if (len > op2.len)
c = len;
else
c = op2.len;
for (i = 0; i < c; i++) {
temp.integer[i] = integer[i] + op2.integer[i] + carry;
if (temp.integer[i] > 9) {
temp.integer[i] %= 10;
carry = 1;
} else
carry = 0;
}
if (carry == 1) {
temp.len = c + 1;
if (temp.len >= numbers)
cout << "***OVERFLOW*****\n";
else
temp.integer[i] = carry;
} else
temp.len = c;
return temp;
}
largeintegers largeintegers::operator-(largeintegers op2) {
largeintegers temp;
int c;
if (len > op2.len)
c = len;
else
c = op2.len;
int borrow = 0;
for (int i = c; i >= 0; i--)
if (borrow == 0) {
if (integer[i] >= op2.integer[i])
temp.integer[i] = integer[i] - op2.integer[i];
else {
borrow = 1;
temp.integer[i] = integer[i] + 10 - op2.integer[i];
}
} else {
borrow = 0;
if (integer[i] - 1 >= op2.integer[i])
temp.integer[i] = integer[i] - 1 - op2.integer[i];
else {
borrow = 1;
temp.integer[i] = integer[i] - 1 + 10 - op2.integer[i];
}
}
temp.len = c;
return temp;
}
largeintegers largeintegers::operator*(largeintegers op2) {
largeintegers temp;
int i, j, k, tmp, m = 0;
for (i = 0; i < op2.len; i++) {
k = i;
for (j = 0; j < len; j++) {
tmp = integer[j] * op2.integer[i];
temp.integer[k] = temp.integer[k] + tmp;
temp.integer[k + 1] = temp.integer[k + 1] + temp.integer[k] / 10;
temp.integer[k] %= 10;
k++;
if (k > m) m = k;
}
}
temp.len = m;
if (temp.len > numbers) cout << "***OVERFLOW*****\n";
return temp;
}
using namespace std;
int main() {
int c;
largeintegers num1, num2, result;
num1.Input();
num2.Input();
num1.Output();
cout << " + ";
num2.Output();
result = num1 + num2;
cout << " = ";
result.Output();
cout << "\n\n";
num1.Output();
cout << " - ";
num2.Output();
result = num1 - num2;
cout << " = ";
result.Output();
cout << "\n\n";
num1.Output();
cout << " * ";
num2.Output();
result = num1 * num2;
cout << " = ";
result.Output();
cout << "\n\n";
c = num1 == num2;
num1.Output();
switch (c) {
case -1:
cout << " is less than ";
break;
case 0:
cout << " is equal to ";
break;
case 1:
cout << " is greater than ";
break;
}
num2.Output();
cout << "\n\n";
system("pause");
}
It seems you are falling victim to the difference between C-style strings and C++ strings. C-style strings are a series of chars followed by a zero (or null) byte. C++ strings are objects that contain a series of characters (usually char, but eventually this will be an assumption you should break) and that know their own length. C++ strings can contain null bytes in the middle of themselves without problem.
To loop through all of the characters of a C++-style string, you can do one of a number of things:
You can use the .size() or .length() members of a string variable to find the number of characters in it, as in for (int i=0; i<str.size(); i++) { char c = str[i];
You can use .begin() and .end() to get iterators to the beginning and end of the string, respectively. A for loop in the form for (std::string::iterator it=str.begin(); it!=str.end(); ++it) will loop you through the members of the string by accessing *it.
If you're using C++11, you can use the for loop construct as follows: for (auto c: str) where c will be of the type of a character of the string str.
In the future, to solve problems like these, you can try using the debugger to see what happens when your program crashes or hits an exception. You likely would find that inside of largeintegers::Input() you running into either a memory access violation or some other problem.
Finally, as a future-looking criticism, you should not use C-style arrays (where you say int integer[ numbers ];) in favor of using C++-style containers, such as vector. A vector is a series of objects (such as ints) that can expand as needed.