I'm working on a c++ program that is supposed to eventually create a cross-reference table from a paragraph of words read in from a file using hashing. Right now I'm mainly working on reading in the input from the file and making sure the hash function is working properly.
Here a little more specifics on this portion of the problem:
The program is supposed to read in a paragraph from a file one word at a time until it reaches a "word" consisting of 10 "*"s. Below this line of *s are a few more lines of words that will be used to test the program later on.
With the code I have written, everything appears to be working properly (I've used the formula to calculate the index of a couple of the words and am getting the same answer as is being displayed), however, I'm not sure how to get the input to stop when I reach the line of 10 *s. So while this seems to be reading the file in correctly and performing the right calculations, it's performing these calculations for every word in the file.
Here's the code I've written:
#include <iostream>
#include <fstream>
using namespace std;
int hash(string word) {
int firstOff = word[0];
int lastOff = word[word.size() - 1];
int index = (firstOff * 256 + lastOff) % 23;
cout << index << endl;
return index;
}
int main() {
ifstream file;
file.open("prog7.dat");
if(!file.is_open()) {
cerr << "Error opening " << file << endl;
}
string word;
while(file >> word) {
hash(word);
}
}
Here's the output I'm getting:
12
6
17
21
1
21
12
14
11
12
7
14
16
10
2
22
19
21
22
7
7
12
21
21
3
9
3
12
14
14
0
3
21
7
6
7
12
7
17
6
2
16
21
7
14
And in case it helps, here's the file I'm using for the input:
the relative lack of acceptance
of these products in the
corporate marketplace is
due less to technical than
to political factors the
availability of this technology
threatens the perks privileges
and traditions of corporate
management
**********
the
political
lack
relative
less
forgive
tradition
factors
more
Can anyone help me out? I'd really appreciate it.
You can simply check for the word in the while condition:
while(file >> word && word != "**********") {
hash(word);
}
You could also break the loop when you reach the word (if you prefer how it looks).
while(file >> word) {
if (word == "**********") break;
hash(word);
}
Can also use an istream_iterator such as
#include <iostream>
#include <string>
#include <iterator>
#include <fstream>
using namespace std;
int main()
{
ifstream file("prog7.dat");
istream_iterator<string> it(file);
while(*it != "**********")
hash(*it++);
}
Related
I am trying to perform some operations on a text file containing a repetition of a C based string and some numbers. My code successfully carried out the operation on the first set but it would not get to the remaining sets.
Please see the content of the text file below:
Max Scherzer 2017
6.2 4 2 2 2 7
6.0 4 3 1 2 10
mod Cameron 2018
6.4 4 1 2 1 3
6.0 4 3 5 2 8
John Brandonso 2019
6.1 1 3 5 2 7
6.5 4 7 3 4 10
I have used .eof() and it completely messed up what i am doing.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
using namespace std;
int main()
{
char playername [25];
int season;
ifstream gamefilein;
gamefilein.open("C:\\Users\\troy\\Desktop\\GAME_SCORE\\gameinfo.txt");
if(!gamefilein)
{
cout<<"unable to open file";
}
double IP;
int H,R,ER,BB,K;
int counter=0;
double totalscore=0;
while(!gamefilein.fail())
{
gamefilein.get(playername,25);
gamefilein>>season;
cout<<playername<<season<<endl;
cout<<"Game Scores:"<<endl;
while(gamefilein>>IP>>H>>R>>ER>>BB>>K)
{
int IPa=IP;
int IPb=(IP-IPa)*10;
int IPc=0;
if(IPa>4)
{
IPc=IPa-4;
}
int score=50+(IPa*3)+(IPb*1)+(IPc*2)+(K*1)-(H*2)-(ER*4)-((R-ER)*2)-(BB*1);
cout<<score<<endl;
counter++;
totalscore+=score;
}
cout<<"Number of Games Started: "<<counter<<endl;
cout<<fixed<<setprecision(2)<<"Average Game Score:
<<(totalscore/counter)<<endl<<endl;
}
gamefilein.close();
return 0;
}
I get the below result, but I want the same result for the rest of the information in the text file, for example, I am expecting two more results like the one I have below.
Max Scherzer 2017
Game Scores:
63
64
Number of Games Started: 2
Average Game Score: 63.50
Aren't you reading the file as a char array?
If I read this correctly you try to shift an int and double over a char array with numbers in a STRING right?
e.g. "6.2" string is different than a 6.2 double number in your memory, hence why it cant work.
You also seem to have a lot of spaces which should not forget as well.
Where do you get that string to begin with? I would recommend you change the creation of that file to a more convenient format e.g. cv or json
I just solved my problem myself. The problem occurred when the loop operating on the integers and double completes its run and sees the character-based string that is in the next dataset. So i inserted a clear member function just at the point where i check for end of file
(gamefilein.clear())
and that solved my problem.
Thanks for attempting to help
Have an ASCII text file with some integer numbers in it, each separated by a space, and sometimes the numbers go on to a new line. For example:
// my_file.txt
23 45 973 49
44 1032 33 99
43 8 4 90824
I want to read 100 of these numbers into an array of "ints". Thus far, I have the following code:
int x[100];
fstream file_in("my_file.txt", ios::in);
for (int i = 0; i < 100; i++)
{
file_in >> x[i];
}
However, I now want to do a couple of other things that I am not sure about.
What if I want to just read the entire file in, without having to go through the loop? If this was binary data, I know that I can just write file_in.read((char*)&x[0], 100 * sizeof(int)). But how can I do this with an ASCII file?
What if I want to skip the first 3 numbers in the file, and start reading from the fourth? Again, if this was binary data, I could just use file_in.seekg(3 * sizeof(char)). But I don't know how to skip in an ASCII file.
No raw loops!
Reading the entire file:
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
std::ifstream f("data.txt");
std::vector<int> v(std::istream_iterator<int>(f), {});
Skipping over the first three:
v.erase(v.begin(), v.begin() + 3);
I'm just trying to run a simple c++ program that will format a .txt file with data entries. I have run it with many different text files of the exact same format, and now it just won't work. I'm sure the solution is simple.
Here is a simplified version of the program (I trimmed down everything to only show the parts that are giving me trouble).
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;
int main(){
ifstream filei("in.txt");
ofstream fileo("comlab.txt");
double a, b;
string s;
stringstream ss;
while (getline(filei,s)){
ss<<s;
ss>>a>>b;
fileo<<setw(10)<<a<<setw(10)<<b<<'\n';
}
fileo.close();
}
Here is a sample input for in.txt:
1 11
2 22
3 33
4 44
5 55
Now here is what I want to show up (exactly the same as input):
1 11
2 22
3 33
4 44
5 55
But here is what actually shows up:
1 11
1 11
1 11
1 11
1 11
What is going on? I'm compiling with g++ and following the C++11 standard.
When you execute
ss>>a>>b;
in the first round of execution of the loop. ss is already at the end of the stream. i.e. ss.eof() == true. You need to clear its state and reset state to start reading from the beginning.
while (getline(filei,s)){
ss<<s;
ss>>a>>b;
ss.clear();
ss.seakg(0);
fileo<<setw(10)<<a<<setw(10)<<b<<'\n';
}
A better alternative is to create the object within the scope of the loop.
while (getline(filei,s)){
stringstream ss;
ss<<s;
ss>>a>>b;
fileo<<setw(10)<<a<<setw(10)<<b<<'\n';
}
or even simpler (Thanks to #vsoftco for the suggestion)
while (getline(filei,s)){
stringstream ss(s);
ss>>a>>b;
fileo<<setw(10)<<a<<setw(10)<<b<<'\n';
}
This question already has answers here:
Processing lines from one text file to another
(2 answers)
Closed 8 years ago.
I am trying to read a text file that has 200 lines looking like these four examples:
1 4:48:08 Orvar Steingrimsson 1979 30 - 39 ara IS200
2 4:52:25 Gudni Pall Palsson 1987 18 - 29 ara IS870
3 5:14:24 Ryan Paavola 1984 18 - 29 ara USA
4 5:18:43 Hendrik Sporing 1990 18 - 29 ara GER
Currently, the lines are organised by their time, as you can see, but I wish to organise them by the birthyear of each contestant, so that in this case, these four lines would look like this:
4 5:18:43 Hendrik Sporing 1990 18 - 29 ara GER
2 4:52:25 Gudni Pall Palsson 1987 18 - 29 ara IS870
3 5:14:24 Ryan Paavola 1984 18 - 29 ara USA
1 4:48:08 Orvar Steingrimsson 1979 30 - 39 ara IS200
I am supposed to rearrange the lines according to the birthyear, and the input file is "laugavegurinn.txt" and the output file is "laugavegurinn2.txt"
Can anyone point out the problem with my code and/or suggest a better way to do this? Heads up, not very skilled with C++ and would appreciate any help at all. This is my code:
#include <iostream> //for basic functions
#include <fstream> //for basic file operations
#include <string> //for string operations
#include <map> //for multimap functions
using namespace std;
void process (istream &in, ostream &out) {
multimap<int, string> data_by_year;
string str;
while (getline(in,str)) {
int year = stoi(str.substr(54, 4));
data_by_year.insert(make_pair(year, str));
}
for (auto v : data_by_year) {
out << v.second << "\n";
}
}
int main () {
ifstream in;
ofstream out;
in.open("laugavegurinn.txt");
out.open("laugavegurinn2.txt");
process(in, out);
}
This is working right? You're just looking for improvements.
The usual way to do this would be to add all the lines unsorted to a std::vector<std::string> and then call std::sort with a custom ordering to sort into the desired order, then print out.
Should be a little more efficient than your solution (which is pretty good anyway).
As an alternative to using str.substr(54 ,4), you could have used the following method (using character positions is error prone if the format ever changes):
#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
using namespace std;
int main() {
string myString = "Three separate tokens";
istringstream iss(myString);
auto it = istream_iterator<string>(iss);
string thirdToken = *(it ++ ++);
cout << thirdToken;
}
This directly reads the third word, regardless of its position or length.
I need to get very basic input from an external file in C++. I tried searching the internet a few times but nothing really applied to what I need. This would be a .txt file that the input it coming from, and it would be filled with lines like this:
131
241
371
481
I have code already to manually get this input, and it looks like this:
using namespace std;
//Gets the initial values from the user.
int control=0;
while (rowb!=0){
cout << "Row: ";
cin >> rowb;
cout << "Column: ";
cin >> columnb;
cout << "Number: ";
cin >> numb;
row[control]=rowb-1;
column[control]=columnb-1;
num[control]=numb;
control++;
}
This is part of a program that solves sudoko boards. The inputed numbers are the initial values that a sudoko board holds, and the user is inputing the row, column, and number that comes from a board.
What I need is to be able to create a .txt file with these numbers stored in rows so that I do not have to enter so many numbers. I have very little idea how to go about doing this. Mainly I'll only be using the txt file for testing my program as I move along with adding more code to it. It takes 150+ entered numbers within my program just to get a single board, and it takes a lot of time. Any accidentally wrong entered value is also a huge problem as I have to start again. So how would I get C++ to read a text file and use those numbers as input?
Aside from the other suggestions, you can simply redirect a file to standard input, like so (where $ is the command prompt):
$ myprogram < mytextfile.txt
That will run myprogram just as normal but take input from mytextfile.txt as if you had typed it in. No need to adjust your own program at all.
(This works on both Unix/Linux systems and on Windows.)
You can open a file for input with std::ifstream from the header <fstream>, then read from it as you would from std::cin.
int main()
{
std::ifstream input("somefile.txt");
int a;
input >> a; // reads a number from somefile.txt
}
Obviously, you can use >> in a loop to read multiple numbers.
Create an std::ifstream object, and read from it just like you would from std::cin. At least if I understand what you're trying to do, the 131 as the first input is really intended to be three separate numbers (1, 3, and 1). If so, it's probably easiest to change your input file a bit to put a space between each:
1 3 1
2 4 1
3 7 1
4 8 1
Personally, I would start with a different format of the file: enter a value for each cell. That is, each row in the input file would represent a row in the sudoko board. Empty fields would use a space character. The immediate advantage is that the input actually pretty much looks like the sudoko board. Also, you would enter at most 90 characters: 9 characters for the board and a newline for each line:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
int main(int ac, char* av[])
{
std::ifstream in(ac == 1? "sudoko.init": av[1]);
char board[9][9];
for (int i(0); i != 9; ++i)
{
in.read(board[i], 9).ignore();
}
if (!in)
{
std::cout << "failed to read the initial board\n";
}
else
{
typedef std::ostream_iterator<char> iterator;
std::fill_n(iterator(std::cout << "board:\n\n+", "+"), 9, '=');
for (int i(0); i != 9; ++i)
{
std::copy(board[i] + 0, board[i] + 9, iterator(std::cout << "\n|", "|"));
std::fill_n(iterator(std::cout << "\n+", "+"), 9, (i + 1) % 3? '-': '=');
}
std::cout << "\n";
}
}
This would take input like this:
4 5 3 8
71 3
16 7
6 4 7
6 8
1 9 5
6 42
5 94
4 7 9 3
Note that each of these lines uses 9 characters. You might want to use something more visible like ..