Below is my code;
int main(){
ifstream infile;
infile.open(fin);
ofstream outfile;
outfile.open(fout);
char c;
int input_order = 0;
string comp_str = "";
vector <string> pfx_str;
srand(time(NULL));
if (infile.fail())
{
cout << "cannot open file!" << endl;
return 0;
}
while (!infile.fail())
{
cout << input_order << endl;
c = infile.get();
if (c == '\n')
{
if (strcmp(comp_str.c_str(), "") != 0)
{
pfx_str.push_back(comp_str);
}
int num = rand() % pfx_str.size();
while (num == 0)
{
num = rand() % pfx_str.size();
}
for (int i = 0; i < num; i++)
{
outfile << "/" << pfx_str.at(i);
}
outfile << "\n";
input_order++;
pfx_str.clear();
}
else if (c == '/')
{
if (comp_str != "")
{
pfx_str.push_back(comp_str);
}
comp_str = "";
}
else
{
comp_str = comp_str + c;
}
}
infile.close();
outfile.close();
return 0;
}
For small set which consist of 10k inputs, it works.
However, for big set such as using 1600k inputs, it prints out 00000, and does not work. What makes it happened? and how to make it correctly working?
(Previously, I used this code for 1600k input and it works correctly....)
In compile, I used g++ -std=gnu++0x .....
I googled this issue but could not find out the right answer.. And also I could not figure out what this issue comes from....
Thanks,
+
This code is for randomly cutting the input.
This is the example of 1 input set; (to show the input pattern)
/aa/ab/bc/aaa/
Here, I consider 'aa', 'ab', 'bc', and 'aaa' as one component.
And I want randomly cut this input as components unit.
this is the brief step of the code;
1. generate the random number(except 0)
2. ex) I use the above input and the random number is 2.
then I cut this input and only '2' components is left, which is /aa/ab/
(repeat this procedure for each inputs in input text file
=> this input; /aa/ab/bc/aaa/
(inside, it generate random number 2)
output to be printed in output file; /aa/ab/
There is nothing wrong with your code.
I updated your code so that it compiles with g++:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main(){
ifstream infile;
infile.open("fin.txt"); // substituted a real file name in here to test
ofstream outfile;
outfile.open("fout.txt"); // ditto here
...the rest is the same as what you put above.
named it test.cpp, and compiled it with:
g++ -lm test.cpp -o test.exe
I wrote a Ruby script to make the input file according to the test set you specified in the comments:
#!/usr/bin/env ruby
File.open( 'fin.txt', 'w') do |f|
1600000.times do
f << "/aa/ab/bc/aaa/\n"
end
end
I then ran the compiled program test.exe, and you totally owe me a beer for watching your line numbers go that high. This is time spent from my life for you that I will never get back. 😂
and got an expected fout.txt with
/aa
/aa/ab
/aa
/aa/ab
/aa/ab/bc
/aa/ab/bc
/aa/ab
/aa/ab/bc
/aa/ab
etc.
My guess is that your system's constraints are causing a system fault. I ran this on a typical desktop machine with a ton of memory, etc. If you're running it on an embedded system, it may not have similar resources. At this point, I was tempted to test on a Raspberry Pi, but I'm burning too much time on this already. Just know that there is nothing wrong with your code.
In the future, try to figure out what your coding problem is. Stack Overflow is super forgiving if you've really tried and can't figure out the solution, but you need to show what you've tried and what happened as a result. For problems that started out like this, where you think that you're trying to figure out an algorithmic problem, always give the data set and the unexpected result that occurred.
Good luck!
Related
I am trying to run a code sorting the ages of Titanic survivors from a text file. It compiles fine, but the program terminates simply saying "segmentation fault" when I choose option B (option A is not written yet.)
Here is a small sample of the text file for reference.
29 1stClass TRUE
0.9 1stClass TRUE
2 1stClass FALSE
30 1stClass FALSE
I've isolated the error to the chunk where the file is processed (//actual processing), but I'm not sure what exactly is wrong.
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <fstream>
#include <ctype.h>
void sortSurvivors();
void sortAgesLiving();
int main()
{
char options;
std::cout << "Titanic Data \nOptions \nA) Display count of people who lived and died... \nB) Display count of people who lived by age... \nPlease select option (A-B)...";
std::cin >> options;
switch (options)
{
case 'A':
sortSurvivors();
break;
case 'B':
sortAgesLiving();
break;
}
}
void sortSurvivors()
{
}
void sortAgesLiving()
{
std::ifstream inputFile;
std::string filename = "TitanicData.txt";
std::string age;
std::string classBoat;
std::string survival;
bool survived;
int eldest = 0;
//pre-sort processing
while (inputFile >> age >> classBoat >> survival)
{
int ageConv = stoi(age);
//G is for the ghetto fix I am pulling here, because I recieve an error when using "TRUE" as a string
char gchar = 'G';
survival += gchar;
if (survival == "TRUEG")
{
survived = true;
}
else
{
survived = false;
}
if (eldest < ageConv)
{
eldest = ageConv;
}
}
//initialize vector
std::vector<int> survivorVector;
for (int i = 0; i < eldest; i++)
{
survivorVector.push_back(0);
}
inputFile.open(filename);
//actual processing (ERROR HERE)
if (inputFile)
{
while (inputFile >> age >> classBoat >> survival)
{
int ageConv = stoi(age);
if (survived = true)
{
survivorVector[ageConv] = survivorVector[ageConv] + 1;
}
for (int j = 0; j <= eldest; j++)
{
std::cout << j << "\t" << survivorVector[j] << "\n";
}
}
// Close the file.
inputFile.close();
}
else
{
std::cout << "I don't know what broke, but uhhhhhhhhhh oops.";
}
}
As per usual I'm sure it's something dumb I overlooked.
In sortAgesLiving(), you have forgotten to open the file before starting your pre-sort processing. As a consequence, your first reading loop will fail to read anything at all. Therefore eldest will stay 0.
You then construct a vector and populate it. But since the loop is based on eldest, the vector survivorVector will stay empty.
When you finally open the file and read it, the first line will be considered as a survivor since you accidentally overwrite the boolean with true (i.e. if (survived = true) instead of if (survived == true) or simply if (survived). You'll then try to access the vector out of bounds.
Even if you correct this error, at the first survivor you'll get again out of bounds. Accessing a vector out of bounds is UB and one of the many possible symptoms can be segmentation fault.
Miscellaneous advices (not related to your issues):
You have an ambiguous age of 0.9. Converting it to an int will cause it to be 0. Is this ok, or do you need to round this up?
If it's rounding up, you could make the age variable a double and read it directly without conversion. You could then convert it mathematically to an integer age rounding it up or truncating it, as needed. If you're sure to have only integers, you could make the variable an int and not worry at all.
It is unsafe to trust a value in a file to directly index a vector. What if between the two reading phases, an additional line would have been added by someone else to the file with a value higher than eldest ? What if the value read would be negative? Better always check that it's in an acceptable range before using a value as an index. It can save you hours of debugging and your customers some nightmares.
Finally, the two-phase read is not necessary: you could just read the age, and after having checked that it's positive and smaller than 150 years (quite optimistic), you could, if needed, resize your vector if the age is equal or larger than the current vector size. Why? Imagine you work one day for US census with files having millions of lines: the fewer passes over the file, the better ;-)
I'm new to C++ and not sure where to start importing a txt file with 100 numbers, then to make a code to find the sum and average of up to 100 numbers
Can anybody help?
Actually, you already have given the answer yourself. First, find out how to read a file. Then, find out how to convert the text in the file to numbers (you will have to decide what kind of number, like integers, floats or complex). Then, summing up the numbers and computing the average are the next two steps.
Just take one step at a time and make sure you always only try small tasks that you can comprehend in isolation. Even when writing something bigger, it often pays to create a simple test example for one small task first. Also, creating a small test example is a prerequisite to posting at Stack Overflow, see the guidelines for further info.
I hope, this example will help you:
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
using namespace std;
/* file.txt
2
3
4
6
*/
int main()
{
string line;
ifstream file("file.txt"); // reading from file: http://www.cplusplus.com/doc/tutorial/files/
if (file.is_open())
{
int sum = 0;
while (getline(file, line))
{
int num = atoi(line.c_str()); // convertion from string into int with 'atoi': http://www.cplusplus.com/reference/cstdlib/atoi/
sum += num;
}
file.close();
cout << "Sum is " << sum << endl; // Sum is 15
}
else
{
cout << "Unable to open file" << endl;
}
return 0;
}
I have this code that should get minimal value and maximal value from user before writing random numbers to a file but it writes to the file and skips the waiting for user input. How to wait and get the user input before writing to file and use the input from the user to write to the file.
Solution: It works except that I have run the following command: g++ randomNumbers.cpp and expected the program to run right after but I forgot to run it manually by running the output file.
#include <iostream>
#include <fstream>
#include <string>
const bool CREATE_FILE = true;
void getMinMax(int&,int&);
void writeFile(std::ofstream&, int&, int&);
int main(){
if (CREATE_FILE){
int min;
int max;
std::ofstream outfile;
getMinMax(min, max);
writeFile(outfile, min, max);
}
}
void getMinMax(int& min,int& max){
std::cout << "Enter min: ";
std::cin >> min;
std::cout << "Enter max: ";
std::cin >> max;
}
void writeFile(std::ofstream& file, int& min, int& max){
file.open("numbers.txt", std::fstream::out);
for (int i = 1; i <= 10; i++){
file << min + (rand() % (int)(max - min + 1));
}
file.close();
}
I don't see any problem with this program. It does what is expected, using Visual Studio 2015 Express. The only bug I see is this:
file << min + (rand() % (int)(max - min + 1));
This appends numbers to the file one after the other, without any separating whitespace. The result for me was the text file containing:
208131917161201920
I'd replace that line with:
file << min + (rand() % (max - min + 1)) << ' ';
By itself, I cannot see how this code does not work on your machine. Try using a different compiler or state the explicit results of the program on your end (e.g. does "numbers.txt" ever get created, and if so, what is inside it if anything?). If this is merely a segment of a larger file, then std::cin is likely reading leftover garbage from the input buffer. Try adding this in the body of getMinMax before requesting user input:
std::cin.ignore(MAX_INT);
std::cin.clear();
And not that this is relevant, but it's not necessary to manually close a file at the end of a function in C++. When std::fstream goes out of scope, its destructor will the close the file automagically. Furthermore, pass ints by value instead of by reference if your function doesn't intend to change them. From the style of your code, I'm guessing you're used to programming in C and are trying to make a switch; it helps to start writing idiomatic C++ code early
EDIT: Try rewriting the getMinMax method as:
#include <sstream>
void getMinMax(int& Min, int& Max)
{
using namespace std;
cin.ignore(MAX_INT);
cin.clear();
string temp;
cout << "Enter min: "
getline(cin, temp);
stringstream(temp) >> Min;
cout << "Enter max: "
getline(cin, temp);
stringstream(temp) >> Max;
//printf("(Min, Max) = (%i, %i)\n", Min, Max); //For debugging
}
This is a verbose but somewhat safer version of what you posted. If this doesn't work, then I don't know what to tell you. If it does work, then my guess is that the input stream was polluted somehow.
I suggest the following:
Fix the missing include: i.e. add include <stdlib.h> to your file.
Open a terminal and navigate to the directory where your randomNrs.cpp file (or whatever you named it) lives.
Compile it: You said you are using g++, so you just run g++ randomNrs.cpp -o randomNrs in that directory - the -o flag will let you name your binary something else than the default a.out. In this example it would be named randomNrs.
Run it: Then run your executable from within that directory by typing ./randomNrs
These where the steps I went through in order to run your program. I'm on RHEL but it should be the same on OS X I think.
this is my first SO post.
I am very new to programming, and with C++ I thought I might try and make a program that allows the user to submits a block of text (max 500 characters), allows them to enter a 4 letter word and the program return with the amount of times it picks that word up in the text.
I am using X-code and it keeps making a green breakpoint and pausing the program at the 'for' loop function. my code is shown below:
#include <iostream>
#include <string>
#include <math.h>
#define SPACE ' '(char)
using namespace std;
//Submit text (maximum 500 characters) and store in variable
string text;
string textQuery(string msgText) {
do {
cout << msgText << endl;
getline(cin, text); } while (text.size() > 500);
return text;
}
//Query word to search for and store as variable
string word;
string wordQuery(string msgWord) {
cout << msgWord << endl;
cin >> word;
return word;
}
//Using loop, run through the text to identify the word
int counter = 0;
bool debugCheck = false;
int searchWord() {
for (int i = 0; i < text.size(); i++) {
char ch_1 = text.at(i);
char ch_2 = text.at(i + 1);
char ch_3 = text.at(i + 2);
char ch_4 = text.at(i + 3);
cout << i;
if(ch_1 == word.at(0) &&
ch_2 == word.at(1) &&
ch_3 == word.at(2) &&
ch_4 == word.at(3) )
{
counter++;
debugCheck = true;
}
}
return counter;
}
//cout the result
int main() {
string textUserSubmit = textQuery("Please submit text (max 500 characters): ");
string wordUserSubmit = wordQuery("Please select a word to search for: ");
int counterResponse = searchWord();
cout << debugCheck << endl;
cout << "The number of times is: " << counterResponse << endl;
return 0;
}
I get the error at the for loop. Any other advice about how i can make my program work for different words, multiple lengths of words and also how i can highlight the words in text would be helpful.
I really would appreciate if someone could aid me with my problem. Thanks!
I get the error at the for loop.
You should describe the error you get. I happen to have access to Xcode so I can run your code and see what happens, but you should try to spare that of people from whom you want help.
In this case you should describe how the debugger stops the program at the line:
char ch_4 = text.at(i + 3);
includes the message: "Thread 1: signal SIGABRT" and the console output shows
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string
Your problem is this: the for loop checks to make sure that i is in the correct range for the string text before using it as an index, but then you also use i+1, i+2, and i+3 as indices without checking that those values are also valid.
Fix that check and the program appears to run fine (given correct input).
Some miscellaneous comments.
Use more consistent indentation. It makes the program easier to read and follow. Here's how I would indent it (using the tool clang-format).
#define SPACE ' '(char) looks like a bad idea, even if you're not using it.
using namespace std; is usually frowned on, though as long as you don't put it in headers it usually won't cause too much trouble. I still could though, and because you probably won't understand the resulting error message you may want to avoid it anyway. If you really don't like writing std:: everywhere then use more limited applications such as using std::string; and using std::cout;.
global variables should be avoided, and you can do so here by simply passing textUserSubmit and wordUserSubmit to searchWord().
there's really no need to make sure text is less than or equal to 500 characters in length. You're using std::string, so it can hold much longer input.
You never check how long word is even though your code requires it to be at least 4 characters long. Fortunately you're using at() to index into it so you don't get undefined behavior, but you should still check. I'd remove the check in textQuery and add one to wordQuery.
Not as in "can't find the answer on stackoverflow", but as in "can't see what I'm doing wrong", big difference!
Anywho, the code is attached below. What it does is fairly basic, it takes in a user created text file, and spits out one that has been encrypted. In this case, the user tells it how many junk characters to put between each real character. (IE: if I wanted to encrypt the word "Hello" with 1 junk character, it would look like "9H(eal~l.o")
My problem is that for some reason, it isn't reading the input file correctly. I'm using the same setup to read in the file as I had done previously on decrypting, yet this time it's reading garbage characters, and when I tell it to output to file, it prints it on the screen instead, and it seems like nothing is being put in the output file (though it is being created, so that means I've done something correctly, point for me!
code:
string start;
char choice;
char letter;
int x;
int y;
int z;
char c;
string filename;
while(start == "enc")
{
x = 1;
y = 1;
cout << "How many garbage characters would you like between each correct character?: " ;
cin >> z;
cout << endl << "Please insert the name of the document you wish to encrypt, make sure you enter the name, and the file type (ie: filename.txt): " ;
cin >> filename;
ifstream infile(filename.c_str());
ofstream outfile("encrypted.txt", ios::out);
while(!infile.eof())
{
infile.get(letter);
while ((x - y) != z)
{
outfile << putchar(33 + rand() % 94);
x++;
}
while((x - y) == z)
{
outfile << letter;
y = 1;
x = 1;
}
}
outfile.close();
cout << endl << "Encryption complete...please return to directory of program, a new file named encrypted.txt will be there." << endl;
infile.close();
cout << "Do you wish to try again? Please press y then enter if yes (case sensitive).";
cin >> choice;
What I pasted above the start of the while loop are the declaration variables, this is part of a much larger code that not only will encrypt, but decrypt as well, I left the decryption part out as it works perfectly, it's this part I'm having an issue with.
Thanks in advance for the assist!
EDIT:: I'm using visual C++ express 2008, and it shoots back that there are no errors at all, nor any warnings.
IMPORTANT EDIT
It turns out it is outputting to the file! However, it is outputting numbers instead of ascii characters, and it is also outputting the garbage character for the letter it should be. When it goes back to the "infile.get(letter)", it doesn't get a new character. So right now it seems to be the issues are 2 fold:
1) Printing numbers instead of ascii characters.
2) Using garbage instead of the actual character it should be getting.
Question Answered
Found out the second part in the "Important Edit" ...it turns out if you name something test.txt...that means it is actually called test.txt.txt when you type it into a C++ program. Just goes to show it's the tiny, minute, simple details that cause any program to go pooey.
Thank you to George Shore. Your comment about the input file being in the wrong place is what gave me the idea to try the actual items name.
Thank you to everyone who helped with the answer!
Further to the previous answers, I believe it's because the file you wish to encrypt is not being found by the original code. Is it safe to assume that you're running the code from the IDE? If so, then the file that is to be encrypted has to be in the same directory as the source.
Also:
outfile << putchar(33 + rand() % 94);
seems to be the source of your garbage to the screen; the 'putchar' function echoes to the screen whilst returning the integer value of that character. What is then going to happen is that number will be output to the file, as opposed to the character.
Changing that block to something like:
while ((x - y) != z)
{
c = (33 + rand() % 94);
outfile << c;
x++;
}
should enable the code to run as you want it to.
Rather than doing this:
while (!infile.eof())
{
infile.get(letter);
if (infile.good())
{
Do this:
while (infile.get(letter))
{
This is the standard pattern for reading a file.
It gets a character and the resulting infile (that is returned by get) is then checked to see if it is still good by converting it to bool.
The line:
outfile << putchar(33 + rand() % 94);
Should probably be:
outfile << static_cast<char>(33 + rant() % 94);
putchar() prints to the standard output. But the return value (same as the input) goes to the outfile. To stop this just convert the value to char and send to outfile.
Is the use of 'y' necessary? It seems confusing and unnecessary to me. If I were implementing this, then I'd expect to use just 'x' and 'z'.
I'm also not sure about the 'while (!infile.eof())' condition; Pascal determines EOF ahead of time, but C++ can only tell you about EOF after attempting to read a character. However, this would only affect the end of the file, not the main body of the loop.
while (!infile.eof())
{
infile.get(letter);
if (infile.good())
{
for (int i = 0; i < z; i++)
outfile << putchar(33 + rand() % 94);
outfile << letter;
}
}
(Uncompiled code!).
Also, do not use this for security - it may help a little, but it certainly won't conceal the information from the determined.