I'm new to C++, and right now I'm learning from the book called Accelerated C++. I finished the third chapter (vectors), and I came to this exercise:
"Write a program to count how many times each distinct word appears in its input."
After some thinking, I started working on it. I wanted to test the program, but std::cout wasn't working. I put cout << "test"; on a few places in my code to see where's the problem, and the conclusion is that it doesn't work inside the first for-loop. Don't recommend me to use maps to solve the problem, because I'm working on vectors. The variables aren't in English, so I'll translate some for you to know what's going on:
recenica - the sentence; rijec - a word; vel_vektora - size of the vector; duz_recenice - length of the sentence; br_ponavljanja - number of times a word appears in the sentence;
#include <vector>
#include <iostream>
#include <string>
using std::string; using std::vector;
using std::cin; using std::cout;
using std::endl;
int main()
{
string rijec;
vector<string> recenica;
while (cin >> rijec) recenica.push_back(rijec);
cout << endl;
typedef vector<string>::size_type vel_vektora;
vel_vektora duz_recenice = recenica.size();
cout << "test0, ";
for (int i = 0; i < duz_recenice - 1; ++i)
{
cout << "test, !";
int br_ponavljanja = 1;
for (int j = i + 1; j < duz_recenice; ++j)
{
cout << "test2, ";
if (recenica[i] == recenica[j])
{
cout << "test3, ";
++br_ponavljanja;
recenica.erase(recenica.begin() + j);
}
cout << "test4, ";
}
cout << recenica[i] << ": " << br_ponavljanja << endl;
}
cout << "test5, ";
getchar();
return 0;
}
What's the problem with the std::cout?
Add << flush to flush your output buffer (each place).
Or use << endl, which both adds newline and flushes.
There are problems with the code, especially for empty input, but that's what you're out to learn about, so I'll leave you to it! :-)
Cheers & hth.,
I'm afraid the language eludes me in terms of variable names, but this "Works for Me™".
Here is my output (First 3 lines input:)
ytreyert
tyryteter
gdhdfgdf
^Z
test0, test, !test2, test4, test2, test4, ytreyert: 1
test, !test2, test4, tyryteter: 1
test5,
You should definitely try flushing the cout buffers after printing (as per Alf's answer).
I notice that gdhdfgdf is not counted, this is because of this line:
for (int i = 0; i < duz_recenice - 1; ++i)
If you only give 1 input word, this loop will not run, as you do duz_recenice = recenica.size(); before looping.
Changing this line to
for (int i = 0; i < duz_recenice; ++i)
solves this problem.
Related
I've recently made a short a program about a new lesson that I've learned online about programming(which I'm a beginner in)C++, which I do every time I learn a new concept, to be in-depth with the concept of it and it's uses.(Its how I teach myself in programming). I used vector in my program and it solved my problem. But, it created a new one.
(You might have already seen this code)
#include <iostream>
#include <string>
#include <windows.h>
#include <vector>
using namespace std;
int main()
{
string LetterInput, LetterLoad, input;
string Words[5] = {"fire","eggs","roll","camera","lotion"};
vector <string> PossibleAnswers;
int Number,a = 0;
int Size,Num;
cout << "Lets play HANGMAN! " << endl;
Sleep(500);
cout << "Think of a word and type in the number" << endl;
cout << "of letters there are" << endl;
cin >> Size;
for (int i = 0; i <= Size; i++){
LetterLoad += "_";
}
Num = sizeof(Words)/sizeof(string);
for (int i = 0; i <= Num ; i++){
if ((unsigned)Size == Words[i].size()){
PossibleAnswers.push_back(Words[i]);
}
}
for (int i = 0;i <= Num;i++){
cout << PossibleAnswers[i] << endl;
}
cout << "Okay lets start" << endl;
Sleep(750);
while(a == 0)
{
cout << PossibleAnswers[0] << endl;
cout << PossibleAnswers[1] << endl;
cout << LetterLoad << endl;
cout << "Type in the position of the letter you want to guess" << endl;
cin >> Number;
cout << "What letter do you want to put?" << endl;
cin >> LetterInput;
LetterLoad[Number-1] = LetterInput[0];
for (size_t i = 0; i <= PossibleAnswers.size(); i++){
for (int n = 0; n <= Size; n++){
if (LetterInput[n] == PossibleAnswers[i][n]){
cout << "Got one" << endl;
}
}
}
}
return 0;
}
The program was able to take the right words. But, it stops working when it is about to reach the cout << "Okay lets start" << endl; and then everything below that line of code. I have heard that vectors require "memory allocation" from other people. Does that have something to with the program not running properly? and how do I fix it?
If the condition if ((unsigned)Size == Words[i].size()){ is not met for any number of cases, then you won't have pushed back enough strings. When that happens, you get a crash in the following for (int i = 0;i <= Num;i++){ loop because you're trying to access more element that you have. I would recommend doing this instead:
for (std::string &s : PossibleAnswers){
std::cout << s << std::endl;
}
You can also do a loop from 0 to PossibleAnswers.size(), like you do further below.
I have heard that vectors require "memory allocation" from other
people.
Nah, you must have misunderstood something. This was just an out of range error, I recommend to avoid those by always looping though vectors using range based for loops or by looping from 0 to vec.size().
You are asking questions about: I am trying to write an essay, but in fact, you don't know the alphabet. In my experience as a teacher, it's better to learn the programming basics first, rather than learning programming with libraries. This statement from you proves my opinion:
I have heard that vectors require "memory allocation" from other people.
Learn the different types of memory blocks. It is necessary for every programmer.
std::string
std::vector
These are linear data structures - don't use them, if you cannot implement them by yourself.
while (a==0) ...
You are allocating 4 bytes (in most architectures nowadays) for variable, which you don't even use it. Most of the compilers will change that code to:
while (true) ...
Because it is equivalent to it.
Everytime someone writes a magical number - a kitty around the world dies. Don't use magical numbers, save a kitty. Even in training sessions. You had time to write the description to the console, but you didn't make a const variable for the size of the array of strings.
It is good that you are motivated to learn programming. But if you are learning it wrong, there won't be any good results. My advice is to change the source, which you are learning from.
for(int i=0;i<50;i++,size++)
{
cin >> inputnum[i];
cout << size;
if(inputnum[i] == '.')
{
break;
}
}
The break breaks the input stream but the size keeps outputting.
The output of size is 012345678910111213...474849.
I tried putting size++ inside the loop but it made no difference. And size afterwards will be equal to 50, which means it went through the full loop.
I forgot to explain that I added the cout << size within the loop to debug/check why it outputted to 50 after the loop even if I only inputted 3 numbers.
I suspect that inputnum is an array of int (or some other numeric type). When you try to input '.', nothing actually goes into inputnum[i] - the cin >> inputnum[i] expression actually fails and puts cin into a failed state.
So, inputnum[i] is not changed when inputting a '.' character, and the break never gets executed.
Here's an slightly modified version of your code in a small, complete program that demonstrates using !cin.good() to break out of the input loop:
#include <iostream>
#include <ostream>
using namespace std;
int main()
{
int inputnum[50];
int size = 0;
for(int i=0;i<50;i++,size++)
{
cin >> inputnum[i];
if (!cin.good()) {
break;
}
}
cout << "size is " << size << endl;
cout << "And the results are:" << endl;
for (int i = 0; i < size; ++i) {
cout << "inputnum[" << i << "] == " << inputnum[i] << endl;
}
return 0;
}
This program will collect input into the inputnum[] array until it hits EOF or an invalid input.
What is inputnum ? Make sure t's a char[]!! with clang++ this compiles and works perfectly:
#include <iostream>
int main() {
int size = 0;
char inputnum[60];
for(int i=0;i<50;i++,size++) {
std::cin >> inputnum[i];
std::cout << size;
if(inputnum[i] == '.') {
break;
}
}
return 0;
}
(in my case with the following output:)
a
0a
1s
2d
3f
4g
5.
6Argento:Desktop marinos$
Your code seams OK as long as you're testing char against char in your loop and not something else.. Could it be that inputnum is some integral value ? if so, then your test clause will always evaluate to false unless inputnum matches the numerical value '.' is implicitly casted to..
EDIT
Apparently you are indeed trying to put char in a int[]. Try the following:
#include <iostream>
int main() {
using namespace std;
int size = 0;
int inputnum[50];
char inputchar[50];
for(int i=0;i<50;i++,size++) {
cin >> inputchar[i];
inputnum[i] = static_cast<int>(inputchar[i]); // or inputnum[i] = (int)inputchar[i];
cout << size << endl; // add a new line in the end
if(inputchar[i] == '.') break;
}
return 0;
}
Then again this is probably a lab assignment, in a real program I'd never code like this. Tat would depend on the requirements but I'd rather prefer using STL containers and algorithms or stringstreams. And if forced to work at a lower-level C-style, I'd try to figure out to what number '.' translates to (simply by int a = '.'; cout << a;`) and put that number directly in the test clause. Such code however might be simple but is also BAD in my opinion, it's unsafe, implementation specific and not really C++.
I have been making a program for a local... place, and it is a program that will calculate how much pizza will should be ordered. The problem, however, is not even the calculations, but rather with the files that keep log-in I.D. data.
#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <fstream>
using namespace std;
string logs[20];
void test(ifstream& IN, string logs[], ofstream& OUT);
void introduction();
int logging_in(string id, string logs[]);
void menu();
string newl = "\n";
string dnewl = "\n\n";
string tnewl = "\n\n\n";
string qnewl = "\n\n\n\n";
string pnewl = "\n\n\n\n\n";
int main()
{
ifstream IN;
ofstream OUT;
string id;
IN.open("loginn.dat");
cout << IN.is_open();
test(IN, logs, OUT);
string sup;
int receive = 0;
introduction();
return 0;
}
void test(ifstream& IN, string logs[], ofstream& OUT)
{
for (int x = 0; x < 20; x++)
{
IN >> logs[x];
}
IN.close();
OUT.open("loginn.dat");
for (int x = 0; x < 20; x++)
{
OUT << logs[x] << " " << "hue" << " ";
}
}
void introduction()
{
string cont;
cout << "Hello. I am the..." << dnewl
<< "Statistical" << newl << "Pizza" << newl
<< "Order" << newl << "Amount" << newl
<< "Diagnostic." << dnewl
<< "Otherwise known as Pizzahand. I will be assisting you to estimate the \namount of pizza that is to be ordered for <INSERT NAME>, as to \neliminate excessive ordering."
<< tnewl;
cout << "Press Enter to continue..." << newl;
cin.get();
}
In theory this is supposed to output the array "logs[]" before executing the rest of the code. This was the case when I had no functions in addition to the main function. As soon as I started to use my next function, "introduction()", the code for reading the text file here
for (int x = 0; x < 20; x++)
{
IN >> logs[x];
}
seemed to be knocked out of order. Instead of performing this task before anything else, it seems as if it does it at the very end of the program as I have tested by outputting its contents while the program was still reading "test()", with no luck. After the main function returns "0", however, I see that my program has outputted data into a test file, "loginns.dat", properly.
It is imperative for my program that this login ID data gets read in at the beginning as when the program transitions to logging in, the data is needed. Also, I have tried placing these arrays and for loops in different locations: in the log-in functions themselves, in the main function, and even another function that I created out of desperation.
I have searched for hours on how to solve this to no avail and experimented myself for plenty of hours more. Every step I took to attempt to fix this lead to more dead ends, or more questions. I am quite the beginner in the sense that this school-year is the first year of studying c++, and I am desperate for an expert opinion (or anyone knowledgeable) to help me face the right direction.
Thank you.
You just need to flush the stream after writing to it:
for (int x = 0; x < 20; x++)
{
OUT << logs[x] << " " << "hue" << " ";
}
OUT.flush();
The reason for this strange behaviour is that file streams don't necessarily write out to files immediately when you write to them. For efficiency reasons, they write the data to an internal memory buffer (an area of memory used by the stream), and then write the buffer contents out to the file all at once when the buffer is flushed. When an application finishes then all of its stream buffers are automatically flushed, which is why you are seeing that the file has been written to after your program finishes. However you can flush them earlier yourself, as shown above. It can also happen when the buffer gets full.
You can also trigger a flush using the endl token, which writes a newline character and flushes the buffer, like this:
for (int x = 0; x < 20; x++)
{
OUT << logs[x] << " " << "hue" << " " << endl;
}
This is part of a greater code for reading an input file word-for-word, then printing the words in reverse order. It uses a string array called words[] to store, word-by-word, the char strings from an input file earlier in the program:
//print to screen
for (int i = MAXSIZE; i >= 0; i--)
{
cout << words[i] << " ";
}
Test input file contents:
This is my test file. I hope this works.
Output is just "works. " repeating on and on.
Why is the i-- apparently never happening?
EDIT: Everything from my code. I'm on a bit of a time crunch here, to say the least. MAXSIZE=1024 part of lab prompt. Can't use vectors or reverse; seen that all over, but it's off limits for this lab. New to programming, so if you could refrain from being condescending, that'd be great. Just trying to get this to work. The reading input.txt and print to screen bit works fine. Output portion is utter fail and I don't know why. Can someone just tell me why instead of insulting me, thanks?
//Kristen Korz
//CIS 22A
//This program reads an input file and writes the words in reverse order to an output file.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//create and link input...
ifstream inputFile;
inputFile.open("input.txt");
//...and output files
ofstream outputFile;
outputFile.open("output.txt");
//error message for file open fail
if (inputFile.fail())
cout << "Error opening the file.\n";
//constant for max size
const int MAXSIZE = 1024;
//string array and temporary-use string
string words[MAXSIZE];
string str; //note: variables will be used for output loops too
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " ";
}
inputFile.close();
cout << endl;
//something wrong with for loop resulting in i apparently not updating
for (int i = MAXSIZE; (outputFile << str) && (i >= 0); --i)
{
words[i] = str;
//for showing in terminal if written correctly
cout << words[i] << " ";
}
outputFile.close();
cout << endl;
system("pause");
return 0;
}
For output with i also printed, my cout statements in the for-loops say:
cout << words[i] << " " << i << " ";
Giving terminal output:
This 0 is 1 my 2 test 3 file. 4 I 5 hope 6 this 7 works. 8
works. 1023 works. 1022 works. 1021 (lots of repeats of works. followed by decrementing numbers) works. 3 works. 2 works. 1 works. 0
Your output loop does:
words[i] = str;
for every iteration. str still holds the value of the last string you input, so this sets every member of words to be the same string. Since your last input string was "works", this explains why you output "works" every time.
It should work better if you just remove that line. Also, start from MAXSIZE - 1. The valid indices of the array are 0 through MAXSIZE-1. Your out-of-bounds access causes undefined behaviour, although apparently in this instance it had no effect.
However if your input only has 8 words as you suggest, then outputting 1024 words will give you a lot of blank space. Consider starting the output from where i got up to, instead of MAXSIZE - 1.
At the part marked as not working (the second for loop), str is being read from but it is never changed to anything else in that loop, so it repeats the last word. i is being updated, the problem is that str is not being updated.
The other issue is that you are trying to access an element past the end of the array, as WhozCraig and Velthune discussed in their answers. You need to properly figure out what you want to do with words in your second for loop. This is key. Also, you need to store where the array you read in ends.
Viewing WhozCraig's link, if you have:
const int MAXSIZE = 1024;
string words[MAXSIZE];
for (int i = MAXSIZE; i >= 0; i--) {
cout << words[i] << " ";
}
You have a string that from 0..1023.
Accessing words[1024] is potentially dangerous.
For iterate correctly your string do:
for (int i = MAXSIZE - 1; i >= 0; --i) {
cout << words[i] << " ";
}
By the way, when you fill words, add a control:
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)) {
if(str.size() <= MAXSIZE) {
words[i] = str;
}
}
update
Be sure that your string in file:
"This is my test file. I hope this works. "
doesn't end with a space. To be sure, test adding "EOF" to your string:
"This is my test file. I hope this works.EOF"
Other, do your loop in this way:
int i = 0;
while(inputFile.good() && i < MAXSIZE) {
std::string word << inputFile;
if(!word.empty())
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " ";
}
The problem why you get a lot of "works" here is:
After this piece of codes:
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " ";
}
inputFile.close();
cout << endl;
//str = "works";
The values of variable str is works.
After that, you set every elements in words by str. So every elements in the words now are the same value works.
for (int i = MAXSIZE; (outputFile << str) && (i >= 0); --i)
{
words[i] = str;//=="works"
//for showing in terminal if written correctly
cout << words[i] << " ";
}
outputFile.close();
cout << endl;
I'm new to programming (in general) and C++ (in particular). I'm learning vectors and am trying to write a simple program that:
allows the user to enter a vector of students' test scores
when the user types the sentinel (-1 in this case), the vector terminates
outputs a tally of the student's grades
Here's my code:
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
const int SENTINEL = -1;
vector<int> studentGrades = { 0 };
int myInput;
int main()
{
do
{
cout << "Please enter a student's grade: ";
cin >> myInput;
if (myInput < 1000)
{
studentGrades[myInput]++;
}
studentGrades.push_back(myInput);
} while (myInput != SENTINEL);
cout << "\n";
for (int i = 0; i < 1000; i++)
cout << i << " grade(s) of " << studentGrades[i] << endl;
return 0;
}
Two questions:
1) Can anyone provide guidance on why this code is only allowing me to enter one student's grade?
2) Is the for loop that compute the "tally" correct?
Thanks in advance for taking a look,
Ryan
* REVISED CODE *
# JCx - this is the revised code:
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
const int SENTINEL = -1;
vector<int> studentGrades = { 0 };
int myInput;
int main()
{
do
{
cout << "Please enter a student's grade (or -1 to QUIT): ";
cin >> myInput;
if (myInput < 1000)
{
studentGrades.at(myInput)++;
}
studentGrades.push_back(myInput);
} while (myInput != SENTINEL);
cout << "\n";
for (int i = 0; i < 1000; i++)
cout << i << " grade(s) of " << studentGrades.at(myInput) << endl;
return 0;
}
and, I'm seeing this error:
Unhandled exception at 0x7707C42D
Microsoft C++ exception: std::out_of_range at memory location 0x0035F890
There's more than one problem. The attempt to access studentGrades[-1] when the users enters your sentinel value, and the fact that the default vector only contains an entry for 0 and the use of push_back.
Let's just walk through some of the problems:
User runs program. User enters 100. studentGrades[100] is out of range. Undefined behaviour occurs as the vector only has one element.
User runs program, enters -1 studentGrades[-1] is out of range.
User runs program, enters 0. studentGrades[0] is in range, incremented to 1. studentGrades.push_back(1) adds an element to the vector studentGrades[1] is now also equal to 1.
As a great starting point, if you swap your subscript vector references for the vector at method as I've shown below you will get out-of-range errors which will help (a lot). The code below still needs work but at least you'll have run-time errors instead of odd behaviour.
int main()
{
do
{
cout << "Please enter a student's grade: ";
cin >> myInput;
if (myInput < 1000)
{
studentGrades.at(myInput)++;
}
studentGrades.push_back(myInput);
} while (myInput != SENTINEL);
cout << "\n";
for (int i = 0; i < 1000; i++)
cout << i << " grade(s) of " << studentGrades.at(myInput) << endl;
return 0;
}
I think if I was implementing this I'd be using std::map instead of a vector. It would let you have a studentGrade[1000] without having to allocate memory for studentGrade[0] to [999] first.
However as you are learning about std::vector check out vector::resize to set the vector big enough for the required elements, std::vector::size to find out whether you need to increase the size. You could then ditch the push_back.
References
vector::at http://www.cplusplus.com/reference/vector/vector/at/
vector::size http://www.cplusplus.com/reference/vector/vector/size/