File reading and Manipulation - c++

I have a text file:
1
2
3
stop
4
The code has to add each number to the previous number to get a new value and it needs to stop when it reads the "stop" in the file.
For example output would be:
1
3
5
Reading has stopped
How can I break the code for my output to be like this?
The "reading has stopped", only has to appear when there is a 'stop' in the file. otherwise the output should just be numbers.

You can read each piece of the file into a string and end if the input is "stop". If the input isn't "stop" you can convert it to an int using std::stoi
#include <string>
#include <iostream>
#include <fstream>
int main() {
std::string numberString;
std::ifstream file{ "filename.txt" };
int previousNumber = 0;
while (file >> numberString)
{
if(numberString == "stop")
{
break;
}
try {
int number = std::stoi(numberString);
std::cout << (number + previousNumber) << " ";
previousNumber = number;
} catch(...) {
std::cout << "invalid number" << std::endl;
}
}
file.close();
std::cout << "Reading has stopped" << std::endl;
}

If your text file has only one string "stop", then there's a very easy solution: you just keep reading integers until the reading fails
int main() {
ifstream ifs("test.txt");
int first = 0;
int second;
while (ifs >> second) {
cout << first + second << ' ';
first = second;
}
cout << "Reading has stopped" << endl;
return 0;
}
The problem with this solution is that if you have other strings in the text file and you want to handle them in a different way, this solution will fail.
Hope it helps.

Related

C++ Searching CSV file from inputted string

I am trying to create a program that will load the CSV file and based upon the inputted word search through the file and return any lines that contain the word. The CSV file is a mass download of tweets and has the following columns:
Date & Time Created
The Tweet
The tweets are also surrounded by b'TWEET TEXT HERE' so would need to remove the b' ' from when it printed out. I am unable to change anything to do with the CSV file sadly so cant manually remove it. The issues I am having are:
Listing the total amount of tweets within the file the program just freezes
Removing the b' ' from the tweets
The else statement causes "not found" to be constantly printed
Code I currently have that is returning the tweets that contain the inputted word but also the false positive.
The current output when running the below code
#include "stdafx.h"
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string token;
ifstream fin;
fin.open("sampleTweets.csv");
if (fin.is_open())
{
cout << "File opened successfully" << "\n";
}
else {
cout << "Error opening file" << "\n";
}
cout << "Enter search word: ";
cin >> token;
"\n";
string line;
while (getline(fin, line)) {
if (line.find(token) != string::npos) {
cout << line << endl;
} else {
cout << token << " not found" << endl;
}
}
fin.close();
char anykey;
cout << "press any key";
cin >> anykey;
return 0;
}
Code I was using for counting total tweets
int count = 0;
char str[140];
while (!fin.eof())
{
fin.getline(str, 140);
count++;
}
cout << "Number of lines in file are " << count;
Any help on this would be amazing as I am quite new to C++ and not sure where to go from here!
You can remove the "b" with erase:
if (line.find(token) != string::npos){
int n= line.find(",");
line.erase(n+1, 3);
cout << line << endl;
}
and you can count the lines inside the while loop:
int count = 0;
while (getline(fin, line)) {
++count;
...
}
EDIT: you can remove the extra quotes and commas like so:
line[n] = ' '; // change comma int space
line.erase(n+1, 4); // remove "b""
line.resize(line.size()-5); // remove trailing """,,

Issue printing .txt file in program C++

I have a program that takes a text file and list the words and how many times they are used. It works but I can't figure out how to print out the text file. Above the sorted words and how many times they appear, I want to display the text from the file. How would I do that? I tried several things but it either does nothing or screws up the rest of the code saying there are 0 unique words. And lastly how would print out the results so they are more ... table -ish...
/*
Something like this:
Word: [equal spaces] Count:
ask [equal spaces] 5
anger [equal spaces] 3
*/
Thank you for any assistance you can provide me.
#include <iterator>
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <cctype>
using namespace std;
string getNextToken(istream &in) {
char c;
string ans="";
c=in.get();
while(!isalpha(c) && !in.eof())//cleaning non letter charachters
{
c=in.get();
}
while(isalpha(c))
{
ans.push_back(tolower(c));
c=in.get();
}
return ans;
}
string ask(string msg) {
string ans;
cout << msg;
getline(cin, ans);
return ans;
}
int main() {
map<string,int> words;
ifstream fin( ask("Enter file name: ").c_str() ); //open an input stream
if( fin.fail() ) {
cerr << "An error occurred trying to open a stream to the file!\n";
return 1;
}
string s;
string empty ="";
while((s=getNextToken(fin))!=empty )
++words[s];
while(fin.good())
cout << (char)fin.get(); // I am not sure where to put this. Or if it is correct
cout << "" << endl;
cout << "There are " << words.size() << " unique words in the above text." << endl;
cout << "----------------------------------------------------------------" << endl;
cout << " " << endl;
for(map<string,int>::iterator iter = words.begin(); iter!=words.end(); ++iter)
cout<<iter->first<<' '<<iter->second<<endl;
return 0;
}
I would just use a simple for loop like this:
for (int x = 0; x < words.size(); x++){
cout >> words[x] << endl
}
And then modify from there to get your desired format.
I did notice though, that you are not returning a value for main in all paths of the above code, which should give a compile time error, but did not when I compiled it, for some reason. I would remind you that you need to have a return value for main. Unless I am misunderstanding your question. I could not run this program without creating a sample file, and so could not test it without extra work. But the program did compile. I did not expect to, because of the missing return statement. If you can make this reproduce your error without me having to create a sample file of words, ei insert the list of words into the code and minimally reproduce the error, I would be able to help you better. As it is, I hope that I helped you.
Something like this should make it:
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <string>
int main( int argc, char* argv[] )
{
std::string file;
std::cout << "Enter file name: ";
std::cin >> file;
std::fstream in( file.c_str() );
if ( in.good() )
{
std::unordered_map<std::string, int> words;
std::string word;
//Use this to separate your words it could be '\n' or anything else
char cSeparator = ' ';
while ( in >> word )
{
//Print the word
std::cout << word << cSeparator;
++words[word];
}
std::cout << std::endl;
//Headers Word and Count separated by 2 tabs
std::cout << "Word:\t\tCount:" << std::endl;
for ( auto& w : words )
std::cout << w.first << "\t\t" << w.second << std::endl;
}
in.close();
return EXIT_SUCCESS;
}
However this is assuming that the text file only contains the words, if you have other kind of stuff there, you should be able to filter it as you want.

Input elements differ from output elements from files C++

I have been having some problems with my code. I was asked to input elements from an .dat file into an array. For class we have to do this for various files without knowing how many elements will be in each file. The only thing we know is that here will never be more then 5000 elements per file.
One of my input file has the following elements:
5.675207 -0.571210
0.728926 0.666069
2.290909 0.751731 2.004545 0.907396
0.702893 0.646427 5.909504 -0.365045
2.082645 0.871841 5.597107 -0.633507
6.117769 -0.164663 6.091736 -0.190282
5.571074 -0.653433 4.503719 -0.978307
3.983058 -0.745620
3.670661 -0.504729
5.857438 -0.413001
When I run my code:
#define _CRT_NONSTDC_NO_DEPRECATE
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main(int argc, char * argv[])
{
ifstream fin;
ofstream fout;
if (argc < 3)
{
cout << "Incorrect usage: prog.exe filenname number" << endl;
cout << "Exiting now, please try again." << endl;
return -1;
}
fin.open(argv[1]);
if (!fin)
{
cout << "Error opening file \"" << argv[1] << "\", exiting." << endl;
return -1;
}
fout.open(argv[2]);
int count = 0;
int word;
double points[5000];
while (fin >> word)
{
fin >> points[count];
++count;
}
fout << "Numer of points is: " << count/2 << endl;
for (int i = 0; i < count; i++)
{
fout << points[i] << " ";
}
fin.close();
fout.close();
return 0;
}
I outputted the elements just to make sure that they were properly inputted. I get the following and I don't know why.
0.675207 0.57121
0.728926 0.666069
0.290909 0.751731 0.004545 0.907396
0.702893 0.646427 0.909504 0.365045
0.082645 0.871841 0.597107 0.633507
0.117769 0.164663 0.091736 0.190282
0.571074 0.653433 0.503719 0.978307
0.983058 0.74562
0.670661 0.504729
0.857438 0.413001
The first digit is converted to a 0 for some reason and the negative ones become positive. Would anyone know why this is occurring?
int word;
is doing you no favours. First it's an integer so fin >> word only reads the integer portion of the inputs. 5.675207 is read as 5. the .675207 is left in the file stream for fin >> points[count]. Words isn't stored anywhere to the 5 is discarded but the .675207 lives on as 0.675207 in points[0].
Where the negative signs are going I didn't bother trying to figure out because
while (fin >> points[count])
{
++count;
}
fixes everything.
When you read in the numbers from the the file you are extracting them as "word" and then storing them as "points". "word" is an integer and "points" is a double, this will give you unexpected behavior. The compiler should give you warnings about this.

Find in C++ if a line from file contains a specific character

I've read the lines from a textfile and i want to check if that line contains the $ sign.
That's what i got so far:
int main() {
ifstream data_store;
string line;
data_store.open("c:\\test.txt");
while (!data_store.eof())
{
getline(data_store, line);
if (line.find("$"))
cout << "1: " << line << endl;
}
data_store.close();
system("PAUSE");
return 0;
}
Furthermore how can i output them to a file ?
To check if a line contains something using std::string::find to need to check the returned value from find to make sure it is a valid return. To do that we compare it against std::string::npos as that is what find() will return if it does not find anything. This is the reason it finds every line as std::string::npos is still considered true when evaluated as a bool. So refactoring your code you would have:
while (getline(data_store, line))
{
if (line.find("$") != std::string::npos)
cout << "1: " << line << endl;
}
I also changed the while loop as using eof is not how to control a while loop. for more information on that see Why is “while ( !feof (file) )” always wrong?
As far as outputting the string to a file see: How to write std::string to file?
It's a minor thing, but a variant of #NathanOliver's solution, is to use a for loop:
ifstream data_store("c:\\test.txt");
for ( string line; getline(data_store, line); ) {
if ( line.find("$") != string::npos )
cout << "1: " << line << endl;
}
// ...
The benefit here is that line is now local only to the loop, which is what it should be since that is the only place it is used.
I did it yesterday forgot to update.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
bool contains_number(const string &c);
int main()
{
int count = 0;
{
string line1[100];
ifstream myfile("D:/Users/Jarvan/Desktop/test.txt");
int a = 0;
if (!myfile)
{
cout << "Error opening output file" << endl;
system("pause");
return -1;
}
while (!myfile.eof())
{
getline(myfile, line1[a], '\n');
if (contains_number(line1[a]))
{
count += 1;
cout << line1[a] << "\n";
}
else cout << "\n";
}
}
cout << count <<endl;
system("pause");
return 0;
}
bool contains_number(const string &c)
{
return (c.find_first_of("$") != string::npos);
}

Why is ifstream failing when reading mixed data?

I have a text file with words and integers. The task is to read only integers from it ignore words. This is an example of such file:
seven 7
I declare an int variable and try to read the ifstream into it (echoing the state of ifstream):
#include <iostream>
#include <fstream>
int main() {
int num = -1;
std::ifstream ifs("file.in");
std::cout << ifs << std::endl;
ifs >> num;
std::cout << ifs << std::endl;
if ( ifs.fail() )
ifs.clear();
std::cout << ifs << std::endl;
ifs >> num;
std::cout << ifs << std::endl;
std::cout << num << std::endl;
return 0;
}
To which I get an output:
1
0
1
0
-1
It's obvious that 'ifs' fails when trying to read a word into an int variable. My question is why does it fail the second time after being cleared?
The first failure doesn't advance the stream position, so the second tries again with exactly the same results. You'll need to skip over the unwanted word, either reading it into a string or using ignore.