Sorting array of strings causes seg fault - c++

I'm trying to write a sort to sort an array of strings in ascending order I have the function as:
void mySort(string list[], int size) {
for (int i=0; i<size; i++){
for (int j=0; j < size-i; j++){
if (strcmp(list[j].c_str(),list[j+1].c_str())< 0);{
std::swap(list[j], list[j + 1]);
}
}
}
}
and then the function that uses the sort:
void q0run(question q){
std::string input = q.programInput; //Place the data file in a variable
//cout << input << endl; //Test to make sure data file stored correctly - works
std::ifstream inputFile (input.c_str()); //Open File
if(inputFile.good()){ //Make sure file is open before trying to work with it
//Begin Working with information
cout << "In File: \t" << input << endl;
int number_of_lines = 0;
std::string line;
while (std::getline(inputFile, line)){
++number_of_lines;
}
std::cout << "Number of lines in text file: " << number_of_lines << endl;
std::string dataStorage[number_of_lines];
inputFile.clear();
inputFile.seekg(0);
for(int loop=0;loop<number_of_lines;loop++){
getline(inputFile,dataStorage[loop]);
}
mySort(dataStorage,number_of_lines);
for(int loop=0;loop<number_of_lines;loop++){
cout << dataStorage[loop] << endl;
}
inputFile.close();
}else{
cout << "Could not open file!!!" << endl;
}
}
When I run the program though it segfaults at the sort. Not sure what I'm doing wrong:
In File: data01a.txt
Number of lines in text file: 253
Segmentation fault (core dumped)
The array to be sorted is being populated, I can run a loop on it and print it all out unsorted, any ideas? An easier sorting method will be fine too! Thanks!

if (strcmp(list[j].c_str(),list[j+1].c_str())< 0);{
Oops!
There's an extra ; so the swap will always occur;
Your inner loop needs one fewer iterations, otherwise j+1 jumps off the end;
And are all those C-string conversions really necessary?
std::string::compare would do the job...

The actual bug in your code was answered in a comment.
Your "j+1" index can be out of bounds and in the first iteration it is. You therefore need to loop j up to size-i-1 or iterate i from 1 onward, thus..
for (int i=1; i<size; i++)
I assume this is some kind of exercise as the correct way to sort is simply to use std::sort.
You have also been offered alternative ways to compare two strings, the simplest of which is just its overloaded operator<, thus
if( list[j] < list[j+1] )

You have an out of bounds access which may be the cause
for (int i=0; i<size; i++){
for (int j=0; j < size-i; j++){
if (strcmp(list[j].c_str(),list[j+1].c_str())< 0){
std::swap(list[j], list[j + 1]);
}
On the first iteration you have
i=0; j=size-1 =>strcmp(list[size-1].c_str(),list[size])
change the stop condition in the first loop:
for (int i=0; i<size-1; i++){
for (int j=0; j < size-i; j++){
if (strcmp(list[j].c_str(),list[j+1].c_str())< 0){
std::swap(list[j], list[j + 1]);
}
hope this helps.

This code does what you want in C++11:
#include <algorithm>
#include <iostream>
#include <array>
#include <string>
using namespace std;
int main()
{
string s1 = "hello";
string s2 = "world!";
string s3 = "peanut";
string s4 = "butter";
array<string,4> ar = {s1,s2,s3,s4};
sort(ar.begin(),ar.end());
for(auto elem : ar)
cout << elem << endl;
return 0;
}

Related

Why is my program to read a vector of strings into an array of character pointers not displaying any output?

I'm on exercise 4.34 of the book C++ Primer, 4th edition, which states "Write a program to read strings into a vector. Now, copy that vector into an array of character pointers. For each element in the vector, allocate a new character array and copy the data from the vector element into that character array. Then insert a pointer to the character array into the array of character pointers." I'm also trying to print the vector and character pointer array, and delete the character pointer array afterwards.
Here's what I've come up with so far:
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
int main()
{
cout << "Enter some strings:" << endl;
vector<string> svec;
string input;
while (cin >> input) {
svec.push_back(input);
}
size_t sarr_sz = svec.size();
char **sarr = new char*[sarr_sz];
size_t carr_sz, carr_num;
char *carr = NULL;
for (vector<string>::size_type i = 0; i < svec.size(); ++i) {
carr_num = i;
carr_sz = svec[i].size();
carr = new char[carr_sz + 1];
size_t cval;
for (string::size_type j = 0; j < svec[i].size(); ++j) {
cval = j;
carr[cval] = svec[i][j];
}
cval = svec[i].size();
carr[cval] = '\0';
sarr[carr_num] = carr;
}
cout << "Vector contents:" << endl;
for (vector<string>::size_type i = 0; i < svec.size(); ++i) {
cout << svec[i] << " ";
}
cout << endl;
cout << "Character pointer array contents:" << endl;
for (size_t i = 0; i < sarr_sz; ++i) {
cout << sarr[i] << " ";
}
cout << endl;
for (size_t i = 0; i < sarr_sz; ++i) {
delete [] sarr[i];
}
delete [] sarr;
return 0;
}
When I compile and run this program, it freezes at the point after entering the string input and displays no output. When I exit the program manually using Ctrl-C, it displays either Vector Output: <first string inputted> or just Vector Output:. I've gone over the program multiple times and can't figure out where I've made an error.
Please keep in mind that I'm a beginner, and I'm just following the conventions of the book. As such, my program is probably neither efficient nor follows correct style. Any help would be greatly appreciated. Thank you.

How to fix a "runtime error" that doesn't affect performance?

Submitted a problem to an online judging platform. Code works perfectly with the provided samples, but judge outputs "runtime error", nothing more.
Code is supposed to calculate resulting fractions from inputs
Sample inputs:
27 12
2460000 98400
3 4000
Line containing 0 0 will follow the last input. First number is the numerator, second is the denominator.
Current code:
#include <iostream>
using namespace std;
int main(){
int num[500], den[500], ent[500];
for (int i = 0; i < 500; i++) {
num[i] = 0;
den[i] = 0;
ent[i] = 0;
}
int i=1;
num[0]=1; den[0]=1;
while((num[i-1]!=0)&&(den[i-1]!=0)){
cin >> num[i] >> den[i];
i++;
} i--;
for(int j=1; j<i; j++){
ent[j]=num[j]/den[j];
num[j]=num[j]%den[j];
}
for(int j=1; j<i; j++){
cout << ent[j] << " " << num[j] << " / " << den[j] << endl;
}
return 0;
}
My psychic debugging skills tell me that the input they give you has more than 499 lines causing your program to run off the end of its hardcoded arrays.
Have you considered std::vector or an approach that doesn't cache all the input before processing?

I want to declare a pointer array to character without using string

Here is the code::
#include <iostream>
using namespace std;
const int MAX = 4;
int main ()
{
char key[20];
char *names[MAX];
for (int i=0; i<MAX; i++)
{
cout << " entr keys\n";
cin >> key;
names[i]=key;
cout<< names[i];
}
for(int i=0; i<MAX;i++)
{
cout << names[i];
}
return 0;
}
When I enter the keys and print them in the 1st for loop they show the right value, but when I print names[i] in the 2nd for loop it keeps showing the last key entered again and again.
Please tell me: where am I going wrong?
When you run names[i]=key; you don't really copy key's string value to names[i].
It just makes name[i] point to where key is (since both name[i] & key are pointers).
so all in all you're overwriting key several times, and making all of names pointers point to key.
You need to copy those strings either by working with std::string instead of char* or by using strcpy. I'd recommend on working with std::string.
Using std::string your code should look like this:
#include <iostream>
#include <string>
using namespace std;
const int MAX = 4;
int main ()
{
string names[4];
for (int i = 0; i < MAX; i++)
{
cout << "entr keys" << endl;
cin >> names[i];
cout << names[i];
}
for(int i=0; i<4;i++)
{
cout << names[i];
}
return 0;
}
Every time you execute the lines
cout << " entr keys\n";
cin >> key;
you're inserting a null-terminated string into key, e.g. "hello\0".
Afterwards you copy key's address and store it into a cell of the names pointers array:
names[i]=key; // Now I point to 'key'
cout<< names[i];
then the cycle starts again. Anyway from the second time on you're inserting null-terminated strings into key and thus overwriting the previous contents. The second time if you had entered "hi\0" the contents of the key array would become
['h', 'i', '\0', 'l', 'l', 'o', '\0']
anyway you're going to only print the first string since the null terminator will prevent the other content from being displayed.
When the program ends you're going to have four pointers to the same key array and that array will only contain the last element inserted which overwrote the previous ones.
In order to solve you can make your array a bidimensional one (or use a string array):
const int MAX = 4;
int main ()
{
char key[4][20]; // <- Now this has two indices
char *names[4];
for (int i = 0; i < MAX; i++)
{
cout << " entr keys\n";
cin >> key[i];
names[i]=key[i];
cout<< names[i];
}
for(int i=0; i<4;i++)
{
cout << names[i];
}
return 0;
}
Live Example
Corrected program:
#include <iostream>
using namespace std;
#include <cstring>
const int MAX = 4;
int main ()
{
char key[20];
char *names[MAX];
for (int i = 0; i < MAX; i++)
{
cout << " entr keys\n";
cin >> key;
names[i] = new char[strlen(key) + 1];//names[i]=key;
strcpy(names[i], key);
cout<< names[i];
}
for(int i=0; i<MAX;i++)
{
cout << names[i];
}
for(int i=0; i<MAX;i++)
{
delete [] names[i];
}
return 0;
}
You need to allocate space for each names[i] and when done, deallocate
also, changed the hardcoded 4 to MAX

not getting any output from my letter count program

I'm working on program that counts letters in a piece of text, I can't seem to get it to work. Could someone please point out what I'm doing wrong.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string inputxt;
cout << "enter txt:\n";
getline(cin, inputxt);
char charcheck[ ]={'a', 'b', 'c', 'd'};
int charsize=sizeof(charcheck)/sizeof(char);
int count[charsize];
cout << charsize;
for (int i=0; i==inputxt.length(); i++){
for(int a=0; a==charsize; a++){
if (inputxt[i]==charcheck[a])
++count[a];
}
}
for (int b=0; b==charsize; b++){
cout << "number of " << charcheck[charsize] << ": " << count[charsize];
cout << endl;
}
return 0;
}
Please note I have not put in all the characters to check the text against. Thanks.
for (int i=0; i==inputxt.length(); i++){
The for construct takes 3 parameters:
initialization
continuation condition (and not termination condition like you did). read it as a while ...
loop action (aka. afterthought)
In other words, for (INIT; CONTINUATION; AFTERTHOUGHT) { BODY } is directly translated as:
INIT;
while (CONTINUATION) { BODY; AFTERTHOUGHT; }
Reverse your middle condition, it should be i!=inputxt.length(). The same applies to every other for loops.
In your for loops, you're using == instead of <. For example:
for (int i=0; i==inputxt.length(); i++)
should be:
for (int i=0; i < inputxt.length(); i++)

How to bubble sort array of pointers to the another array of chars

I have one array containing chars from the input and the other array containing pointers to the corresponding chars in the first array. This part went good.
But then I would like to bubble sort the char** array (array of pointers) so the original array stays untouched but something goes wrong(the text is not sorted).
EDIT: Please discuss only the sorting algorithm
char tab[200];//array of chars
char** t = new char*[tabLength];
//SOMETHING
....
....
int n = tabLength;//length of tab(length of the word it contains)
//TILL HERE EVERYTHING IS FINE -----------------------------------
//bubble sorting below
do{
for(int i = 0; i < n -1; i++){
if(*t[i] > *t[i+1]){
char* x = t[i];
t[i] = t[i+1];
t[i+1] = x;
}
n--;
}
}while(n>1);
cout<<"sorted input";
for(int i = 0; i < tabLength; i++)
cout<<t[i];
cout<<endl;
cout<<"original"<<tab<<endl;
Make sure you print out the values that the pointers point at:
for(int i = 0; i < tabLength; i++)
cout << *t[i];
I would simply use the functionality already at my disposal in the standard library:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string original;
std::getline(std::cin, original);
std::cout << '|' << original << "|\n";
std::string sorted = original;
std::sort(std::begin(sorted), std::end(sorted));
std::cout << "Sorted : " << sorted << '\n';
std::cout << "Original: " << original << '\n';
}
Test run:
|Hello world, how are you doing today?|
Sorted : ,?Haadddeeghilllnoooooorrtuwwyy
Original: Hello world, how are you doing today?