Why do I get an Segmentation fault error - c++

My code works fine on codeblocks compiler on my computer but when I upload it to an online editor I get an Segmentation fault error and I don't know why.
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <fstream>
using namespace std;
int main(int argc, char *argv[]) {
ifstream stream(argv[1]);
char line[1000];
int x,last=-1;
while (stream>>line)
{
x = atoi(strtok(line,","));
cout<<x;
last=x;
while(x=atoi(strtok(NULL,",")))
{
if(x!=last)
{
cout<<","<<x;
last=x;
}
}
cout<<endl;
}
return 0;
}
You are given a sorted list of numbers with duplicates. Print out the sorted list with duplicates removed.
And this is the input
6,7,8,9,9,10,11,12,13,14,15
11,12,13,14,15,16,17,18,19,20
2,2,2,2,2
10,11,12,13,14,15,16,16,17
13,14,14,15,16,17,17,17,18
15,16,17,17,18,18,18,18,19,19,20
2,3,4,5,5
13,14,15,16,17
10,11,12,13,14,15,15,15,15,16,16,16
12,13,14,15,16,17,17,18
5,6,7,8,9,10,11
14,14,14,15,15,16,17,17,18,19,19,20,21,22
13,14,15,16,16,17,17,18
15,16,17,18,19,20,21,21,21,21,22,22
6,6,6,7,8,9,10,11,11,11,12,12,13
12,12,13,14,15,15,16,17,17,18,19,19,20,21
8,9,9,9,10,10,11,12,13,13,14,15
12,13,14,15,16,17,18
1,1,1,2,2,3,3,4,4
1,2,3,4

Since you're asking us to guess, let's start at the top ....
The code doesn't check that argv[1] is valid. If not, then you just dereferenced a null-pointer, and that caused your segmentation fault.
Does your "online editor" pass parameters? I suggest checking argc > 1.
Next, your code looks like it will pass a null pointer to atoi at the end of every line. That's another segmentation fault.

You are calling atoi with the result of strtok.
If strtok doesn't find anything it returns a null pointer.
This is the case at the end of the line.
So you are passing a null pointer to atoi which then leads to a crash.
Using your example this should work:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
ifstream stream(argv[1]);
char line[1000];
char* ln;
char* num;
int x;
int last;
while (stream >> line)
{
ln = line;
last = -1;
while (num = strtok(ln, ","))
{
x = atoi(num);
if (x != last)
{
if(last != -1) cout << "," << x;
else cout << x;
last = x;
}
ln = NULL;
}
cout << endl;
}
return 0;
}
EDIT: Another solution with checking for valid paramters and w/o strtok and atoi:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
if (argc < 2) {
cout << "Usage: " << argv[0] << " <file>";
return 1;
}
ifstream stream(argv[1]);
if (!stream.is_open())
{
cout << "Failed to open file \"" << argv[1] << "\"";
return 2;
}
char line[1000];
while (stream >> line)
{
int last = -1;
int x = 0;
for (char* pos = line; pos < line + strlen(line); pos++)
{
if (*pos >= '0' && *pos <= '9')
{
x = (x * 10) + (*pos - '0');
}
else
{
if (last != x)
{
if (last != -1) {
cout << ',';
}
cout << x;
last = x;
}
x = 0;
}
}
cout << endl;
}
return 0;
}

Related

Function find() works incorrect

My task is to check if a number contains 8 or not. I've converted the number into a std::string and have used its find() method. But it only works with a number which starts with 8, for example 8, 81, 881, etc. For numbers like 18, 28, etc, it doesn't work.
#include <iostream>
#include <math.h>
#include <string>
using namespace std;
unsigned long long g = 0;
int main()
{
string str;
cin >> str;
int f = stoi(str);
string eig = "8";
for (int a = 1; a <= f; a++)
{
string b = to_string(a);
if (b.find(eig) != size_t() && b.rfind(eig) != size_t())
{
cout << "It worked with " << b << "\n";
g++;
}
}
cout << g;
}
You are using std::string::find() and std::string::rfind() incorrectly. They do not return size_t() if a match is not found. They return std::string::npos (ie size_type(-1)) instead. size_t() has a value of 0, so find(...) != size_t() will evaluate as true if no match is found at all (-1 != 0), or any character other than the first character is matched (>0 != 0). This is not what you want.
Also, your use of rfind() is redundant, since if find() finds a match then rfind() is guaranteed to also find a match (though just not necessarily the same match, but you are not attempting to differentiate that).
Try this:
#include <iostream>
#include <string>
using namespace std;
unsigned long long g = 0;
int main()
{
int f;
cin >> f;
for (int a = 1; a <= f; a++)
{
string b = to_string(a);
if (b.find('8') != string::npos)
{
cout << "It worked with " << b << "\n";
++g;
}
}
cout << g;
}
#include <iostream>
#include <string>
#include <cassert>
int main(int argc, char **argv) {
auto s = std::to_string(1234567890);
assert(s.find('8') != std::string::npos);
return 0;
}
Is this what you want?

why my cpp code can't run?(about char*[])

this is my code
the error is Segmentation fault,and i can't understand why
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
char* szword[100];
int i = 0;
do
{
cin >> szword[i];
cout << szword[i];
i++;
}while(strcmp(szword[i - 1], "done"));
cout << i + 1;
return 0;
}
For starters neither declaration from headers <cstdio> and <string> is used in your program. So you should remove these directives
#include <cstdio>
#include <string>
You declared an initialized array with the element type char *. Thus this statement
cin >> szword[i];
invokes undefined behavior because the pointer szword[i] has indeterminate value.
Moreover this call even if the argument of the operator will be correct
cin >> szword[i];
can fail. You should check whether it was successful. And I think there is no great sense to output the string "done".
Also in this statement
cout << i + 1;
you are outputting a value that is greater than the number of inputted strings.
If to use character arrays then your program could look the following way
#include <iostream>
#include <cstring>
int main()
{
const size_t N = 100;
char szword[N][N];
size_t i = 0;
while ( std::cin.getline( szword[i], sizeof( szword[i] ) ) &&
std::strcmp( szword[i], "done" ) != 0 )
{
std::cout << szword[i++] << '\n';
}
std::cout << i << '\n';
return 0;
}
The program output might look like
Hello
World
2
This below code works fine, if you want to use char *, for C++ string you can use the C++ version
C Version:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
char *tmp;
int i = 0;
do
{
cin >> tmp;
cout << tmp;
i++;
}while(strcmp(tmp, "done"));
cout << i + 1;
return 0;
}
C++ Version:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
string tmp;
int i = 0;
do
{
cin >> tmp;
cout << tmp;
i++;
}while(tmp != "done"));
cout << i + 1;
return 0;
}

C++ - Checking if a word is palindrome in struct data type

I want to know how to check if a word is palindrome in struct data type or object whatever you want to call it. I want to read a data from file then I need to check if that type of word that I have read is a palindrome or not. Also i need to reverse order of the words but I did that so do not need any help about that.
Here is the code:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
struct lettersStr
{
string name;
string object;
};
int main(int argc, char** argv)
{
ifstream letter;
letter.open("letter.txt");
lettersStr things[200];
int numberOfThings= 0;
while(letter >> letter[numberOfThings].name >> letter[numberOfThings].object)
{
numberOfThings++;
}
for (int i = 0; i < numberOfThings; i++)
{
cout << letter[i].name << " " << letter[i].object<< endl;
}
string names;
for (int i = 0; i < numberOfThings; i++)
{
names= things[i].name;
}
for (int i = numberOfThings- 1; i >= 0; i--)
{
cout << things[i].name << endl;
}
bool x = true;
int j = names.length() - 1;
for (int i = 0; i < j; i++,j--)
{
if (things[i].name.at(i) != things[i].name.at(j))
x = false;
if (x)
{
cout << "String is a palindrome ";
}
else
cout << "String is not a palindrome";
}
And here is the cout:
Kayak Audi
Ahmed Golf7
Ahmed
Kayak
String is not a palindrome
String is not a palindrome
I think major problem is this:
for (int i = 0; i < j; i++,j--)
{
if (things[i].name.at(i) != things[i].name.at(j))
x = false;
As you can see it wont cout right way of checking if a word is palindrome or not.
P.S: If this is a stupid question I am sorry, I am a beginner in C++ programming.
Cheers
As already pointed out in the comments, for (int i = 0; i < j; i++,j--) loops though things and the letters of their names simultaneously. You also have to account for cases where you compare a lower and an upper case letter such as the 'K' and 'k' at the beginning and end of 'Kayak'. You can use std::tolower for this.
Here is an example (live demo):
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
bool is_palindrome(std::string name)
{
if (name.empty())
return false;
// As has been pointed out, you can also use std::equal.
// However, this is closer to your original approach.
for (unsigned int i = 0, j = name.length()-1; i < j; i++,j--)
{
if (std::tolower(name.at(i)) != std::tolower(name.at(j)))
return false;
}
return true;
}
struct lettersStr
{
string name;
string object;
};
int main(int argc, char** argv)
{
std::vector<lettersStr> vec = {lettersStr{"Kayak","Boat"},lettersStr{"Audi","Car"}};
for (const auto &obj : vec)
if (is_palindrome(obj.name))
std::cout << obj.name << " is a palindrome" << std::endl;
else
std::cout << obj.name << " isn't a palindrome" << std::endl;
}
It gives the output:
Kayak is a palindrome
Audi isn't a palindrome

Segmentation Fault 11 while trying to run compiled C++ code

I am doing an assignment (.csv-parser) for uni. While trying to run the code after compilation it returns a SegFault 11.
This is my code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
int main (int argc, char** argv) {
string line;
string buffer;
vector<vector<string> > database;
vector<string> dataset;
//bool start = true;
ifstream denkmaeler;
denkmaeler.open(argv[1]);
ifstream denkmal;
denkmal.open(argv[1]);
int semic = 1;
//int semic2 = 1;
int zaehler = 0;
if (denkmal.is_open()){
(getline(denkmal, buffer));
for (int i = 0; i < buffer.length(); i++ ){
if(buffer[i] == ';'){
semic++;}
}
}
denkmal.close();
if(denkmaeler.is_open()) {
//if (counter < 1) {
while (getline(denkmaeler, buffer));
if (line.back() == *argv[2]) {
line += argv[2];
stringstream ss(line);
while (getline(ss, line, *argv[2])) {
dataset.push_back(line);
database.push_back(dataset);
dataset.clear();
}
}
}
for (int x=0, y=semic; x < semic; y=database.size(), x++, y++){
if (x > semic){
x=0;
cout << '\n' << "-------------------------------" << '\n' << endl;
}
if (database[y][0].length() == 0){
database[y][0] = "not available";
}
cout << database[x][0] << " : " << database[y][0] << endl;
}
}
If someone would be able to point out my mistake I would be very thankful. I read some posts pointing out that the problem could be an array but I am not sure how that could be.
For segmentation error, it is best to use a debugging tool which can exactly show you where the error is (which line)!
I am using gdb, i recommend you to google it

Program executes correctly then segfaults

At the end of the program, my array prints out properly, and then the program segfaults. Why?
#include <iostream>
#include <stdio.h>
#include <iomanip>
#include <string.h>
using namespace std;
int main(int argc, char *argv[]) {
FILE *file = fopen(argv[1], "r");
struct item{
char type[9];
int price;
bool wanted;
};
item items[20]; char temp[8];
for (char i = 0; i < 100; i++)
{
if (fscanf(file,
"%[^,], %[^,], %d",
items[i].type,
temp,
&items[i].price) != 3)
break;
else if (!strcmp(temp, "for sale"))
items[i].wanted = false;
else if (!strcmp(temp, "wanted"))
items[i].wanted = true;
else
cout << "aaaagghghghghhhh!!!" << endl;
}
for (char i = 0; i < 100; i++)
{
cout << items[i].type << endl;
cout << items[i].price << endl;
cout << items[i].wanted << endl;
}
}
Your array is declared with only 20 spaces, yet your loop goes to 100. Maybe change your array to have 100 spaces.
Use
item items[100];
Overflowing arrays leads to undefined behavior. It is possible that your code wrote into memory required by the C++ run-time during program stack unwinding, etc.