Currently have this simple code written, trying to figure out why it's not counting specific words every time.
#include "pch.h"
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
int main()
{
int t = 0;
int a1 = 0;
string a[100];
ifstream food;
food.open("food.txt");
if (food.fail())
{
cout << "File can't open" << endl;
}
else
cout << "File successfully opened" << endl;
int i = 0;
while (!food.eof())
{
// Tomato
food >> a[i];
if (a[i] == "tomato")
{
t = t + 1;
}
i++;
// Apple
food >> a[i];
if (a[i] == "apple")
{
a1 = a1 + 1;
}
i++;
}
cout << "Amount of Tomatos: " << t << endl;
cout << "Amount of Apples: " << a1 << endl;
}
The text file I'm using:
apple
apple
tomato
apple
tomato
tomato
The output:
File successfully opened
Amount of Tomatoes: 2
Amount of Apples: 2
The purpose is to find the amount of each food found in the list. I'm currently only using two kinds of food but will have many more.
There are several problems with your code.
using eof() in a loop incorrectly. You can't check eof() before performing a read operation first.
using an array without bounds checking. For that matter, you don't need an array at all.
skipping words, which is why you are not counting everything you are expecting. Let's take the very first line, apple. Since it is not a "tomato", you skip it and read the next word in the file, which is "apple", so you count it. But you didn't count the 1st apple at all.
You need to do something more like this instead:
#include "pch.h"
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
int main()
{
int tomatoes = 0;
int apples = 0;
string s;
ifstream food;
food.open("food.txt");
if (!food.is_open())
{
cout << "File can't open" << endl;
return 0;
}
cout << "File successfully opened" << endl;
while (food >> s)
{
// Tomato
if (s == "tomato")
++tomatoes;
// Apple
else if (s == "apple")
++apples;
}
cout << "Amount of Tomatos: " << tomatoes << endl;
cout << "Amount of Apples: " << apples << endl;
return 0;
}
Alternatively, as #user463035818 mentioned in comments, you can use a std::map instead:
#include "pch.h"
#include <fstream>
#include <string>
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<string, int> foods;
string s;
ifstream food;
food.open("food.txt");
if (!food.is_open())
{
cout << "File can't open" << endl;
return 0;
}
cout << "File successfully opened" << endl;
while (food >> s) {
foods[s]++;
}
for (map<string, int>::iterator iter = foods.begin(); iter != foods.end(); ++iter) {
cout << "Amount of " << iter->first << ": " << iter->second << endl;
}
/* or, if you are using C++11 or later...
for (auto &item : foods) {
cout << "Amount of " << item.first << ": " << item.second << endl;
}
*/
return 0;
}
Related
I've been trying to delete an element from my vector using fstream for a while. I made a post before about this and I applied the advice from you guys but still I'm not getting my program to delete the element of my vector.
I can creat and re write my .txt file into another one but I can't make my code to delete the element. I think I've been having problems with ios::truc or ios::out. Any suggestion ? feel free to try my code and check it out.
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <fstream>
#include <stdlib.h>
using namespace std;
void Menu()
{
cout << "******************" << endl;
cout << "1 - Add student" << endl;
cout << "2 - Delete student" << endl;
cout << "3 - All students" << endl;
cout << "******************" << endl;
}
struct School
{
string Name;
string remove;
int Ages;
int Option;
};
int main()
{
School Students;
vector <string> Names;
ofstream Myfile("practiceFile.txt", ios::app);
if(!Myfile.is_open())
{
cout << "Error opening file" << endl;
}
if(Myfile.is_open())
{
Menu();
cout << endl;
cout << "Option: ";
cin >> Students.Option;
cin.ignore();
if(Students.Option == 1)
{
cout << "Enter name: ";
getline(cin, Students.Name);
Names.push_back(Students.Name);
for(int i = 0; i < Names.size(); i++)
{
Myfile << Names[i] << endl;
}
}
if(Students.Option == 2)
{
cout << "Enter name: ";
getline(cin, Students.remove);
for(int i = 0; i < Names.size(); i++)
{
if(Students.remove == Names[i])
{
auto itr = find(Names.begin(), Names.end(), Students.remove);
if(itr != Names.end())
{
Names.erase(itr);
Myfile << Names[i] << endl;
}
}
}
}
}
ofstream TempFile("practiceFile_temp.txt", ios::trunc|ios::out);
if(TempFile.is_open())
{
for(int i = 0; i < Names.size(); i++)
{
TempFile << Names[i] << endl;
}
}
TempFile.close();
Myfile.close();
remove("practiceFile.txt");
rename("practiceFile_temp.txt", "practiceFile.txt");
string line;
ifstream NewFile("practiceFile.txt", ios::in);
while(NewFile >> line)
{
if(Students.Option == 3)
{
cout << line << endl;
}
}
}
Actually, if you compile my code you won't be able to save strings into the file. But when I delete this part of my code (here below) At leats I'm able to save strings into the file but not delete them. As I said before, I think I'm not using ios::trunc|ios::out correct. Thanks!
ofstream TempFile("practiceFile_temp.txt", ios::trunc|ios::out);
if(TempFile.is_open())
{
for(int i = 0; i < Names.size(); i++)
{
TempFile << Names[i] << endl;
}
}
TempFile.close();
Myfile.close();
remove("practiceFile.txt");
rename("practiceFile_temp.txt", "practiceFile.txt");
UPDATE:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <fstream>
#include <stdlib.h>
using namespace std;
void Menu()
{
cout << "******************" << endl;
cout << "1 - Add student" << endl;
cout << "2 - Delete student" << endl;
cout << "******************" << endl;
}
struct School
{
string Name;
string remove;
int Ages;
int Option;
};
int main()
{
School Students;
vector <string> Names;
ifstream NewFile("practiceFile.txt");
string line;
while(getline(NewFile, line))
{
cout << line << endl;
}
ofstream Myfile("practiceFile.txt", ios::app);
if(!Myfile.is_open())
{
cout << "Error opening file" << endl;
}
if(Myfile.is_open())
{
Menu();
cout << endl;
cout << "Option: ";
cin >> Students.Option;
cin.ignore();
if(Students.Option == 1)
{
cout << "Enter name: ";
getline(cin, Students.Name);
Names.push_back(Students.Name);
}
if(Students.Option == 2)
{
cout << "Enter name: ";
getline(cin, Students.remove);
for(int i = 0; i < Names.size(); i++)
{
if(Students.remove == Names[i])
{
Names.erase(Names.begin() + i);
}
}
}
for(int i = 0; i < Names.size(); i++)
{
Myfile << Names[i] << endl;
}
}
ofstream TempFile("practiceFile_temp.txt", ios::trunc);
if(TempFile.is_open())
{
for(int i = 0; i < Names.size(); i++)
{
TempFile << Names[i] << endl;
}
}
TempFile.close();
Myfile.close();
remove("practiceFile.txt");
rename("practiceFile_temp.txt", "practiceFile.txt");
}
How do I direct the output of this code into a .txt file?
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace std;
int main() {
using std::cin;
using std::cout;
using std::endl;
int input=1;
int sum=0;
int counter=1;
while (input != 0)
{
std::cout << "Please enter the hit data: ";
std::cin >> input;
if (input == 0) // after puting in data input zero
{
break;
}
else if (input != 0)
{
sum += input;
counter++;
}
}
counter = counter - 1 ;
std::cout << "Sum of hits entered: " << sum << endl ;
std::cout << "Number of hits entered: " << counter << endl ;
if ( counter < 100 )
{
std::cout << "The hits are less than 100" ;
}
else if ( counter > 100 )
{
std::cout << "The hits are greater than 100" ;
}
else if ( counter == 100 )
{
std::cout << "The hits are equal to 100" ;
}
}
Also, instead of a user having to input data, how can I get the program to read data from another .txt file? I understand you can do this all easily in the terminal; however, I would like for the program to create the .txt file.
Also, how do I get the program to recognize certain numbers? I want it to output something like "there was twelve number -11s counted".
Use std::ifstream to read input from a file, and std::ofstream to write output to a file. For example:
#include <iostream>
#include <fstream>
int main()
{
int sum = 0;
int counter = 0;
std::ifstream in("hits.txt");
if (in.is_open())
{
while (in >> input)
{
sum += input;
++counter;
}
}
else
{
std::ofstream out("hits.txt");
int input;
do
{
std::cout << "Please enter the hit data: ";
// after putting in data, input zero
if (!(std::cin >> input) || (input == 0))
break;
out << input << " ";
sum += input;
++counter;
}
while (true);
}
std::cout << "Sum of hits entered: " << sum << endl ;
std::cout << "Number of hits entered: " << counter << endl ;
if (counter < 100)
{
std::cout << "The hits are less than 100" << std::endl;
}
else if (counter > 100)
{
std::cout << "The hits are greater than 100" << std::endl;
}
else
{
std::cout << "The hits are equal to 100" << std::endl;
}
return 0;
}
Also, how do I get the program to recognize certain numbers? I want it to output something like "there was twelve number -11s counted".
You can use std:map for that, eg:
#include <iostream>
#include <fstream>
#include <map>
int main()
{
int sum = 0;
int counter = 0;
std::map<int, int> hits; // hit counter
std::ifstream in("hits.txt");
if (in.is_open())
{
while (in >> input)
{
hits[input]++;
sum += input;
++counter;
}
}
else
{
std::ofstream out("hits.txt");
int input;
do
{
std::cout << "Please enter the hit data: ";
// after putting in data, input zero
if (!(std::cin >> input) || (input == 0))
break;
out << input << " ";
hits[input]++;
sum += input;
++counter;
}
while (true);
}
std::cout << "Sum of hits entered: " << sum << endl ;
std::cout << "Number of hits entered: " << counter << endl ;
if (counter < 100)
{
std::cout << "The hits are less than 100" << std::endl;
}
else if (counter > 100)
{
std::cout << "The hits are greater than 100" << std::endl;
}
else
{
std::cout << "The hits are equal to 100" << std::endl;
}
for (auto &p : hits)
{
if (p.second == 1)
std::cout << "there was 1 number " << p.first << " counted" << std:::endl;
else
std::cout << "there were " << p.second << " number " << p.first << "'s counted" << std:::endl;
}
/* or, if you are not using C++11 or later:
for (std::map<int, int>::iterator iter = hits.begin(); iter != hits.end(); ++iter)
{
std::map<int, int>::value_type &p = *iter;
if (p.second == 1)
std::cout << "there was 1 number " << p.first << " counted" << std:::endl;
else
std::cout << "there were " << p.second << " number " << p.first << "'s counted" << std:::endl;
}
*/
return 0;
}
Outputting data to a .txt file is easy indeed. You already included , now you need to create an object from the type std::ofstream and use it to write your text into a file. I would create a function like this (above main):
#include <iostream>
#include <fstream>
#include <string>
void outputTextToFile (std::string p_text) {
//is created under your project filepath:
std::ofstream file("nameoffile.txt", std::ios::app); //"app" = appending, instead of overwriting text
file << "Writing this to a file.\n";
file.close();
}
Afterwards you can call your function in the while loop with the string text you want, like this for example:
outputTextToFile("test Text");
Reading text from a .txt file is very similar to this, I would suggest you look up this thread: Read file line by line
Here is my code, I have attached the screenshot of what output Zybooks expects, and what my output is. I am trying to get it to output exactly what Zybooks is asking, however something seams to be wrong. It is compiling though. Or maybe Zybooks is just being stupid?
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <cstring>
using namespace std;
int main() {
string title;
string col1;
string col2;
string val;
int numCommas = 0;
vector<string> stringData;
vector<int> intData;
cout << "Enter a title for the data:" << endl;
getline(cin, title);
cout << "You entered: " << title << endl << endl;
cout << "Enter the column 1 header:" << endl;
getline(cin, col1);
cout << "You entered: " << col1 << endl << endl;
cout << "Enter the column 2 header:" << endl;
getline(cin, col2);
cout << "You entered: " << col2 << endl << endl;
while (1) {
cout << "Enter a data point (-1 to stop input):" << endl;
getline(cin, val);
if (val == "-1") {
break;
}
if (val.find(',') == -1) {
cout << "Error: No comma in string." << endl << endl;
}
else {
for (int i = 0; i < val.length(); i++) {
if (val.at(i) == ',') {
numCommas++;
if (numCommas > 1){
break;
}
}
}
if (numCommas == 1) {
stringData.push_back(val.substr(0, val.find(',')));
intData.push_back(stoi(val.substr(val.find(',') + 1, val.length() - 1)));
cout << "Data string: " << val.substr(0, val.find(',')) << endl;
cout << "Data integer: " << stoi(val.substr(val.find(',') + 1, val.length() - 1)) << endl;
}
else {
cout << "Error: Too many commas in input." << endl << endl;
}
}
}
return 0;
}
Thanks.
Thanks.
Your problem is that you initialise numCommas to zero at the start of the program rather than at the start of each author input. That means, once it exceeds one, it will stay that high at least(a), meaning future inputs will always be seen as having too many commas.
You just need to set it to zero immediately before checking each input.
(a) Well, until it wraps around (if it wraps around). But that will be an awful lot of commas you need to input :-)
I am working on a program that allows the user to practice division. My code is below:
//div1
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
using namespace std;
#define CLS "\033[2J\033[1;1H"
#define NEWLINE "\n"
int main() {
srand(time(NULL));
int a, div1, div2;
div1=rand()%11;
div2=rand()%11;
while (div2>div1) {
swap(div1,div2);
continue;
}
if (div1%div2!=0) {
return main();
} else {
cout << CLS;
cout << NEWLINE;
do {
cout << div1 << " / " << div2 << " = ?" << endl;
cin >> a;
cout << CLS;
cout << NEWLINE;
cout << "\t\tWrong!!" << endl;
cout << NEWLINE;
} while (a!=div1/div2);
cout << CLS;
cout << NEWLINE;
cout << "\t\tCorrect!!" << endl;
cout << NEWLINE;
cout << "Hit enter to continue." << endl;
cin.ignore();
cin.get();
return main();
}
return 0;
}
Basically, what it is supposed to do is first choose two random numbers. Then, it is supposed to check to see if the second number (div2) is greater than the first (div1), and if they are, it will switch them. Then, it will use the modulus (div1%div2) to make sure that the two numbers can be divided by each other without a remainder. If they cannot be divided without a remainder, it will restart the program (return main();). However, whenever I run it, I get the segmentation fault: core dumped, either when I start it or after running it a few times. Any ideas on how to fix this?
Thanks!!
Here's an example of what I've said in the comments. Obviously, you can refactor this so that it works more gracefully (as of now it'll give you floating point exceptions sometimes), but it gives you an idea on how to do this without calling main again.
NOTE: You do not need to make a constant for NEWLINE. There is already a built-in constant in std. In fact, you're already using that constant (endl). So you can just do cout << endl instead of cout << NEWLINE.
//div1
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
using namespace std;
#define CLS "\033[2J\033[1;1H"
#define NEWLINE "\n"
int main() {
while(true) {
srand(time(NULL));
int a, div1, div2;
div1=rand()%11;
div2=rand()%11;
while (div2>div1) {
swap(div1,div2);
continue;
}
if (div1%div2!=0) {
} else {
cout << CLS;
cout << NEWLINE;
do {
cout << div1 << " / " << div2 << " = ?" << endl;
cin >> a;
cout << CLS;
cout << NEWLINE;
cout << "\t\tWrong!!" << endl;
cout << NEWLINE;
} while (a!=div1/div2);
cout << CLS;
cout << NEWLINE;
cout << "\t\tCorrect!!" << endl;
cout << NEWLINE;
cout << "Hit enter to continue." << endl;
cin.ignore();
cin.get();
}
}
return 0;
}
This code can get into "divide by 0" error. This is why you would be getting error.
The line "if (div1%div2!=0) {" seems erroneous.
In this line if div2 == 0, then your code will crash.
The code that I posted below is supposed to work in recursion (the Sort() function) even up to 1kk times. The problem is: when the Sort() function gets into loop number 43385 the console stops working and alerts: "The program has stopped working". Is it a problem with memory? If yes, where is the bad part of the code? Greetings.
#include <iostream>
#include <string>
using namespace std;
string a, b;
int n=0,i=0,counter=0;
int Sort(int i)
{
int x=0,y=0,tmp0=0;
char tmp1;
for(x=i;x<n;x++) {
if(a[x]==b[i]){
tmp0=x;
tmp1=a[x];
break;
}
else
continue;
}
for(y=tmp0;y>=i;y--)
y==i ? a[i]=tmp1 : a[y]=a[y-1];
counter+=tmp0-i;
if(i==n-1)
return counter;
else
Sort(i+1);
}
int main()
{
cin >> n >> a >> b;
Sort(0);
return 0;
}
Perhaps a call stack overflow because of too deep recursion?
To add to iltal's comment, you may want to print out information on strings a, b: a.size(), a.length(), a.capacity(), a.max_size()
I'm not sure what this code is trying to do. Here's a revision, with some print statements added, along with a random string generator.
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
string a, b;
int n=0,i=0,counter=0;
int Sort(int i)
{
int x=0,y=0,tmp0=0;
char tmp1;
for(x=i;x<n;x++) {
if(a[x]==b[i]){
tmp0=x;
tmp1=a[x];
cout << "x = " << x << " set tmp0 to " << tmp0 << " and tmp1 to " << tmp1 << endl;
break;
}
else
continue;
}
for(y=tmp0;y>=i;y--)
y==i ? a[i]=tmp1 : a[y]=a[y-1];
counter+=tmp0-i;
cout << " endof sort: a is " << a << endl;
cout << " b is " << b << endl;
if(i==n-1) {
cout << "Returning counter " << counter << endl;
return counter;
} else {
cout << "Running sort(" << i << " + 1)" << endl;
Sort(i+1);
}
}
string randomStrGen(int length) {
static string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
string result;
result.resize(length);
for (int i = 0; i < length; i++)
result[i] = charset[rand() % charset.length()];
return result;
}
int main()
{
n = 50;
srand(time(NULL));
string a0, b0;
a0 = randomStrGen(n);
a = a0;
b0 = randomStrGen(n);
b = b0;
// cin >> n >> a >> b;
cout << "Max string size is " << a.max_size() << endl;
cout << "Calling sort" << endl
<< " n is " << n << endl
<< " a is " << a << endl
<< " b is " << b << endl;
Sort(0);
cout << " endof program: a inital: " << a0 << endl;
cout << " a final: " << a << endl;
cout << " b inital: " << b0 << endl;
cout << " b final: " << b << endl;
return 0;
}
counter is of type int but it has a lot of values summed in it which may be in all larger than int. maybe try int64?
You could hard code some test cases, like n = 20, a = "xyz...", b = "abc...", and add print statements to your sort function to track what is going on. Also, it may be helpful to add some comments to clarify what the purpose of the different loops are.