Read from file up to another point C++ - c++

So I have a list
{"ID":"55e5f0c8ace3e","nombre":"Jacqueline ","apellido":"Charlet ","sobrenombre":"","edad":"30","caracteristicas":"","comentario":"",
I need to change that list and put it in a correct way like:
ID: 55e5f0c8ace3e
Nombre: Jacqueline
Apellido: ...
etc..
Tried this:
#include <iostream>
#include <fstream>
using namespace std;
ifstream datos("datos.txt");
ofstream final("final.txt");
int main(){
char valor;
if(!datos)
{
cout << "error";
}
else
{
while(!datos.eof())
{
datos.get(valor);
if(valor == 'I' && datos.peek() == 'D')
{
cout << "I can read" << endl;
}
}
}
}
I´m trying to do this with C++, which is the correct way to do it? I´ve tried some ways, but i dont know how to read from one point to another, by this i mean read from the double comas the ID and finish on the other double comas.
Thanks in advance

Introduce a integer state variable that describes what part of file you're in. Then interpret every character in accordance with that. For example, initially it's 0. Once you encounter a ", it becomes 1 - that means you're reading a name. If state is 1, and a character is not a "", you accumulate characters in some string variable. Once you encounter a quote character and state is 1, that means the name is over. And so on.
If this is not homework, Google for a C++ JSON parser. This is a stock problem, solved a thousand times already.
Also, please don't edit the answer - place a comment instead.

Related

Filling a cstring using <cstring> with text from a textfile using File I/O C++

I began learning strings yesterday and wanted to manipulate it around by filling it with a text from a text file. However, upon filling it the cstring array only prints out the last word of the text file. I am a complete beginner, so I hope you can keep this beginner friendly. The lines I want to print from the file are:
"Hello World from UAE" - First line
"I like to program" - Second line
Now I did look around and eventually found a way and that is to use std::skipary or something like that but that did not print it the way I had envisioned, it prints letter by letter and skips each line in doing so.
here is my code:
#include <fstream>
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
int main() {
ifstream myfile;
myfile.open("output.txt");
int vowels = 0, spaces = 0, upper = 0, lower = 0;
//check for error
if (myfile.fail()) {
cout << "Error opening file: ";
exit(1);
}
char statement[100];
while (!myfile.eof()) {
myfile >> statement;
}
for (int i = 0; i < 30; ++i) {
cout << statement << " ";
}
I'm not exactly sure what you try to do with output.txt's contents, but a clean way to read through a file's contents using C++ Strings goes like this:
if (std::ifstream in("output.txt"); in.good()) {
for (std::string line; std::getline(in, line); ) {
// do something with line
std::cout << line << '\n';
}
}
You wouldn't want to use char[] for that, in fact raw char arrays are hardly ever useful in modern C++.
Also - As you can see, it's much more concise to check if the stream is good than checking for std::ifstream::fail() and std::ifstream::eof(). Be optimistic! :)
Whenever you encounter output issues - either wrong or no output, the best practise is to add print (cout) statements wherever data change is occurring.
So I first modified your code as follows:
while (!myfile.eof()) {
myfile >> statement;
std::cout<<statement;
}
This way, the output I got was - all lines are printed but the last line gets printed twice.
So,
We understood that data is being read correctly and stored in statement.
This raises 2 questions. One is your question, other is why last line is printed twice.
To answer your question exactly, in every loop iteration, you're reading the text completely into statement. You're overwriting existing value. So whatever value you read last is only stored.
Once you fix that, you might come across the second question. It's very common and I myself came across that issue long back. So I'm gonna answer that as well.
Let's say your file has 3 lines:
line1
line2
line3
Initially your file control (pointer) is at the beginning, exactly where line 1 starts. After iterations when it comes to line3, we know it's last line as we input the data. But the loop control doesn't know that. For all it knows, there could be a million more lines. Only after it enters the loop condition THE NEXT TIME will it come to know that the file has ended. So the final value will be printed twice.

Comparing a string of quiz answers to questions

I have a C++ test question that asks us to write a program that:
1) asks the user to input a string of answers a,b,c, and d: (Example: ACDBDA)
2) asks he user to input a string that is the answer key: (example DBADCD) (we also need to put in something to make sure the length of the answer key is the same as the answers, but that is no biggie)
3) prints the percentage of input answers that were correct, ie match up with the answer key.
Most of this isn't too bad, but I'm not sure how to go about comparing the two strings to see how they differ. Is there any way to get a variable equal to one of the characters in the string which could then be compared with a variable representing the character in the same place as the other string? That's the only way that comes to mind for me. I'm not really looking for a specific code or someone to do it for me, just need some pointers in the right direction.
Thanks!
Ok, so I've made some progress on this and I think I am close. The problem now is that I'm getting "Expression must be of class type" error on the commented lines. I think the issue is in the way I am passing my parameters but I can't seem to figure out how to fix it :(. I've google'd several parameter passing articles but none seem to speak to passing a parameter then getting it's length or comparing it as I do in the program. Any help would be greatly appreciated. Here is the code:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
string getAnswers(string answers)
{
cout << "What are your answers to this questionless quiz? BE WARY OF CHOOSING INCORRECTLY\n:";
cin >> answers;
return answers;
}
string getKey(string key)
{
cout << "Just kidding. What are the answers? \n:";
cin >> key;
return key;
}
double getPercentage(double percentage)
{
int total;
int correct;
getAnswers();
getKey();
total = getAnswers.size(); // "error: expression must have class type"
for (i=0; i>total; i++)
{
int j = 0;
if (getAnswers.at(j) = getKey.at(j)) // "error: expression must have class type" (for both getAnswers and getKey)
correct++;
j++;
}
percentage = (correct/total) * 100;
}
int main()
{
getAnswers();
getKey();
cout << getPercentage(answers, key); //Also I'm really not sure how to get the parameters from previous functions into this one here. Maybe I shoudln't even add parameters and just show the function?
return 0;
}

Create an array with external file in C++

I have 4 days of training in C++, so bear with me.
Two data files are required to evaluate a multiple-choice examination. The first file
(booklet.dat) contains the correct answers. The total number of questions is 50. A sample
file is given below:
ACBAADDBCBDDAACDBACCABDCABCCBDDABCACABABABCBDBAABD
The second file (answer.dat) contains the students’ answers. Each line has one student
record that contains the following information:
The student’s answers (a total of 50 answers) in the same format as above (* indicates no answer)., followed by Student ID and Student Name. Example:
AACCBDBC*DBCBDAAABDBCBDBAA*BCBDD*BABDBCDAABDCBDBDA 6555 MAHMUT
CBBDBC*BDBDBDBABABABBBBBABBABBBBD*BBBCBBDBABBBDC** 6448 SINAN
ACB*ADDBCBDDAACDBACCABDCABCCBDDABCACABABABCBDBAABD 6559 CAGIL
I have a homework assignment to write a C++ program that counts the total number of correct answers by each student and outputs this information to another file called report.dat. In this file, the student’s IDs, names and scores must be given. Each correct answer is worth 1 point. For the sample files given above, the output should be as follows:
6555 MAHMUT 10
6448 SINAN 12
6550 CAGIL 49
Here's what I have so far:
include <iostream>
include <fstream>
using namespace std;
int main()
{
char booklet[50] answers[50]
int counter
// Link answers with booklet.dat
booklet = ifstream
input_file("booklet.dat");
return 0;
// Link answers with answers.dat
answers = ifstream
input_file("answer.dat");
return 0;
while (booklet==answers)
{
counter++
cout << "The student had">>counter>> "answers right";
}
}
I'm not even sure I am in the correct direction. I know I need to create an array from the file booklet.dat and another one from the file answer.dat. Then the comparison has to be made and the matches between the two have to be counted.
I don't expect anyone to do the assignment for me, i just need a nudge in the right direction.
1.) On your Syntax:
a) Each line in C++ has to end with an ";". There are some lines in your excample which don't. (Normally your compile should point at this or the following line with an error)
b) Multiple variable definitions need a "," in between two different variables.
2.) I would recommend you to use something like that:
(have a look at C++ Reference fstream)
EDIT: just a little outline, which is not complete in this form, just to give you and idea ;-)
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
int nr_of_students = 1000; /* Or any number you'd like to analyze */
int stud_nr[nr_of_students];
string stud_name[nr_of_students];
int stud_count[nr_of_students];
fstream in_out;
in_out.open("filename.dat",fstream::in); // fstream::in for reading from file
// fstream::out for writing to this file
if(in_out.is_open())
{
for(lines=0;(in_out>>answers && lines<nr_of_students);lines++)
{
in_out >> stud_nr[lines]; /* EDIT: sorry hat some index confusions here... */
in_out >> stud_name[lines];
stud_count[lines]=0;
for(int i=0;i<50;i++)
{
/* comparison between the booklet_array and the answers_array */
/* Count up the stud_count[lines] for each right comparison */
}
}
/* some simmilar code for the output-file */
}
else cout << "Error reading " << "filename.dat" << endl;
return 1;
}
3.) Your code would also get more performance with vectors.
A good Tutorial would be: Tutorial part I
and you find part 2 in the comments there
4.) you can achieve a more dynamic code with argc and argv**, just google for that
I hope these comments help you a little bit to carry on ;)
You are already on the right direction. Basically you want to load the answer key into an array for fast comparison and then you need to check the answers of each student and each time they get a correct answer you increment a counter and write the ID, name and score for each student. There are problems with your code such as missing semicolons.
Also please note that returning exits a function and that no statements after an unconditional return are executed, returning from main terminates your program.
The normal approach to open a file for reading is:
#include<fstream>
#include<string>
int main()
{
std::ifstream input_file("inputfilename");
// since the answer key is one line
// and each students answer , id and name are also one line
// getting that line using std::getline() would be sufficient
std::string line;
std::getline(input_file, line);
// line would now contain the entire first line except the newline character
std::getline(input_file, line);
//now line would now contain the second line in the file
return 0;
}
Writing to a file is similar we use ofstream to open a file for writing.
Like so:
#include<fstream>
int main()
{
std::ofstream output_file("outputfilename");
// lets say we have a string and an int that we want to write
std::string line_to_write("Hello File");
int number = 42;
output_file << line_to_write << number; // writes the string and then 42 on the same line
output_file << '\n'; // writes the newline character so that next writes would appear on another line
return 0;
}
For references to the standard library and C++ in general when you need to know the available functions to do something I recommend cppreference here are the specific pages on ifstream and ofstream.

read in values and store in list in c++

i have a text file with data like the following:
name
weight
groupcode
name
weight
groupcode
name
weight
groupcode
now i want write the data of all persons into a output file till the maximum weight of 10000 kg is reached.
currently i have this:
void loadData(){
ifstream readFile( "inFile.txt" );
if( !readFile.is_open() )
{
cout << "Cannot open file" << endl;
}
else
{
cout << "Open file" << endl;
}
char row[30]; // max length of a value
while(readFile.getline (row, 50))
{
cout << row << endl;
// how can i store the data into a list and also calculating the total weight?
}
readFile.close();
}
i work with visual studio 2010 professional!
because i am a c++ beginner there could be is a better way! i am open for any idea's and suggestions
thanks in advance!
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <limits>
struct entry
{
entry()
: weight()
{ }
std::string name;
int weight; // kg
std::string group_code;
};
// content of data.txt
// (without leading space)
//
// John
// 80
// Wrestler
//
// Joe
// 75
// Cowboy
int main()
{
std::ifstream stream("data.txt");
if (stream)
{
std::vector<entry> entries;
const int limit_total_weight = 10000; // kg
int total_weight = 0; // kg
entry current;
while (std::getline(stream, current.name) &&
stream >> current.weight &&
stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n') && // skip the rest of the line containing the weight
std::getline(stream, current.group_code))
{
entries.push_back(current);
total_weight += current.weight;
if (total_weight > limit_total_weight)
{
break;
}
// ignore empty line
stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
else
{
std::cerr << "could not open the file" << std::endl;
}
}
Edit: Since you wannt to write the entries to a file, just stream out the entries instead of storing them in the vector. And of course you could overload the operator >> and operator << for the entry type.
Well here's a clue. Do you see the mismatch between your code and your problem description? In your problem description you have the data in groups of four lines, name, weight, groupcode, and a blank line. But in your code you only read one line each time round your loop, you should read four lines each time round your loop. So something like this
char name[30];
char weight[30];
char groupcode[30];
char blank[30];
while (readFile.getline (name, 30) &&
readFile.getline (weight, 30) &&
readFile.getline (groupcode, 30) &&
readFile.getline (blank, 30))
{
// now do something with name, weight and groupcode
}
Not perfect by a long way, but hopefully will get you started on the right track. Remember the structure of your code should match the structure of your problem description.
Have two file pointers, try reading input file and keep writing to o/p file. Meanwhile have a counter and keep incrementing with weight. When weight >= 10k, break the loop. By then you will have required data in o/p file.
Use this link for list of I/O APIs:
http://msdn.microsoft.com/en-us/library/aa364232(v=VS.85).aspx
If you want to struggle through things to build a working program on your own, read this. If you'd rather learn by example and study a strong example of C++ input/output, I'd definitely suggest poring over Simon's code.
First things first: You created a row buffer with 30 characters when you wrote, "char row[30];"
In the next line, you should change the readFile.getline(row, 50) call to readFile.getline(row, 30). Otherwise, it will try to read in 50 characters, and if someone has a name longer than 30, the memory past the buffer will become corrupted. So, that's a no-no. ;)
If you want to learn C++, I would strongly suggest that you use the standard library for I/O rather than the Microsoft-specific libraries that rplusg suggested. You're on the right track with ifstream and getline. If you want to learn pure C++, Simon has the right idea in his comment about switching out the character array for an std::string.
Anyway, john gave good advice about structuring your program around the problem description. As he said, you will want to read four lines with every iteration of the loop. When you read the weight line, you will want to find a way to get numerical output from it (if you're sticking with the character array, try http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/, or try http://www.cplusplus.com/reference/clibrary/cstdlib/atof/ for non-whole numbers). Then you can add that to a running weight total. Each iteration, output data to a file as required, and once your weight total >= 10000, that's when you know to break out of the loop.
However, you might not want to use getline inside of your while condition at all: Since you have to use getline four times each loop iteration, you would either have to use something similar to Simon's code or store your results in four separate buffers if you did it that way (otherwise, you won't have time to read the weight and print out the line before the next line is read in!).
Instead, you can also structure the loop to be while(total <= 10000) or something similar. In that case, you can use four sets of if(readFile.getline(row, 30)) inside of the loop, and you'll be able to read in the weight and print things out in between each set. The loop will end automatically after the iteration that pushes the total weight over 10000...but you should also break out of it if you reach the end of the file, or you'll be stuck in a loop for all eternity. :p
Good luck!

Read file and extract certain part only

ifstream toOpen;
openFile.open("sample.html", ios::in);
if(toOpen.is_open()){
while(!toOpen.eof()){
getline(toOpen,line);
if(line.find("href=") && !line.find(".pdf")){
start_pos = line.find("href");
tempString = line.substr(start_pos+1); // i dont want the quote
stop_pos = tempString .find("\"");
string testResult = tempString .substr(start_pos, stop_pos);
cout << testResult << endl;
}
}
toOpen.close();
}
What I am trying to do, is to extrat the "href" value. But I cant get it works.
EDIT:
Thanks to Tony hint, I use this:
if(line.find("href=") != std::string::npos ){
// Process
}
it works!!
I'd advise against trying to parse HTML like this. Unless you know a lot about the source and are quite certain about how it'll be formatted, chances are that anything you do will have problems. HTML is an ugly language with an (almost) self-contradictory specification that (for example) says particular things are not allowed -- but then goes on to tell you how you're required to interpret them anyway.
Worse, almost any character can (at least potentially) be encoded in any of at least three or four different ways, so unless you scan for (and carry out) the right conversions (in the right order) first, you can end up missing legitimate links and/or including "phantom" links.
You might want to look at the answers to this previous question for suggestions about an HTML parser to use.
As a start, you might want to take some shortcuts in the way you write the loop over lines in order to make it clearer. Here is the conventional "read line at a time" loop using C++ iostreams:
#include <fstream>
#include <iostream>
#include <string>
int main ( int, char ** )
{
std::ifstream file("sample.html");
if ( !file.is_open() ) {
std::cerr << "Failed to open file." << std::endl;
return (EXIT_FAILURE);
}
for ( std::string line; (std::getline(file,line)); )
{
// process line.
}
}
As for the inner part the processes the line, there are several problems.
It doesn't compile. I suppose this is what you meant with "I cant get it works". When asking a question, this is the kind of information you might want to provide in order to get good help.
There is confusion between variable names temp and tempString etc.
string::find() returns a large positive integer to indicate invalid positions (the size_type is unsigned), so you will always enter the loop unless a match is found starting at character position 0, in which case you probably do want to enter the loop.
Here is a simple test content for sample.html.
<html>
<a href="foo.pdf"/>
</html>
Sticking the following inside the loop:
if ((line.find("href=") != std::string::npos) &&
(line.find(".pdf" ) != std::string::npos))
{
const std::size_t start_pos = line.find("href");
std::string temp = line.substr(start_pos+6);
const std::size_t stop_pos = temp.find("\"");
std::string result = temp.substr(0, stop_pos);
std::cout << "'" << result << "'" << std::endl;
}
I actually get the output
'foo.pdf'
However, as Jerry pointed out, you might not want to use this in a production environment. If this is a simple homework or exercise on how to use the <string>, <iostream> and <fstream> libraries, then go ahead with such a procedure.