How to fix this code to read this file in C++? [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Here's my code, which should be able to read the file, but it gives me this:
Error: Invalid format in file
What's wrong in this code?
int main()
{
std::map<std::string, std::vector<std::string>> routes;
print_rasse();
std::string inp;
std::cout << "Give a name for input file: ";
std::getline(std::cin, inp);
std::ifstream file(inp);
std::string row;
if ( not file ) {
std::cout << "Error: File could not be read." << std::endl;
return EXIT_FAILURE;
}
while(getline(file, row)){
if (count(row.begin(), row.end(),';'+!1)){
std::cout << "Error: Invalid format in file." << std::endl;
return EXIT_FAILURE;
}
}
}
The .txt file which I'm trying to read contains this:
West;Pyynikintori;0
West;Tuulensuu;0.5
West;Keskustori;1.5
West;Koskipuisto;1.8
West;Rautatieasema;2.2
West;Tulli;2.5
West;Sammonaukio;2.8
East;Sammonaukio;
East;Kaleva;0.2
East;Uintikeskus;0.3
East;Kalevanrinne;0.6
East;Hakametsa;1
East;Turtola;3
East;Hallila;5
East;Hervanta;7
East;Hervannan kampus;7.1
South;Hervannan kampus
South;Etela-Hervanta;0.4
South;Hervantajarvi;0.7
Hospital;Sammonaukio
Hospital;Kalevan kirkko;0.1
Hospital;Hippos;0.4
Hospital;TAYS;0.6
Hospital;Kaupin kampus;0.7

In this statement:
if (count(row.begin(), row.end(),';'+!1))
!1 is effectively the same as 0, so ';'+0 is just ';'. The statement is effectively this:
if (count(row.begin(), row.end(), ';'))
It is counting the number of ; characters in the row. An integer implicitly converts to a bool, where 0 is false and non-0 is true. So, if there are any matching characters in the row, the if will evaluate as true, otherwise as false.
Since each line in the .txt file shown has 2 ; characters in it, count() will return 2, thus the if will be true, and so the code will display the error message.
You probably meant to do this instead:
if (count(row.begin(), row.end(), ';') != 2)

Related

sf::String put into std::map key doesn't work - the vaule is not saved into map [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
as I wrote in the topic - I try to put sf::String into map first argument and it does not work. Here's the code:
void Flashcards::add(sf::String sf_string) {
std::string text = sf_string.toAnsiString();
std::pair<std::string,std::string> pairr = std::make_pair(text,"<Polish translation>");
std::cout << "Inserting: " << pairr.first << std::endl;
all_words.insert(pairr); //std::map<std::string, std::string> variable
void Flashcards::show() {
std::cout << "Flashcards:\n";
for (std::map<std::string, std::string>::iterator it = all_words.begin(); it != all_words.end(); it++)
{
std::cout << "English word: " << it->first
<< " " << "Polish word: " << it->second << std::endl;
}
The result in console is:
Inserting: //a word//
Flashcards:
Polish word: <Polish translation>
Instead of needed:
Inserting: hello
Flashcards:
English word: //a word// Polish word: <Polish translation>
Here are the variations I have already tried:
1) I switched the arguments so it looked like this: std::make_pair("<Polish translation>",text); and it works - hardcoded key and the value are both showed in the console (but I don't want hardcoding, what is obvious).
2) Note that this line: std::cout << "Inserting: " << pairr.first << std::endl; shows that the key value is converted into std::string correctly - calling this will show value we have just typed on the keyboard.
3) I tried to send the sf::String value directly to the std::make_pair() method, it works exactly the same as putting std::string there.
Can somebody say how to make this work?
The string you are providing as an argument to the add method obviously ends with a \r (carriage return) character, probably because you are reading it from a Windows text file using a Unix/Linux execution environment. If you capture the output of your program in a file and look at it with a hexdumper (such as hd), you should immediately see what is going on.
It certainly has nothing to do with your use of the C++ standard library. However, you don't need to go to all that work to insert an entry into a std::map. Just do this:
all_words[key] = value;
As long as key has the right type (or there is an automatic conversion), that will do precisely what you want in a single line easily-understood line, and probably more efficiently as well.

Reading a text file into a char array, then into a char linked list

So currently I am working on an assignment, and for a section of it I need to be able to read a .txt file into a linked list of type char. I was already confused trying to do this, so I set out on a different path and decided to try to copy the text from the file into a char array, and then one by one copy the values in the array into the linked list.
So far I have my program compiling and running up to a certain point, before I receive the error Segmentation fault (core dumped).
The code for reading the file is as follow:
void readFile(list<char> &originList, string fileName){
ifstream fileInput;
fileInput.open(fileName.c_str());
int arraySize = fileInput.gcount();
char tempHold[arraySize];
if (!fileInput) {
cout << "Can't open file: " << fileName << "\n";
} else {
string contents((istreambuf_iterator<char>(fileInput)), istreambuf_iterator<char>());
strcpy (tempHold, contents.c_str());
for (int x = 0; x < fileInput.gcount(); x++) {
originList.push_back(tempHold[x]);
}
}
fileInput.close();
}
Also to add some context, using cout I determined that the code stops running, instead presenting the error, at the following point:
strcpy (tempHold, contents.data());
Also, I am not 100% on how exactly they work, only a loose idea to be honest. I mostly sourced the idea from this Stack Overflow question,
How to copy a .txt file to a char array in c++, but got confused somewhere a long the way.
Thanks in advance for any help you can provide.
istream::gcount returns the number of characters extracted by the last unformatted input operation performed on the object. Since you did not read anything from the file, you should get something wrong.Call, for example, istream.getline(); before calling gcount()
Like my comment to your question says, read each character from the file and add it to the list.
void readFile(list<char> &originList, string fileName) {
ifstream fileInput(fileName.c_str());
if (!fileInput) {
cout << "Can't open file: " << fileName << "\n";
}
char c;
while (fileInput.get(c)) {
originList.push_back(c);
}
}
Note: while (fileInput.get(c)) This reads the character and returns the stream. When a stream is used as a bool value it checks to see if the stream is valid. Valid means eof() and bad() are both false. - From a comment to the answer to the question linked below.
My answer was adapted from this other Stack Overflow question: Reading from text file until EOF repeats last line

I can't read a single line using getline() [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I've got a class:
class DataBase{
private:
fstream db_file;
public:
DataBase(){
db_file.open("db.txt", std::ios::in | std::ios::out);
}
void couteverything(){
string line;
if(db_file.good() && db_file.is_open()){
getline(db_file, line);
cout << line;
cout << "ok";
}
}
~DataBase(){
db_file.close();
}
};
and a file db.txt with some content.
I'd like to cout it to the console, but it's not working - as if the file was empty (nothing appears on the screen).
In your constructor, you do not test whether the file opened successfully. Therefore, you have no idea if the file opened successfully. Thus, your couteverything method can't distinguish EOF from "failed to open." You might consider adding a check:
DataBase(){
db_file.open("db.txt", std::ios::in | std::ios::out);
if (!db_file.is_open() || !db_file.good()) {
// put an error message here, or throw an exception. Up to you.
}
}
Once you're in couteverything(), presumably you want to loop over the entire file. You need a loop for that, not an if statement. Something like this:
while (getline(db_file, line)) {
cout << line;
cout << "ok";
}
Even if you did not want to loop here (in which case coutnextline() might be a better name for the method), you still want to test the result of getline() directly, rather than testing good() and is_open() before each read. You need to test whether getline() succeeds, otherwise your code will try to process one line beyond EOF or a read error.
if (getline(db_file, line)) {
cout << line;
cout << "ok";
}
If you do only want to output a line at a time, I'm not sure how the code that calls this would know when to stop. But, that's a different problem. (Hint: You could solve that by returning a bool from this line-at-a-time method.)

c++ Parsing prices of a text file [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I need to parse the following file so it takes the item as a string then skip the # sign and then take the price as a float.
text file:
hammer#9.95
saw#20.15
shovel#35.40
how would I go about doing this?
In case when you have std::string in presented format you could use something like this:
std::string test {"test#5.23"};
std::cout << std::stof(std::string{test.begin() + test.rfind('#') + 1, test.end()});
Note that std::stof is C++11 function
Read the file line by line into a string. Find # and parse second part as float.
std::ifstream file("input.txt");
for (std::string line; std::getline(file, line); )
{
auto sharp = line.find('#'); // std::size_t sharp = ...
if (sharp != std::string::npos)
{
std::string name(line, 0, sharp);
line.erase(0, sharp+1);
float price = std::stof(line);
std::cout << name << " " << price << "\n";
}
}
Note: I didn't some error checking, do them yourself as an exercise. and also you should know about std::string, std::ifstream, std::getline and std::stof.

How to properly read from a .csv? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am having memory trouble with my code, and figured out that my code was being read wrong. For example the last value is adding numbers, not sure why. Also the names aren't coming out right.
This is what the output is looking like:
4101,BRAEBURN02.07682e-3172.07691e-317
4021,DELICIOUS02.07682e-3172.07691e-317
4020,DELICIOUS02.07682e-3172.07691e-317
4015,DELICIOUS02.07682e-3172.07691e-317
4016,DELICIOUS02.07682e-3172.07691e-317
4167,DELICIOUS02.07682e-3172.07691e-317
4124,EMPIRE,1,1.14,145.202.07682e-3172.07691e-317
4129,FUJI02.07682e-3172.07691e-317
4131,FUJI02.07682e-3172.07691e-317
As you can see the Empire was separated properly with the exception of the the last value.
Here's my code: the cout part was just for my personal use to see if the values were being inputted properly.
int main()
{
string name;
double price;
int by_weight;
double inventory;
int plu_code;
ifstream infile;
infile.open("inventory.csv");
while(!infile.eof())
{
stringstream ss;
string line = "";
getline(infile,line);
Tokenizer tok(line, ",");
ss << line;
ss >> plu_code >> name >> by_weight >> price >>inventory;
cout << plu_code<<"" <<name<<"" << by_weight<<"" << price <<""<<inventory<<"\n";
table[plu_code] = new Product(plu_code, name,by_weight, price,inventory);
numProducts++;
}
return 0;
}
The Empire line works because it's the only one whose name contains no whitespace. When you read strings from a stream, they are delimited by whitespace, so you only get the first word. If there are more words after that, then reading a double or other numeric type will fail because the stream is still pointing at non-numeric characters. You are not testing that your input operations succeeded, but it should have been obvious from your output.
I'm not sure what effect your Tokeniser class is supposed to have here. But perhaps have a look at this SO question for tokenising commas out of the stream. You can use a single getline call with a comma delimiter to read the name, and then normal << operator for the others.
[Edit] In fact, after cleaning up your question layout I notice that the Empire line doesn't work. It's reading the rest of the line as the name, and then still outputting uninitialised values. Which suggests to me your Tokeniser doesn't do anything at all.