Query regarding SPOJ TEST - c++

I might be wrong in asking an SPOJ problem on this forum but I wanted to understand one mechanism which I wanted to know from the enriched community here.
Your program is to use the brute-force approach in order to find the Answer to Life, the Universe, and Everything. More precisely... rewrite small numbers from input to output. Stop processing input after reading in the number 42. All numbers at input are integers of one or two digits.
Example
Input:
1
2
88
42
99
Output:
1
2
88
My Solution:
#include <iostream>
using namespace std;
int main()
{
int n,i=0;
int a[100] = {0};
while((cin>>n))
{
a[i] = n;
i++;
continue;
}
for(int j = 0;a[j]!=42;j++)
cout<<a[j]<<endl;
return 0;
}
Good Solution:
#include <iostream>
using namespace std;
int main()
{
int n;
while(true)
{
cin>>n;
if(n == 42)
break;
cout<<n<<endl;
}
return 0;
}
My query is what happens to the input in the good solution?We would be running the loop only till the number is not 42.How does Good solution handle the remaining input?I got some hint that it is somewhat related to buffering and all.Please provide me some explanation or links or study material or at least some keyword to google etc to get clarity on this.

Remaining input in good solution will be ignored by "good solution".
If you need more info read:
object
std::cin
extern istream cin;
Standard input stream
Object of class istream that represents the standard input stream oriented to narrow characters (of type char). It corresponds to the C stream stdin.
The standard input stream is a source of characters determined by the environment. It is generally assumed to be input from an external source, such as the keyboard or a file.
object
stdin
FILE * stdin;
Standard input stream
The standard input stream is the default source of data for applications. In most systems, it is usually directed by default to the keyboard.
stdin can be used as an argument for any function that expects an input stream (FILE*) as one of its parameters, like fgets or fscanf.

Related

C++ binary files I/O, data lost when writing

I am learning C++ with the "Programming: Principles and Practice Using C++" book from Bjarne Stroustrup. I am currently studying chapter 11 and I found an example on how to read and write binary files of integers (section 11.3.2). I played around with the example and used a .txt file (input.txt) with a sentence which I read and wrote to another file (output.txt) (text_to_binary fnc) and then read and wrote back to the original file (input.txt) (binary_to_text fnc).
#include<fstream>
#include<iostream>
using namespace std;
void text_to_binary(ifstream &ifs, ofstream &ofs)
{
for (int x; ifs.read(as_bytes(x), sizeof(char));)
{
ofs << x << '\n';
}
ofs.close();
ifs.close();
}
void binary_to_text(ifstream &ifs, ofstream &ofs)
{
for (int x; ifs >> x;)
{
ofs.write(as_bytes(x), sizeof(char));
}
ifs.close();
ofs.close();
}
int main()
{
string iname = "./chapter_11/input.txt";
string oname = "./chapter_11/output.txt";
ifstream ifs{iname, ios_base::binary};
ofstream ofs{oname, ios_base::binary};
text_to_binary(ifs, ofs);
ifstream ifs2{oname, ios_base::binary};
ofstream ofs2{iname, ios_base::binary};
binary_to_text(ifs2, ofs2);
return 0;
}
I figured out that I have to use sizeof(char) rather than sizeof(int) in the .read and .write command. If I use the sizeof(int) some chars of the .txt file go missing when I write them back to text. Funnily enough chars only goes missing if
x%4 != 0 (x = nb of chars in .txt file)
example with sizeof(int):
input.txt:
hello this is an amazing test. 1234 is a number everything else doesn't matter..asd
(text_to_binary fnc) results in:
output.txt:
1819043176
1752440943
1763734377
1851859059
1634558240
1735289210
1936028704
824192628
540291890
1629516649
1836412448
544367970
1919252069
1768453241
1696622446
543519596
1936027492
544483182
1953784173
774795877
(binary_to_text fnc) results back in:
input.txt:
hello this is an amazing test. 1234 is a number everything else doesn't matter..
asd went missing.
Now to my question, why does this happen? Is it because int's are saved as 4 bytes?
Bonus question: Out of interest, is there a simpler/more efficient way of doing this?
edit: updated the question with the results to make it hopefully more clear
When you attempt to do a partial read, the read will attempt to go beyond the end of the file and the eof flag will be set for the stream. This makes its use in the loop condition false so the loop ends.
You need to check gcount of the stream after the loop to see if any bytes was actually read into the variable x.
But note that partial reads will only write to parts of the variable x, leaving the rest indeterminate. Exactly which parts depends on the system endianness, and using the variable with its indeterminate bits will lead to undefined behavior.

c++ if(cin>>input) doesn't work properly in while loop

I'm new to c++ and I'm trying to solve the exercise 6 from chapter 4 out of Bjarne Stroustrups book "Programming Principles and Practise Using C++ and don't understand why my code doesn't work.
The exercise:
Make a vector holding the ten string values "zero", "one", ...,
"nine". Use that in a program that converts a digit to its
corresponding spelled-out value: e.g., the input 7 gives the output
seven. Have the same program, using the same input loop, convert
spelled-out numbers into their digit form; e.g., the input seven gives
the output 7.
My loop only executes one time for a string and one time for an int, the loop seems to continue but it doesn't matter which input I'm giving, it doesn't do what it's supposed to do.
One time it worked for multiple int inputs, but only every second time. It's really weird and I don't know how to solve this in a different way.
It would be awesome if someone could help me out.
(I'm also not a native speaker, so sorry, if there are some mistakes)
The library in this code is a library provided with the book, to make the beginning easier for us noobies I guess.
#include "std_lib_facilities.h"
int main()
{
vector<string>s = {"zero","one","two","three","four","five","six","seven","eight","nine"};
string input_string;
int input_int;
while(true)
{
if(cin>>input_string)
{
for(int i = 0; i<s.size(); i++)
{
if(input_string == s[i])
{
cout<<input_string<<" = "<<i<<"\n";
}
}
}
if(cin>>input_int)
{
cout<<input_int<<" = "<<s[input_int]<<"\n";
}
}
return 0;
}
When you (successfully) read input from std::cin, the input is extracted from the buffer. The input in the buffer is removed and can not be read again.
And when you first read as a string, that will read any possible integer input as a string as well.
There are two ways of solving this:
Attempt to read as int first. And if that fails clear the errors and read as a string.
Read as a string, and try to convert to an int. If the conversion fails you have a string.
if(cin >> input) doesn't work properly in while loop?
A possible implementation of the input of your program would look something like:
std::string sentinel = "|";
std::string input;
// read whole line, then check if exit command
while (getline(std::cin, input) && input != sentinel)
{
// use string stream to check whether input digit or string
std::stringstream ss(input);
// if string, convert to digit
// else if digit, convert to string
// else clause containing a check for invalid input
}
To discriminate between int and string value you could use peek(), for example.
Preferably the last two actions of conversion (between int and string) are done by separate functions.
Assuming the inclusion of the headers:
#include <iostream>
#include <sstream>

Read a line of a file c++

I'm just trying to use the fstream library and I wanna read a given row.
I thought this, but I don't know if is the most efficient way.
#include <iostream>
#include <fstream>
using namespace std;
int main(){
int x;
fstream input2;
string line;
int countLine = 0;
input2.open("theinput.txt");
if(input2.is_open());
while(getline(input2,line)){
countLine++;
if (countLine==1){ //1 is the lane I want to read.
cout<<line<<endl;
}
}
}
}
Is there another way?
This does not appear to be the most efficient code, no.
In particular, you're currently reading the entire input file even though you only care about one line of the file. Unfortunately, doing a good job of skipping a line is somewhat difficult. Quite a few people recommend using code like:
your_stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
...for this job. This can work, but has a couple of shortcomings. First and foremost, if you try to use it on a non-text file (especially one that doesn't contain new-lines) it can waste inordinate amounts of time reading an entire huge file, long after you've read enough that you would normally realize that there must be a problem. For example, if you're reading a "line", that's a pretty good indication that you're expecting a text file, and you can pretty easily set a much lower limit on how long that first line could reasonably be, such as (say) a megabyte, and usually quite a lot less than that.
You also usually want to detect whether it stopped reading because it reached that maximum, or because it got to the end of the line. Skipping a line "succeeded" only if a new-line was encountered before reaching the specified maximum. To do that, you can use gcount() to compare against the maximum you specified. If you stopped reading because you reached the specified maximum, you typically want to stop processing that file (and log the error, print out an error message, etc.)
With that in mind, we might write code like this:
bool skip_line(std::istream &in) {
size_t max = 0xfffff;
in.ignore(max, '\n');
return in.gcount() < max;
}
Depending on the situation, you might prefer to pass the maximum line size as a parameter (probably with a default) instead:
bool skip_line(std::istream &in, size_t max = 0xfffff) {
// skip definition of `max`, remainder identical
With this, you can skip up to a megabyte by default, but if you want to specify a different maximum, you can do so quite easily.
Either way, with that defined, the remainder becomes fairly trivial, something like this:
int main(){
std::ifstream in("theinput.txt");
if (!skip_line(in)) {
std::cerr << "Error reading file\n";
return EXIT_FAILURE;
}
// copy the second line:
std::string line;
if (std::getline(in, line))
std::cout << line;
}
Of course, if you want to skip more than one line, you can do that pretty easily as well by putting the call to skip_line in a loop--but note that you still usually want to test the result from it, and break the loop (and log the error) if it fails. You don't usually want something like:
for (int i=0; i<lines_to_skip; i++)
skip_line(in);
With this, you'd lose one of the basic benefits of assuring that your input really is what you expected, and you're not producing garbage.
I think you can condense your code to this. if (input) is sufficient to check for failure.
#include <iostream>
#include <fstream>
#include <limits>
int main()
{
std::ifstream input("file.txt");
int row = 5;
int count = 0;
if (input)
{
while (count++ < row) input.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::string line;
std::getline(input, line);
std::cout << line;
}
}

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.

Using C++ code in VIsual C++, no errors but some part of the code is just ignored

I'm an absolute beginner to programming and i'm just doing some exercises exercises for the beginning.
First of all, i'm using Visual C++ 2010 to compile C-Code. I just create a new project and choose an empty console application. After that, I create a ressource file named test.c and change in the file properties the elementype to C/C++ Compiler and compile as C++ Code, so that i can use #include <iostream> for the std::cin.get() command. Now the code:
#include <stdio.h>
#include <iostream>
int main()
{
int number1, number2;
int sum;
puts("Enter number 1 please:");
scanf_s("%d",&number1);
puts("Enter number 2 please:");
scanf_s("%d",&number2);
std::cin.get();
std::cin.get(); //(1)
sum = number1 + number2;
printf("The average is %f\n", sum/2);
return 0;
}
Now my problem ist that the "std::cin.get()" command is just ignored. Afer typing in the two numbers the program just stops and the console window closes.
Any idea where the problem is?
I have another question please.
Since my problem with holding the console open is solved (1), now my printf() gives me just zeros as output. I want to have a float number as output but no matter what i type in as number1 and number2 i always get "0.000000".
Since i'm still working on my little program to verify the input before it is accepted, i have another question please.
I want to use the following code just to check the input.
#include <stdio.h>
#include <iostream>
#include <ctype.h>
int main()
{
int number1, number2;
int sum;
puts("Enter number 1 please:");
scanf_s("%d",&number1);
if (isdigit(number1))
{
puts("Enter number 2 please:");
scanf_s("%d",&number2);
}
else
{
puts("Your input is not correct. Enter a number please.");
}
std::cin.get();
std::cin.get();
/*
sum = number1 + number2;
printf("The average is %f\n", sum/2); */
return 0;
}
Well it doensn't work. I type in a digit and my response is "Your input is not...". I have used the search and found the following: Check if User Inputs a Letter or Number in C. Unfortunately the suggestions doesn't help me.
It's not ignored. When you type your second number, then hit enter, it puts your number plus a newline character in the input stream. scanf removes the number, but leaves the newline character alone. When you call cin.get(), since there's a character in the stream, it doesn't wait for your input.
PigBen has already given you a good explanation of where you err. However, I have some additonla points to make about your program which won't fit into a comment:
You are mixing C and C++ input. Why? What's wrong with std::cin >> number1?
When you change number1 to double, you need to remember to change the formatting string in scanf(), too, while with IO streams the compiler will figure out everything for you. With streams and C++' strings, containers and other data structures, it's much harder to do something that compiles, but invokes the dreaded Undefined Behavior at run-time.
Also note that you do not check whether your inputting operations succeed. What happens if I invoke your program, and instead of passing it numbers, I enter non-digits? Never use input from users, files, or other externals sources unverified.
With IO streams, the input operator >> returns (a reference to) the stream, and you can use streams as if they were booleans, so you can do
if(std::cin >> number1)
// input succeeded
or
if( !(std::cin >> number2) ) // note the negation operator !
// input error
to check.
Streams enter a bad state internally after input/output errors. Any further IO operations will fail on a stream that had encountered an error. Therefore, if you want, you can delay input verification until all input operations are done:
std::cout << "Enter number 1 please:";
std::cin >> number1;
std::cout << "Enter number 2 please:";
std::cin >> number2;
if(!std::cin)
// input error
However, remember to always verify input before you first use it.
Note that I didn't check the output for errors. That's because it's hard to imagine something going wrong with output to the console. (And what would you do about it? Print an error message?) However, if you write into a file, remember to check output, too. It's easy for a file operation to go wrong.
In answer to your modified question it is because you are using ints for division. Change int sum to float sum and everything should be fine.
To answer your modified question: you're using the %f printf() format with an int, and that doesn't work. If you want to print out floating-point, you need to pass a double. You could print out (double)sum / 2 or even sum / 2.0, both of which yield doubles. (No, a float doesn't work the same for a variadic function like printf().) As it is, you're passing what is probably a four-byte type and telling printf() to treat it as an eight-byte type of different format, so it's no wonder you're not getting the expected results.
Alternately, you could switch to C++ iostreams, which save you the problem of matching types and knowing the default promotions. You'd still get an integer from sum/2, and that would drop any one-half, but it would be the right result.