I'm taking a users input like so:
algo_type "pattern" filename
ex.
bf "inging" input_file.txt
As of now I separate the users input into three different variables, one for the algo_type, one for the pattern I'm looking for, and one for the filename. Once I get the pattern and filename I'm trying to take the pattern into the Bruteforce algo and search each line and print the position that pattern occurs in the line of the .txt file. Right now though every time I enter the input into the algo it returns -1 meaning the BruteForce isn't running? What exactly am I doing wrong here?
int BruteForce(const string& line, const string& pattern){
int n , m;
n = line.length();
m = pattern.length();
for(int i = 0 ; i < n - m ; i++){
int j = 0;
while( j < m && line[i + j] == pattern[j]){
j = j+1;
if( j == m){
return i;
}
}
}
return -1;
}
int main(){
string text, algo_type , pattern , fname, line;
getline(cin ,text);
istringstream iss(text);
if(iss >> algo_type >> pattern >> fname){
cout << algo_type << pattern << fname << "'\n'";
}
int i = 0;
ifstream ifs;
ifs.open(fname.c_str());
while(getline(ifs, line) && fname != ""){
if( algo_type == "bf"){
cout << "Line " << i++ << ":" << BruteForce(line,pattern) << endl;
}
}
return 0;
}
I suppose you wanted return -1 at the end of BruteForce, rather then at the end of the first iteration.
Also, the first loop condition needs to have <= instead of <, or matches ending in the very position won't be found.
Here's a complete, fixed version: EDIT as per the edit, list multiple matches within lines:
#include <string>
using namespace std;
int BruteForce(const string& line, size_t start, const string& pattern) {
const size_t n = line.length();
const size_t m = pattern.length();
if (n<m) return -1;
for(size_t i = start; i <= (n - m); i++) {
for(size_t j=0; j < m && (line[i + j] == pattern[j]); ++j) {
if(j == m-1) {
return i;
}
}
}
return -1;
}
#include <iostream>
#include <fstream>
#include <sstream>
int main() {
string text, algo_type, pattern, fname, line;
getline(cin ,text);
istringstream iss(text);
if(iss >> algo_type >> pattern >> fname) {
cout << " " << algo_type << " " << pattern << " " <<fname << "\n";
}
int i = 1;
ifstream ifs;
ifs.open(fname.c_str());
while(getline(ifs, line) && fname != "") {
if(algo_type == "bf") {
int pos = -1;
while (-1 != (pos = BruteForce(line, pos+1, pattern)))
cout << "Line " << i << ":" << pos << " " << line << endl;
}
i++;
}
return 0;
}
See it Live on Coliru: http://coliru.stacked-crooked.com/a/f1a7693d7d3bd7c5
I've tested it with
./test <<< "bf iss /etc/dictionaries-common/words" | grep Miss
Which printed
Line 10241:1 Miss
Line 10242:1 Mississauga
Line 10242:4 Mississauga
Line 10243:1 Mississippi
Line 10243:4 Mississippi
Line 10244:1 Mississippi's
Line 10244:4 Mississippi's
Line 10245:1 Mississippian
Line 10245:4 Mississippian
Line 10246:1 Mississippian's
Line 10246:4 Mississippian's
Line 10247:1 Mississippians
Line 10247:4 Mississippians
Line 10248:1 Missouri
Line 10249:1 Missouri's
Line 10250:1 Missourian
Line 10251:1 Missourian's
Line 10252:1 Missourians
Line 10253:1 Missy
Line 10254:1 Missy's
Related
I am processing a .txt file of format shown below:
Header 1:\n Header 2: \n 1 \n 2 \n 3 \n Header 1a: \n ...
And my code is as follows:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
ifstream infile(argv[1]);
string file_name = argv[1];
int after_underscore = 0;
string cut_name;
for (int i = 0; i < file_name.length(); i++) {
if (!ispunct(file_name[i])) {
cut_name += file_name[i];
}
else
break;
}
ofstream outfile(cut_name + std::string("_processed.txt"));
cout << "Processing " << argv[1] << "..." << endl;
string line;
int header_no = 7; // change this if the number of headers in the txt file changed
size_t points_no = 0; // this is the number of recorded points for each entry
size_t no_of_events = 0;
// define the needed header
string header1 = "Record Length";
string header2 = "Event Number";
size_t foundHeader1, foundHeader2 = 0;
while (!infile.eof()) {
// to process the header
for (unsigned int i = 0; i < header_no; i++) {
getline(infile, line);
foundHeader1 = line.find(header1);
foundHeader2 = line.find(header2);
int found_colon = line.find(":");
// looking for the "Record Length " header and find the number of points recorded
// Also look for "Event Number" header and count how many events are recorded
if (foundHeader1 != string::npos) {
line = line.substr(found_colon + 1);
points_no = stoi(line);
continue;
}
else if (foundHeader2 != string::npos) {
no_of_events += 1;
continue;
}
else
continue;
}
}
infile.close();
infile.clear();
// to process the numbers
outfile << "Number of points per entry: " << points_no << endl;
outfile << "Number of events recorded: " << no_of_events << endl;
outfile << endl;
infile.open(argv[1]);
while (infile) {
cout << "Hello" << endl;
for (unsigned int i = 0; i < header_no; i++) {
getline(infile, line);
}
for (unsigned int i = 0; i < points_no; i++) {
getline(infile, line);
outfile << line << " ";
}
outfile << endl;
}
outfile.close();
cout << "Done processing! " << cut_name << "_processed.txt is produced" << endl;
}
The code gives me the correct output, but I noticed that there are some white spaces added in the output file towards the end of my output.
I wanted my entries to end after "730 \n" but oddly some white spaces are added after then and an extra \n is there too. These white spaces are unwanted and gave me issues when I want to further process the output file. I could not figure out why they are present there. Can anyone help me to check what went wrong or give me some advise? Thanks you.
Basically, the issue I am having is in the title, I am trying to create a multi-threaded application to read and sum up the contents of a file, this works correctly with one thread. However, when more are introduced they come out with the same output. How do I fix this?
The code
void *sumThread(void *);
pthread_mutex_t keepOut = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t keepOutSum = PTHREAD_MUTEX_INITIALIZER;
int counter = 0, line_count = 0;
char* loc;
double total = 0;
void split(const string& s, char c, vector<string>& v)
{
string::size_type i = 0;
string::size_type j = s.find(c);
while (j != string::npos)
{
v.push_back(s.substr(i, j - i));
i = ++j;
j = s.find(c, j);
if (j == string::npos)
v.push_back(s.substr(i, s.length()));
}
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
cerr << "Usage: " << argv[0] << " filename" << endl;
return 1;
}
string line;
loc = argv[1];
ifstream myfile(argv[1]);
myfile.unsetf(ios_base::skipws);
line_count = std::count(std::istream_iterator<char>(myfile),
std::istream_iterator<char>(),
'\n');
myfile.clear();
myfile.seekg(-1, ios::end);
char lastChar;
myfile.get(lastChar);
if (lastChar != '\r' && lastChar != '\n')
line_count++;
myfile.setf(ios_base::skipws);
myfile.clear();
myfile.seekg(0, ios::beg);
pthread_t thread_id[NTHREADS];
for (int i = 0; i < NTHREADS; ++i)
{
pthread_create(&thread_id[i], NULL, sumThread, NULL);
}
for (int i = 0; i < NTHREADS; ++i)
{
pthread_join(thread_id[i], NULL);
}
cout << setprecision(2) << fixed << total << endl;
return 0;
}
void *sumThread(void *)
{
pthread_mutex_lock(&keepOut);
int threadNo = counter;
counter++;
pthread_mutex_unlock(&keepOut);
ifstream myfile(loc);
double runningTotal = 0;
string line;
if (myfile.is_open())
{
for (int i = threadNo; i < line_count; i += NTHREADS)
{
vector < string > parts;
getline(myfile, line);
// ... and process out the 4th element in the CSV.
split(line, ',', parts);
if (parts.size() != 3)
{
cerr << "Unable to process line " << i
<< ", line is malformed. " << parts.size()
<< " parts found." << endl;
continue;
}
// Add this value to the account running total.
runningTotal += atof(parts[2].c_str());
}
myfile.close();
}
else
{
cerr << "Unable to open file";
}
pthread_mutex_lock(&keepOutSum);
cout << threadNo << ": " << runningTotal << endl;
total += runningTotal;
pthread_mutex_unlock(&keepOutSum);
pthread_exit (NULL);
}
Sample output
2: -46772.4
0: -46772.4
1: -46772.4
3: -46772.4
-187089.72
Each thread is supposed to read and sum up the numbers in the file, then add them together when it's done. However, the threads all seem to return the same number even though the threadNo variable a clearly different as indicated in the output.
Your problem is here:
for (int i = threadNo; i < line_count; i += NTHREADS) {
vector<string> parts;
getline(myfile, line);
getline() doesn't know the value of i, so it is still reading adjacent lines from the file, without skipping any lines. Hence all threads are reading the same first few lines of the file.
int line = 0;
string teststring = " ";
string stringarray[100];
while (codeFile.good())
{
getline(codeFile, teststring, ' ');
if(teststring!="" && teststring[0]!='\n' && teststring[0] != 9 && teststring[0] != 10 && teststring[0] != 32 && teststring[0]!=' '
&& teststring!=" " && teststring!=" ")
{
stringarray[line]=teststring; // still stores whitespace :(
cout << stringarray[line] << endl;
line++;
}
}
Hello, I am going through a text file and trying to store each string inside an element of an array but, am having problems with elements storing completely white space.
I have just solve a similar problem, how about this code:
while (codeFile.good())
{
getline(codeFile, teststring);
for(size_t idx = 0; idx < teststring.size(); i++) {
size_t start = idx;
while (teststring[i] != ' ') {
idx++;
}
stringarray[line] = teststring.substr(start, idx - start);
cout << stringarray[line] << endl;
line++;
}
}
Ignoring all the white spaces is exactly what operator>> does.
Your snippet can be rewritten as:
// ...
std::string word;
std::vector<std::string> words;
while ( codeFile >> word )
{
if ( word.empty() ) continue;
std::cout << word << '\n';
words.push_back(std::move(word));
}
I've been working on this program for a very long time now and I think I'm close to being done. However, my code is outputting something strange and I cannot find the issue.
Expected output:
This is a happy tESt to check if my reader works!
An happy alligator was AT tHe happy park and a happy a cow blew its nose in a happy scarf. are you an happy Octagon THe
Actual output:
This is a tE happySt to check if my reader works!
a happy
THe Happy
How can I make the following code behave as I expect?
#include <iostream>
#include <string>
#include <cctype>
#include <fstream>
#include <sstream>
#include <locale>
using namespace std;
void
usage(char *progname, string msg){
cerr << "Error: " << msg << endl;
cerr << "Usage is: " << progname << " [filename]" << endl;
cerr << " specifying filename reads from that file; no filename reads standard input" << endl;
}
string capitalization(string word,string adj){
for(int i = 0; i <= word.length(); i++){
if(isupper(word[i])){
for(int j = 0; j <= adj.length(); j++){
adj[j] = toupper(adj[j]);
return adj;
}
}
else if(isupper(word[0])){
for(int j = 0; j <= adj.length(); j++){
adj[j] = tolower(adj[j]);
return adj;
}
}
else{
for(int j = 0; j <= adj.length(); j++){
adj[j] = tolower(adj[j]);
return adj;
}
}
}
}
int main(int argc, char *argv[]){
string adj;
string file;
cin >> adj;
cin >> file;
string line;
string articles[14] = {"a","A","an","aN","An","AN","the","The","tHe","thE","THe","tHE","ThE","THE"};
ifstream rfile;
rfile.open(file.c_str());
if(rfile.fail()){
cerr << "Error while attempting to open the file." << endl;
return 0;
}
string::size_type pos;
string word;
string words[1024];
while(getline(rfile,line)){
istringstream iss(line);
for(int i = 0; i <= line.length(); i++){
iss >> word;
words[i] = word;
for(int j = 0; j <= 14; j++){
if(word == articles[j]){
string article = word;
iss >> word;
pos = line.find(article);
//cout << pos << endl;
string adjec = capitalization(word,adj);
int position = (pos + word.length());
line.insert(position, " " + adjec);
continue;
}
}
}
cout << line << "\n";
}
}
This may not fix any of your problems, but...
The logic in these lines is wrong.
istringstream iss(line);
for(int i = 0; i <= line.length(); i++){
iss >> word;
Let's say your line is
This is a test.
For this line, line.length() is 15 but there aren't 15 words. What you need is
istringstream iss(line);
while ( iss >> word ) {
I open a txt file using argc, argv, and getline. I did that properly, but now I have to get the number of words per line (the number of lines is not known before) and I must output them in reverse. Meaning from the bottom line to the top line. Any help is appreciated. This code outputs the number of words in the file:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main(int argc, char *argv[])
{
if(argc < 1){
cerr << "Usage: " << argv[0] << "filename.txt" << endl;
}
ifstream ifile(argv[1]);
if(ifile.fail()){
cerr << "Could not open file." << endl;
return 1;
}
int n;
ifile >> n;
cout << n;
int numberOfWords = 0;
string line;
for(int i = 0; i <= n; i++){
getline(ifile, line);
cout << line << endl;
}
size_t i;
if (isalpha(line[0])) {
numberOfWords++;
}
for (i = 1; i < line.length(); i++) {
if ((isalpha(line[i])) && (!isalpha(line[i-1]))) {
numberOfWords++;
}
}
cout<<"The number of words in the line is : "<<numberOfWords<<endl;
return 0;
}
To find the number of words per line you would use std::getline() to iterate over each line and use std::stringstream to extract each chunk of whitespace-separated input. Then you would iterate over each chunk of input and check to see if each character is alphabetic:
int numberOfWords = 0;
for (std::string line, word; std::getline(ifile, line); )
{
std::istringstream iss(line);
while (iss >> word)
{
bool alpha = true;
for (char c : word)
if (!std::isalpha(c)) alpha = false;
if (alpha) ++numberOfWords;
}
std::cout << "Number of words on this line: " << numberOfWords << std::endl;
numberOfWords = 0;
}