Read File Line by line and output the first coloumn - c++

I am new to c++ and am trying to do a string search for 2 words(double and triple) in a file and print the line on which they are found. Some lines only have the word "double" and some only have the word "triple".
The code doesn't seem to output the words, it just prints the last line at the end of the loop.
I forgot to add that I need to print the first element of the line on which the word is found, I am able to locate the line where the word is found, however, it doesnt seem to print the first element on the file.
Here is my code.
int main(int argv, char *argc[]){
const string filen("test.txt");
ifstream inFile(filen.c_str());
string line = "";
char IDList[10];
string ID = "";
char* double_word = "double"; // test variable to search in file
char* triple_word = "triple";
stringstream ss;
string word = "";
unsigned int currentLine = 0;
// iterate through each line and check if the words double or triple exist.
while(getline(inFile, line)){
currentLine++;
if (line.find(double_word) != string::npos) {
cout << "found the word \"double\" on line: " << currentLine << endl;
// this part takes the input file and reads the first character of the line i.e. the ID and adds it to the IDList
// string array.
while(inFile >> IDList){
cout << "File Id: " << IDList << endl;
inFile.ignore(numeric_limits<streamsize>::max(), ' ');
for(int i=0;i<10;i++){
ss << IDList[i] << endl;
}
word = ss.str();
}
}
else if(line.find(triple_word) != string::npos){
cout << "found the word \"triple\" on line: " << currentLine << endl;
// now take the id of this file and add it to a different queue.
while(inFile >> IDList){
cout << "File Id: " << IDList << endl;
inFile.ignore(numeric_limits<streamsize>::max(), ' ');
for(int i=0;i<10;i++){
ss << IDList[i] << endl;
}
word = ss.str();
}
}
else if(line.find(double_word) && line.find(triple_word) != string::npos){
cout << "Found both words double and triple in line: " << currentLine << endl;
while(inFile >> IDList){
cout << "File Id: " << IDList << endl;
inFile.ignore(numeric_limits<streamsize>::max(), ' ');
for(int i=0;i<10;i++){
ss << IDList[i] << endl;
}
word = ss.str();
}
}
else{
cout << "neither word found, moving to next line" << endl;
}
}
inFile.close();
cout << "Id's added to the queue" << word << endl;
return 0;
}

I think you can simplify your code and write something like this:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
using std::string;
using std::vector;
using std::cout;
using std::cin;
int main(int argc, char* argv[]) {
const string filen("test.txt");
std::ifstream inFile(filen.c_str());
string line;
string double_word = "double"; // test variable to search in file
string triple_word = "triple";
vector<string> IDs;
unsigned int currentLine = 0;
// iterate through each line and check if the words double or triple exist.
while(getline(inFile, line)){
currentLine++;
bool found_d_word = line.find(double_word) != string::npos;
bool found_t_word = line.find(triple_word) != string::npos;
if ( found_d_word && !found_t_word )
cout << "found the word \"double\" on line: " << currentLine << '\n';
if ( found_t_word && !found_d_word )
cout << "found the word \"triple\" on line: " << currentLine << '\n';
if ( found_d_word && found_t_word )
cout << "Found both words double and triple in line: " << currentLine << '\n';
if ( found_d_word || found_t_word ) {
std::istringstream ss{line};
string ID;
ss >> ID;
cout << "File Id: " << ID << '\n';
// my guess: store all the IDs in one vector
IDs.push_back(ID);
} else {
cout << "neither word found, moving to next line\n";
}
}
inFile.close();
return 0;
}
One of the problems with your code is that you first read a line of the input file (with getline), put that in a string and then, when the word "double" or "triple" is found in the string, you try to read the ID from the file while you should read it from the same string.

Try this,
#include "iostream"
#include "string"
#include "sstream"
#include "fstream"
using namespace std;
int main()
{
stringstream y; string x; int lc=0, id;
ifstream fin("file.txt");
while (getline(fin, x))
{
++lc;
y.str(x);
y >> id;
bool d=x.find("double")!=string::npos;
bool t=x.find("triple")!=string::npos;
if (d and t)
cout << "found words double and triple on line " << lc
<< ", id is " << id << endl;
else if (d)
cout << "found word double on line " << lc
<< ", id is " << id << endl;
else if (t)
cout << "found word triple on line " << lc
<< ", id is " << id << endl;
}
}

Related

Trying to run a count so I know when the last row of data is written so I can output a ']' instead of a ','

I want my output file to look like this:
However, no matter what I try, it looks like this:
I can't get my comma condition to work for the output. I've tried to use eof, counts, etc but I'm not really sure where to go.
I've tried looking at other posts, but I either can't find one linked, or I don't actually understand it.
#include <iostream>
#include <fstream> //ofstream declared in this header file
#include <string>
#include <sstream>
#include <vector>
using namespace std;
//Creates Structure For Columns
struct InputFile
{
string Date;
string Value;
string SignalStrength;
string Voltage;
};
int main()
{
ifstream input;
string Row;
string Column;
int count = 0;
int count2 = 0;
//Stores Data From Structure As Vector
vector<InputFile> InputDataStored;
input.open("Temperature.csv");
if (input.fail())
{
cerr << "File does not exist. Exiting" << endl; //cerr is cout for errors
return 1; //This could be used as an error code
}
if (!input)
{
cerr << "File could not be opened." << endl;
}
while (getline(input, Row)) //Remove top line output from sensor data when opened in Notepad
{
getline(input, Row); // read an entire row and store it in a string variable 'line'
stringstream ss{ Row }; // used for breaking words
vector<string> Columns; // creates a temporary vector of strings
while (getline(ss, Column, ',')) // read an entire row and store it in a string variable 'column'
{
Columns.push_back(Column); // add all the data of a row to the temporary vector
count++;
}
//InputFile t{}; // convert string to struct types
InputFile t;
if (Row.empty())
continue; // if it is a blank row, ignore it
else
t.Date = Columns[1];
t.Value = Columns[2];
t.SignalStrength = Columns[4];
t.Voltage = Columns[5];
InputDataStored.push_back(t); // add all the data of the new row to a vector
count2++;
cout << t.Date << " " << t.Value << " " << t.SignalStrength << " " << t.Voltage << endl;
}
input.close();
ofstream output;
output.open("SensorData.json");
if (!output)
{
cerr << "File could not be opened." << endl;
}
int JSONcount = 0;
output << "[";
for (InputFile t : InputDataStored)
{
JSONcount++;
output << "{" << endl;
output << "\"Date\": \"" << t.Date << "\"" << endl;
output << "\"Temperature\": " << t.Value << endl;
output << "\"Signal_strength\": " << t.SignalStrength << endl;
output << "\"Voltage\": " << t.Voltage << endl;
if (count2 >= JSONcount)
output << "}]" << endl;
else
output << "}," << endl;
}
output << JSONcount << endl;
output << count << endl;
output << count2;
output.close();
}
There are multiple mistakes in your code. Try something more like this instead:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
struct InputFile
{
string Date;
string Value;
string SignalStrength;
string Voltage;
};
int main()
{
vector<InputFile> InputDataStored;
string Line, Column;
int count = 0, count2 = 0;
ifstream input("Temperature.csv");
if (!input)
{
cerr << "Input file could not be opened. Exiting" << endl;
return 1;
}
getline(input, Line); //Remove top line output from sensor data when opened in Notepad
while (getline(input, Line)) // read an entire row and store it in a string variable 'line'
{
istringstream iss{ Line };
if (Line.empty())
continue;
vector<string> Columns;
while (getline(iss, Column, ','))
{
Columns.push_back(Column);
++count;
}
InputFile t;
t.Date = Columns[1];
t.Value = Columns[2];
t.SignalStrength = Columns[4];
t.Voltage = Columns[5];
InputDataStored.push_back(t);
++count2;
cout << t.Date << " " << t.Value << " " << t.SignalStrength << " " << t.Voltage << endl;
}
input.close();
ofstream output("SensorData.json");
if (!output)
{
cerr << "Output file could not be opened. Exiting" << endl;
return 1;
}
int JSONcount = 0;
output << "[";
for (const auto &t : InputDataStored)
{
++JSONcount;
if (JSONcount > 1)
output << "," << endl;
output << "{" << endl;
output << "\"Date\": \"" << t.Date << "\"" << endl;
output << "\"Temperature\": " << t.Value << endl;
output << "\"Signal_strength\": " << t.SignalStrength << endl;
output << "\"Voltage\": " << t.Voltage << endl;
output << "}";
}
output << "]" << endl;
output << JSONcount << endl;
output << count << endl;
output << count2;
output.close();
return 0;
}

Reading in one word from a file

I'm new to C++, and I need to find the one word inputted (searchWord) within the text file "input.txt".
I have it now where it will output every word in the file, but I need it to just output the inputted string and find it.
#include<iomanip>
#include<fstream>
#include<string>
using namespace std;
int main(){
// Variable Declaration
string fileName;
string searchWord;
int exitValue = 0;
// Name the file to open
ifstream inputFile;
// Prompt the user to enter the file name
cout << "Enter the name of the file: ";
cin >> fileName;
// Logic to determine if the file name equals "input.txt"
if (fileName == "input.txt"){ // if user input = input.txt
inputFile.open("input.txt"); // opening input.txt
}
else{
cout << "\nCould not open '" << fileName << "'." << endl;
exit(0);
}
// Prompt the user for a word to search for in the file
cout << "Enter a value to search for: ";
cin >> searchWord;
// Logic to determine if the inputted string is in the file or not
while (inputFile >> searchWord){
cout << "\n'" << searchWord << "' was found in '"
<< fileName << "'." << endl;
}
inputFile.close();
return 0;
}
Do it just a bit different:
// Logic to determine if the inputted string is in the file or not
string inputWord;
while (inputFile >> inputWord){ // Do not overwrite the given searchWord
if(inputWord == searchWord ) { // Check if the input read equals searchWord
cout << "\n'" << searchWord << "' was found in '"
<< fileName << "'." << endl;
break; // End the loop
}
}
This worked for me:
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
// Returns the index of the value you are looking for.
// If the value isn't found, it returns -1.
int searchFile(string filename, string value) {
FILE *fp;
int c, i = 0;
string contents = "";
fp = fopen(filename.c_str(), "r");
while (true) {
c = fgetc(fp);
contents += c;
if (feof(fp)) {
break;
}
i++;
if (i >= value.length() && contents.substr(i - value.length(), i) == value) {
return i;
}
}
fclose(fp);
return -1; // value not found in file
}
int main() {
string fileName;
string value;
cout << "Enter file name: ";
cin >> fileName;
cout << endl << "Enter search value: ";
cin >> value;
int index = searchFile(fileName.c_str(), value.c_str());
if (index == -1) cout << "Not found";
else cout << "Found at index " << index << endl;
cin.get();
cin.get();
return 0;
}

How to iterate position of the words in a file using vectors c++

I have to read dictionary.txt and test.txt. Then, have to check each word in test.txt if it is equal then this word would be added in KnownWords container and the remaining will be in UnknownWords container. I have done so far everything. But, in function DisplayKnownWordStats() I also have to display the position of the words. I tried the following code but it is not giving me correct value of the positions.
Can someone please help me out to get the correct position of the KnownWords from test.txt.
void WordStats::ReadTxtFile()
{
std::ifstream ifile(Filename);
if (!ifile)
{
std::cerr << "Error Opening file " << Filename << std::endl;
exit(1);
}
for (std::string word; ifile >> word; )
{
transform(word.begin(), word.end(), word.begin(), ::tolower);
WordMap & Words = (Dictionary.count(word) ? KnownWords : UnknownWords);
Words[word].push_back(ifile.tellg());
}
std::cout << KnownWords.size() << " known words read." << std::endl;
std::cout << UnknownWords.size() << " unknown words read." << std::endl;
}
// Displays stats of words in KnownWords
void WordStats::DisplayKnownWordStats()
{
cout << " ";
cout << " Word Count Position(s)\n";
for (Paragraph = KnownWords.begin(); Paragraph != KnownWords.end(); ++Paragraph)
{
string word = (*Paragraph).first;
vector<int> vect = (*Paragraph).second;
int cnt = vect.size();
cout << setw(15) << word << setw(10) << cnt << " ";
for (int i = 0; i<cnt; i++)
cout << vect[i] << ' '; // something wrong with this code
cout << endl;
}
}
void WordStats::ReadTxtFile(){
int pos=-1;
string word;
std::ifstream ifile(Filename);
if(!ifile)
{
std::cerr << "Error Opening file " << Filename << std::endl;
exit(1);
}
for (std::string word; ifile >> word; )
{
transform (word.begin(), word.end(), word.begin(), ::tolower);
word.erase(std::remove_if(word.begin(), word.end(), [](char c)
{
return (c < 'a' || c > 'z') && c != '\'' ;
}), word.end());
if (word == "") continue;
pos++;
if (Dictionary.find(word) != Dictionary.end())
{
Paragraph = KnownWords.find(word); //adding word to the knownWords
if (Paragraph != KnownWords.end())
{
Paragraph->second.push_back(pos); //adding position of the word
}
else
{
KnownWords[word] = vector<int>(1, pos); //adding record which is new
}
}
else
{
Paragraph = UnknownWords.find(word); //adding word to the knownWords
if (Paragraph != UnknownWords.end())
{
Paragraph->second.push_back(pos); //adding position of the word
}
else
{
UnknownWords[word] = vector<int>(1, pos); //adding record which is new
}
}
}
cout << KnownWords.size() << " known words read." << endl;
cout << UnknownWords.size() << " unknown words read." << endl;
}
void WordStats::DisplayKnownWordsStats()
{
vector<int>::iterator v;
cout << "\n";
cout << setw(22) << "Word" << setw(12) << "Count" << setw(20) << "Position(s)" << endl;
for (Paragraph = KnownWords.begin(); Paragraph != KnownWords.end(); Paragraph++)
{
string word = (*Paragraph).first;
vector<int> vect = (*Paragraph).second;
int count = vect.size();
cout << setw(22) << word << setw(9) << count ;
cout << " ";
for ( v = vect.begin(); v < vect.end(); v++)
{
cout << *v << " ";
}
cout << endl;
}
cout << "\n";
}
Words[word].push_back(ifile.tellg());
Above ifile.tellg() returns a position after a word. For example if a file contains the word "word", you read a first word from a file, then ifile.tellg() returns 4. It seems you expect the position 0 there. You should do like bellow:
Words[word].push_back(ifile.tellg() - word.size());

Reading letters and numbers from .txt file

I program which reads the letters and numbers from the input being used. But i dont know how to implement this to a .txt file. This is my code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
char ch;
int countLetters = 0, countDigits = 0;
cout << "Enter a line of text: ";
cin.get(ch);
while(ch != '\n'){
if(isalpha(ch))
countLetters++;
else if(isdigit(ch))
countDigits++;
ch = toupper(ch);
cout << ch;
//get next character
cin.get(ch);
}
cout << endl;
cout << "Letters = " << countLetters << " Digits = " << countDigits << endl;
return 0;
}
I made a mistake in my HW I was suppose to count the words instead of letters from the .txt file. Im having trouble counting words because I get confused with the space between words. How could I change this code to count the words instead of letters? I really appreciate the help.
This code counts each word separately. If the first character of a "word" is a number, it assumes the entire word is numeric.
#include <iterator>
#include <fstream>
#include <iostream>
int main() {
int countWords = 0, countDigits = 0;
ifstream file;
file.open ("your_text.txt");
string word;
while (file >> word) { // read the text file word-by-word
if (isdigit(word.at(0)) {
++countDigits;
}
else {
++countWords;
}
cout << word << " ";
}
cout << endl;
cout << "Letters = " << countLetters << " Digits = " << countDigits << endl;
return 0;
}
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char ch;
int countLetters = 0, countDigits = 0;
ifstream is("a.txt");
while (is.get(ch)){
if(isalpha(ch))
countLetters++;
else if(isdigit(ch))
countDigits++;
ch = toupper(ch);
cout << ch;
}
is.close();
cout << endl;
cout << "Letters = " << countLetters << " Digits = " << countDigits << endl;
return 0;
}

Vector of Structs of Vector and String Not printing correctly

I am a beginning c++ student and am attempting to write a program that takes a word in a file and indexes it, listing each word only once and displaying the line numbers of every time that word appears. I have tried using a map but i found it impossible to get the line numbers for the words. Instead, I am using a vector of structs that has an integer vector and a string for each word. I am trying to read each word, place it into a stringstream, then output it into the string in the struct. Then I take the line number and push_back it into the vector in the struct. then I save everything to the vector of the struct and try to print out each word associated with the line number vector. I am getting nowhere and would like some help. Itd be much appreciated! Here is my source code:
#include <iostream>
#include <string>
#include <fstream>
#include <map>
#include <sstream>
#include <vector>
using namespace std;
struct words {
vector<int> lineNumbers;
string word;
};
int main() {
ifstream inFile, testStream;
ofstream outFile;
string temp, choice, inFileName, outFileName, word, trash, word2, tempString;
int idx = 0, count = 0, idxTwo = 0;
bool outputOpened = false;
//map <string,int> wordList;
/map <string,int>::iterator wordIt;
stringstream myStream(ios_base::in| ios_base::out);
vector<words> myIndex;
words data;
for (;;) {
cout << "Options: "<< endl << "1. Index" << endl << "2. Quit" << endl
<< "Please enter an option: ";
getline(cin, temp);
//cin >> temp;
//cin.ignore(8192, '\n');
choice.resize(temp.length());
transform(temp.begin(), temp.end(), choice.begin(), ::toupper);
if (choice.compare("INDEX") == 0 || choice.compare("1") == 0) {
do {
inFileName.clear();
cout << "Index Program" << endl
<< "==============" << endl << endl;
cout << "Input file name: ";
getline(cin, inFileName);
inFile.open(inFileName.c_str());
if(inFile.fail()) {
cout << "Can't open file" << endl;
if(inFile.bad()) {
cout << "Bad" << endl;
}
inFile.clear();
}
}
while (!inFile.is_open());
do {
cout << "Output file name: ";
getline( cin, outFileName);
testStream.clear();
testStream.open(outFileName.c_str());
if(testStream.good()) {
cout << "That file already exists, try again" << endl;
testStream.clear();
testStream.close();
}
else {
testStream.clear();
testStream.close();
outFile.open(outFileName.c_str());
if (outFile.good()) {
outputOpened = true;
}
}
}
while (!outputOpened);
while (getline(inFile, trash)){
count++;
myStream << trash;
//myStream >> tempString;
while(myStream >> data.word) {
data.lineNumbers.push_back(count);
myIndex.push_back(data);
}
}
for (idx = 0; idx < myIndex.size(); idx++) {
outFile << "Word: "<< " "<< myIndex[idx].word << ", ";
for (idxTwo = 0; idxTwo < myIndex[idx].lineNumbers.size(); idxTwo++) {
outFile << "Found on lines " << " " << myIndex[idx].lineNumbers[idxTwo];
}
}
inFile.close();
outFile.close();
}
else if (choice.compare("QUIT") == 0 || choice.compare("2") == 0) {
return 0;
}
else {
cout << temp << " is an unrecognized option, please try again" << endl;
}
}
return 0;
}
Your problem seems to be that you are always appending each word to the vector<words>.
What you probably want, is a map<string, vector<int>>. Use .insert to insert words in to the set, if it already exists then just append the current line number to the value.
For this part of your program:
while (getline(inFile, trash)){
count++;
myStream << trash;
//myStream >> tempString;
while(myStream >> data.word) {
// 2.
// data.lineNumbers.clear();
data.lineNumbers.push_back(count);
myIndex.push_back(data);
}
// 1. add:
// myStream.clear();
}
You are using a global myStream. But the state of this myStream will be in a bad state after processing each line, as it ran out of data. The state mush be cleared for it to work again.
The data is also global, which make the line number for every word to be saved in data.lineNumber, not only the line number of the current word. You may want to clear it at each run.
Here are some issues:
Add myStream.clear(); after the while(myStream >> data.word) loop.
Add "\n" to the end of the following line to print on a new line:
outFile << "Found on lines " << " " << myIndex[idx].lineNumbers[idxTwo]<<"\n";
Also, the following nested loop will not give you correct results. It will grow with line numbers and keep printing "Found on lines":
for (idx = 0; idx < myIndex.size(); idx++) {
outFile << "Word: "<< " "<< myIndex[idx].word << ", ";
for (idxTwo = 0; idxTwo < myIndex[idx].lineNumbers.size(); idxTwo++) {
outFile << "Found on lines " << " " << myIndex[idx].lineNumbers[idxTwo]<<"\n";
}