Having a SegFault where there should be none - c++

Program keeps throwing a seg fault under conditions where it should not. I have arrays and vectors, and have tried both options. Seems to always throw the seg fault on the third value of the array/vector of 3. There is another functions after this that when commented out lets it go a few more times. But the results is the same, it still seg faults.
char bits[3];//vector<char> bits(3,'0');
vector<string> inputs;
string temp;
for(int x = 0;!i.eof();x++)
{
getline(i, temp);
inputs.push_back(temp);
}
for(int x = 0; x < inputs.size();x++)
{
cout << endl << inputs[x];
}
for(int x = 0; x < 3;x++)
{
cout << endl << bits[x];
}
for(int cursor = 0;cursor< inputs.size();cursor++)
{
cout << endl << "bitstogoin " << cursor;
cout << endl << inputs.size();
bits[0]=inputs[cursor][0];
cout << endl << "got1 " << bits[0];
bits[1]=inputs[cursor][1];
cout << endl << "got2 " << bits[1];
bits[2]=inputs[cursor][2]; //seg faults on this line.
cout << endl << "bitsin";
for(int t = 0; t < 3;t++)
{
cout << bits[t];
}
The commands that are being given via the input file look like:
100 10110101
101 11001011
111
110
000
111
110 etc...

Note: this probably has nothing to do with your segfault but should still be addressed.
The following input loop has two problems. First, the x is pointless because you never do anything with the value of x. Second, looping on eof() is rarely correct (see: Testing stream.good() or !stream.eof() reads last line twice).
for(int x = 0;!i.eof();x++)
{
getline(i, temp);
inputs.push_back(temp);
}
Try the following instead:
while (getline(i, temp))
{
inputs.push_back(temp);
}

In your code here:
vector<string> inputs;
string temp;
for(int x = 0;!i.eof();x++)
{
getline(i, temp);
inputs.push_back(temp);
}
You read in strings and place them into a vector.
Ask yourself this? What is the length of each of these strings?
When you call
bits[2]=inputs[cursor][2];
You are accessing the 3rd character of a string in that vector. Before this statement try this:
if (inputs[cursor].size() < 3)
cout << "String is less than 3!" << endl;
If your program prints that debug line, then you know you're in trouble.
Indeed, you're not really doing anything to check the lengths of your strings before you try to access characters in them.

Related

C++: How to display the last five names/lines when reading from a file?

I've been trying to get this function to read the last five lines of a file. This is all I have so far. A similarly structured function that finds the first five lines and displays them worked fine and so does the part of this function that counts up the total number of lines.
Everything else seems to work fine except this part and I'm not sure what I'm doing wrong. I tried multiple different solutions (aka just moving the code around and deleting lines to see if it would help) but nothing worked. It can, however, display 46-50 with the colons but not the last five lines. If I were to display the names before the for loop part and within the while loop counting part, it would successfully display all of the names.
Help would be appreciated.
Thanks. (sorry if I'm not formatting this correctly)
void displayLastFive(ifstream & fin)
{
char name[81];
int totalNumberOfLines = 0;
fin.getline(name, 81);
fin.clear();
fin.seekg(0L, ios::beg);
while (!fin.eof())
{
fin.getline(name, 81);
totalNumberOfLines++;
}
for (int i = totalNumberOfLines - 5; i < totalNumberOfLines; i++)
{
fin.getline(name, 81);
cout << i + 1 << ": " << name << endl;
}
cout << endl;
}
answer was much simpler than I thought
void displayLastFive(ifstream & fin)
{
char name[81];
int totalNumberOfLines;
totalNumberOfLines = count(fin);
fin.clear();
fin.seekg(0L, ios::beg);
for (int i = 0; i < totalNumberOfLines; i++)
{
fin.getline(name, 81);
if (i >= totalNumberOfLines - 5)
{
cout << i + 1 << ": " << name << endl;
}
}
cout << endl;
}

My variables are mixing values with each other ???? C++

I have two string variables that are mixing each others letters after a certain point and I have no idea why.
string dna1 and dna2 is read in from a .txt file like this:
string opfile1(string& dnafile, string& dnaseq1); // function dec
string opfile2(string& dnafile, string& dnaseq2);
int main()
{
string dna1;
string dna2;
string seq1;
string seq2;
order1 = openSecondFile(dna1, seq1);
order2 = openThirdFile(dna2, seq2);
//function calls ^
string opfile1(string& dnafile, string& dnaseq1); // function dec
{
string PName;
string frag;
ifstream in_s;
in_s.open(dnafile.c_str());
if(in_s.fail()) //if file does not exist a fail message will appear
{
cout << "Unable to open input file " << song1File << endl;
exit(EXIT_FAILURE);
}
getline(in_s, frag, '|');
Name = frag.substr(1);
in_s >> dnaseq1;
in_s.clear();
return Name;
}
//func def.
The function opfile2 is the exact same except wherever you see a '1', I replaced it with a '2' to match its variables.
Now when I print these out in my main function they appear like this:
cout << dnaseq1 << endl;
cout << dnaseq2 << endl;
Output:
FDFDAFDAF
DFDAFDATZY
Which is correct! Now, when I try to print them using a for loop this happens:
int columns = dnaseq1Size + 1;
for(int i = 0; i < columns; ++i)
{
if(i == 0)
{
cout << setw(3) << "-" << " ";
}
else
{
cout << setw(3) << dnaseq2.at(i) << " ";
}
}
Output:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::at: __n (which is 9) >= this->size() (which is 9)
- D F D A F D A F Aborted (core dumped)
(it starts printing the other notes)
I have no idea what's happening, can anyone help?
EDIT: I figured out the issue and fixed it. I think the issue had something to do with the fact I was using arrays and a "size" so I switched to a 2D vector and used .size instead and the issue fixed it self.
It's clear enough. Your string has size 9, (FDFDAFDAF for example) but you try and print musicalnotes2.at(9). If your string has size 9 then only 0 to 8 are legal indexes
As said in the comments the suspicious part is when you write
int columns = song2Size + 1;
for(int i = 0; i < columns; ++i)
...
Why do you add one there? That seems to be the problem.
It sounds like looks like your're trying to print out each char from the musicalnotes variables
one way to be able to do it is to wrap it in a function (easier to reuse)
void printNotes(const string &musicalNotes) {
cout << setw(3) << "-" << " ";
for(int i = 0; i < musicalNotes.length(); ++i)
{
cout << setw(3) << musicalNotes.at(i) << " ";
}
cout << endl;
}
int main()
{
//... code up until you wish to print it
printNotes(musicalnotes1);
printNotes(musicalnotes2);
//... if you want something afterward
return 0;
}
Here we replace the int columns = song2Size + 1; with the length of the string, and prior to writing anything from there we write out the -
Example output would be:
- F D F D A F D A F
- D F D A F D A T Z Y
I assume that song2Size would be equal to the musicalnotes2.length(), if that's the case you do write over the strings length and therefor you get your out of bounds error. If it contains 9 chars then it would be at index 0,1...7,8 not to 9

c++ for loop with decrement update causing infinite loop?

This is part of a greater code for reading an input file word-for-word, then printing the words in reverse order. It uses a string array called words[] to store, word-by-word, the char strings from an input file earlier in the program:
//print to screen
for (int i = MAXSIZE; i >= 0; i--)
{
cout << words[i] << " ";
}
Test input file contents:
This is my test file. I hope this works.
Output is just "works. " repeating on and on.
Why is the i-- apparently never happening?
EDIT: Everything from my code. I'm on a bit of a time crunch here, to say the least. MAXSIZE=1024 part of lab prompt. Can't use vectors or reverse; seen that all over, but it's off limits for this lab. New to programming, so if you could refrain from being condescending, that'd be great. Just trying to get this to work. The reading input.txt and print to screen bit works fine. Output portion is utter fail and I don't know why. Can someone just tell me why instead of insulting me, thanks?
//Kristen Korz
//CIS 22A
//This program reads an input file and writes the words in reverse order to an output file.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//create and link input...
ifstream inputFile;
inputFile.open("input.txt");
//...and output files
ofstream outputFile;
outputFile.open("output.txt");
//error message for file open fail
if (inputFile.fail())
cout << "Error opening the file.\n";
//constant for max size
const int MAXSIZE = 1024;
//string array and temporary-use string
string words[MAXSIZE];
string str; //note: variables will be used for output loops too
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " ";
}
inputFile.close();
cout << endl;
//something wrong with for loop resulting in i apparently not updating
for (int i = MAXSIZE; (outputFile << str) && (i >= 0); --i)
{
words[i] = str;
//for showing in terminal if written correctly
cout << words[i] << " ";
}
outputFile.close();
cout << endl;
system("pause");
return 0;
}
For output with i also printed, my cout statements in the for-loops say:
cout << words[i] << " " << i << " ";
Giving terminal output:
This 0 is 1 my 2 test 3 file. 4 I 5 hope 6 this 7 works. 8
works. 1023 works. 1022 works. 1021 (lots of repeats of works. followed by decrementing numbers) works. 3 works. 2 works. 1 works. 0
Your output loop does:
words[i] = str;
for every iteration. str still holds the value of the last string you input, so this sets every member of words to be the same string. Since your last input string was "works", this explains why you output "works" every time.
It should work better if you just remove that line. Also, start from MAXSIZE - 1. The valid indices of the array are 0 through MAXSIZE-1. Your out-of-bounds access causes undefined behaviour, although apparently in this instance it had no effect.
However if your input only has 8 words as you suggest, then outputting 1024 words will give you a lot of blank space. Consider starting the output from where i got up to, instead of MAXSIZE - 1.
At the part marked as not working (the second for loop), str is being read from but it is never changed to anything else in that loop, so it repeats the last word. i is being updated, the problem is that str is not being updated.
The other issue is that you are trying to access an element past the end of the array, as WhozCraig and Velthune discussed in their answers. You need to properly figure out what you want to do with words in your second for loop. This is key. Also, you need to store where the array you read in ends.
Viewing WhozCraig's link, if you have:
const int MAXSIZE = 1024;
string words[MAXSIZE];
for (int i = MAXSIZE; i >= 0; i--) {
cout << words[i] << " ";
}
You have a string that from 0..1023.
Accessing words[1024] is potentially dangerous.
For iterate correctly your string do:
for (int i = MAXSIZE - 1; i >= 0; --i) {
cout << words[i] << " ";
}
By the way, when you fill words, add a control:
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)) {
if(str.size() <= MAXSIZE) {
words[i] = str;
}
}
update
Be sure that your string in file:
"This is my test file. I hope this works. "
doesn't end with a space. To be sure, test adding "EOF" to your string:
"This is my test file. I hope this works.EOF"
Other, do your loop in this way:
int i = 0;
while(inputFile.good() && i < MAXSIZE) {
std::string word << inputFile;
if(!word.empty())
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " ";
}
The problem why you get a lot of "works" here is:
After this piece of codes:
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " ";
}
inputFile.close();
cout << endl;
//str = "works";
The values of variable str is works.
After that, you set every elements in words by str. So every elements in the words now are the same value works.
for (int i = MAXSIZE; (outputFile << str) && (i >= 0); --i)
{
words[i] = str;//=="works"
//for showing in terminal if written correctly
cout << words[i] << " ";
}
outputFile.close();
cout << endl;

std::getline returning the wrong size

something wrong with getline(), taking the words in correct but still the value of size remains 26.
I tried printing each time it takes in a character and all of them do print so itis taking in strings correctly, but not storing them?
I have attached the code below to refer
Ask me for the whole project if you need to refer what is going wrong if someplace else.
void TldPart::PreloadTLDs()
{
ifstream in(TLD_TEST_FILE);
if(in)
{
string tld;
for(int i =0; !in.eof(); i++)
{
getline(in,tld);
String myString = tld.c_str();
//cout << myString.GetLength() << endl;
for(int j=0; j<myString.GetLength();j++)
{
myString[j]=tolower(myString[j]);
}
//cout << myString << endl;
ValidTLDs.insert(pair<String,int>(myString,i));
//ValidTLDs[myString] = true; //if the map was bool
}
in.close();
cout << ValidTLDs.size(); //Printing the size //prints 26
}
}

std::cout not working inside a for-loop

I'm new to C++, and right now I'm learning from the book called Accelerated C++. I finished the third chapter (vectors), and I came to this exercise:
"Write a program to count how many times each distinct word appears in its input."
After some thinking, I started working on it. I wanted to test the program, but std::cout wasn't working. I put cout << "test"; on a few places in my code to see where's the problem, and the conclusion is that it doesn't work inside the first for-loop. Don't recommend me to use maps to solve the problem, because I'm working on vectors. The variables aren't in English, so I'll translate some for you to know what's going on:
recenica - the sentence; rijec - a word; vel_vektora - size of the vector; duz_recenice - length of the sentence; br_ponavljanja - number of times a word appears in the sentence;
#include <vector>
#include <iostream>
#include <string>
using std::string; using std::vector;
using std::cin; using std::cout;
using std::endl;
int main()
{
string rijec;
vector<string> recenica;
while (cin >> rijec) recenica.push_back(rijec);
cout << endl;
typedef vector<string>::size_type vel_vektora;
vel_vektora duz_recenice = recenica.size();
cout << "test0, ";
for (int i = 0; i < duz_recenice - 1; ++i)
{
cout << "test, !";
int br_ponavljanja = 1;
for (int j = i + 1; j < duz_recenice; ++j)
{
cout << "test2, ";
if (recenica[i] == recenica[j])
{
cout << "test3, ";
++br_ponavljanja;
recenica.erase(recenica.begin() + j);
}
cout << "test4, ";
}
cout << recenica[i] << ": " << br_ponavljanja << endl;
}
cout << "test5, ";
getchar();
return 0;
}
What's the problem with the std::cout?
Add << flush to flush your output buffer (each place).
Or use << endl, which both adds newline and flushes.
There are problems with the code, especially for empty input, but that's what you're out to learn about, so I'll leave you to it! :-)
Cheers & hth.,
I'm afraid the language eludes me in terms of variable names, but this "Works for Me™".
Here is my output (First 3 lines input:)
ytreyert
tyryteter
gdhdfgdf
^Z
test0, test, !test2, test4, test2, test4, ytreyert: 1
test, !test2, test4, tyryteter: 1
test5,
You should definitely try flushing the cout buffers after printing (as per Alf's answer).
I notice that gdhdfgdf is not counted, this is because of this line:
for (int i = 0; i < duz_recenice - 1; ++i)
If you only give 1 input word, this loop will not run, as you do duz_recenice = recenica.size(); before looping.
Changing this line to
for (int i = 0; i < duz_recenice; ++i)
solves this problem.