How do you put a letter triangle in a file? - c++

So this is for some homework I am working on.
I've been working on this for days now. I need to print a letter triangle,
example
a
aa
aaa
to a file I create in the code. I have gotten the triangle part down using a for loop but cannot figure out how to get it into a file. here is what I have so far.
#include <iostream>
#include <fstream>
using namespace std;
char loop()
{ for (int i = 1; i <=15; i++){
for (int j = 1; j <= i; j++){
cout << "a";
}
cout << endl;
}
}
int main()
{
ofstream week2 ("week2assignment.txt");
if (week2.is_open()){
char result = loop();
{
week2 << loop() + "\n";
}
}
week2.close();
else cout << "file wasnt created";
return 0;
}
This is my first post on here and I am in my second week of learning C++ so any help would be appreciated immensely. Thank you all in advance.

You just need to replace cout with week2 everywhere, since cout is the terminal and week2 is your file.
Given the current structure of your code, where you write to cout in a function, you'll need to pass week2 as an argument to that function to use it there.

First of all, don't build a habit of using using namespace std
std::endl will put a linebreak, but it will also flush your stream. Put easily, outputting something is a really costly (=takes a long time) action in regard to other actions. To account for this, streams are buffered and once the buffer is full it will be flushed automatically. When you use std::endl the buffer might be flushed prematurely and this will tank performance. This is of course not really an issue in this small exercise, but I think it's still good to know. You can use \n instead. Although it might not look like it, it will provide a platform independend linebreak and should virtually always be used instead of std::endl.
Then consider what your function loop should do. Right now, you said it has return type char but it's not returning something. Therefore you should correct this and specify that this function is not returning anything, but just performing an action, hence return type void.
As suggested by John Zwinck, if you pass the stream as an argument, your function becomes more powerful and works with any kind of outgoing stream (i.e. std::ostream).
We can make the function even more generic, but I'll leave it to you to understand the code (if not, feel free to post a comment for clarification). Please note also, that loop is not a descriptive name. I have no idea what loop does. Always give your functions a name that makes it clear what they are doing.
#include <iostream>
#include <fstream>
void print_letter_triangle(std::ostream& out, char c = 'a', int count = 15)
{
for( int i = 0; i < count; i++ ){
for( int j = 0; j < i; j++ )
{
out << c;
}
out << '\n';
}
}
int main()
{
// for testing purposes
print_letter_triangle(std::cout);
print_letter_triangle(std::cout, 'b');
print_letter_triangle(std::cout, 'c', 7);
std::ofstream week2("week2assignment.txt");
if( week2.is_open() )
{
print_letter_triangle(week2);
week2.close();
}
else
{
std::cout << "Error: File wasn't created.\n";
}
return 0;
}
Lastly: Try to build an early habit of how you want to format your code, positions of curly braces, spaces around operators. Right now it was a little bit inconsistent (which might as well have been caused by putting it on StackOverflow).
There are a couple more nitpicks one can offer (for example, I changed the loop to start from 0 and used the < instead of the <= operator, you can convince yourself that this does not change the number of loop iterations. However, it is common in programming languages to start from 0 (as counter-intuitive as that might be at first). Finally, since negative counting values do not make sense in this loop, one might change int to unsigned int, but I felt that might have been a little too much. Feel free to do so on your own, if you wish).

I suggest you use this code:
#include <iostream>
#include <fstream>
using namespace std;
const char* loop()
{ for (int i = 1; i <=15; i++){
for (int j = 1; j <= i; j++){
return "a";
}
return "\n";
}
}
int main()
{
ofstream week2 ("week2assignment.txt");
week2 << loop() << "\n";
return 0;
}
You must return a value from your loop() function.

Related

i'm getting an error in for loop and if statements:

#include <iostream>
using namespace std;
int main() {
int i,t,km,sum=0;
std::cin >> t;
for( i=0;i<t;i++){
cin>>km;
}
for(i=0;i<t;i++){
if(km>300){
sum=km*10;
cout<<sum;
}
else if(km<=300){
sum=300*10;
cout<<sum;
}
else{
cout<<"wrong!";
}
}
return 0;
}
i'm not getting what's wrong with the code, when i'm entering number of test cases(t) as 1 it's running. but afterwars it's only executing the else block.
We'll start with a mini code review:
#include <iostream>
using namespace std; // Bad practice; avoid
/* Generally poor formatting throughout */
int main() {
int i,t,km,sum=0; // Prefer each variable declared on its own line; i is unnecessary
std::cin >> t;
for( i=0;i<t;i++){ // Overwrites `km` t times
cin>>km;
}
for(i=0;i<t;i++){ // Only does work on the last number entered
if(km>300){
sum=km*10; // You likely want to be adding on, not overwriting
cout<<sum;
}
else if(km<=300){
sum=300*10;
cout<<sum;
}
else{ // Impossible to reach given your two other conditions
cout<<"wrong!";
}
}
return 0;
}
The comments have spelled a lot of this out. You overwrite km t times. You only end up running your check on the last value of km that was entered, t times. You likely want to process t inputs, and the way to do this is with a single loop instead of the two that you have.
You overwrite your sum instead of (I assume) adding on to it. You wanted to sum += and not just sum =. The computer is actually pretty dumb, but it's very good at doing exactly what you told it to do. It is incapable of guessing your intent. That's supposed to be comforting, but it can be interpreted many ways.
I would also recommend taking the time to come up with better variable names. It looks like you're doing some calculations, possibly having to do with legs of a trip, but it's unclear. Making your code harder to read by choosing horrible names like t won't allow others to easily help you, and it will make your own code seem like a foreign language after just a couple days. Help yourself and others out by choosing good names.
As I stated, you might have been able to figure this out on your own if the code was indented properly. Consistent and proper formatting is extremely important for readability. If you don't want to be bothered doing it yourself, tools like clang-format exist.
Here's your code again, touched up a bit. I took a couple guesses at intended behavior.
#include <iostream>
int main() {
int t;
int km;
int sum = 0;
std::cin >> t;
for (int i = 0; i < t; i++) {
std::cin >> km;
if (km > 300) {
sum += km * 10;
std::cout << sum << '\n';
} else if (km <= 300 && km > 0) {
sum += 300 * 10;
std::cout << sum << '\n';
} else {
std::cout << "wrong!";
}
}
return 0;
}

2d array comparing with char

I have an array that reads data from a file, the data is binary digits such as 010011001001 and many others so the data are strings which I read in to my 2d array but I am stuck on comparing each value of the array to 0. Any help would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string myArr[5000][12];
int i = 0, zeroCount = 0, oneCount = 0;
ifstream inFile;
inFile.open("Day3.txt");
while(!inFile.eof())
{
for(int i = 0; i < 5000; i++)
{
for(int j = 0; j < 12; j++)
{
inFile >> myArr[i][j];
j++;
}
i++;
}
}
for(int j = 0; j < 12; j++)
{
for(int i = 0; i < 5000; i++)
{
if(myArr[i][j].compare("0") == 0)
{
zeroCount++;
}
else
{
oneCount++;
}
i++;
}
if(zeroCount > oneCount)
{
cout << "Gamma is zero for column " << i << endl;
}
else
{
cout << "Gamma is One for column " << i << endl;
}
j++;
}
}
some input from the text file:
010110011101
101100111000
100100000011
111000010001
001100010011
010000111100
Thank you for editing you question and providing more information. Now, we can help you. You have 2 major misunderstandings.
How does a for loop work?
What is a std::string in C++
Let us start with the for loop. You find an explanation in the CPP reference here. Or, you could look also at the tutorial shown here.
The for loop has basically 3 parts: for (part1; part2; part3). All are optional, you can use them, but no need to use them.
part1 is the init-statement. Here you can declare/define/initialize a variable. In your case it is int i = 0. You define a variable of data type int and initialize it with a value of 0
part2 is the condition. The loop will run, until the condition becomes false. The condition will be check at the beginning of the loop.
part3 is the so called iteration-expression. The term is a little bit misguiding. It is basically a statement that is executed at the end of the loop, before the next loop run will be executed and before the condition is checked again.
In Pseudo code it is something like this:
{
init-statement
while ( condition ) {
statement
iteration-expression ;
}
}
which means for the part of your code for(int j = 0; j < 12; j++)
{
int j = 0; // init-statement
while ( j < 12 ) { // while ( condition ) {
inFile >> myArr[i][j]; // Your loop statements
j++; // Your loop statements PROBLEM
j++; // iteration-expression from the for loop
}
}
And now you see the problem. You unfortunately increment 'j' twice. You do not need to do that. The last part3 of the for loop does this for you already.
So please delete the duplicated increment statements.
Next, the std::string
A string is, as its names says, a string of characters, or in the context of programming languages, an array of characters.
In C we used to write actually char[42] = "abc";. So using really a array of characters. The problem was always the fixed length of such a string. Here for example 42. In such an array you could store only 41 characters. If the string would be longer, then it could not work.
The inventors of C++ solved this problem. They created a dynamic character array, an array that can grow, if needed. They called this thing std::string. It does not have a predefined length. It will grow as needed.
Therefore, writing string myArr[5000][12]; shows that you did not fully understand this concept. You do not need [12], becuase the string can hold the 12 characters already. So, you can delete it. They characters will implicitely be there. And if you write inFile >> myString then the extractor operator >> will read characters from the stream until the next space and then store it in your myString variable, regardless how long the string is.
Please read this tutorial about strings.
That is a big advantage over the C-Style strings.
Then your code could look like:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string myArr[5000];
int zeroCount = 0, oneCount = 0;
ifstream inFile;
inFile.open("Day3.txt");
while (!inFile.eof())
{
for (int i = 0; i < 5000; i++)
{
inFile >> myArr[i];
}
}
for (int i = 0; i < 5000; i++)
{
zeroCount = 0; oneCount = 0;
for (int j = 0; j < 12; j++)
{
if (myArr[i][j]== '0')
{
zeroCount++;
}
else
{
oneCount++;
}
}
if (zeroCount > oneCount)
{
cout << "Gamma is zero for column " << i << endl;
}
else
{
cout << "Gamma is One for column " << i << endl;
}
}
}
But there is more. You use the magic number 5000 for your array of strings. This you do, because you think that 5000 is always big enough to hold all strings. But what, if not? If you have more than 5000 strings in your source file, then your code will crash.
Similar to the string problem for character arrays, we have also a array for any kind of data in C++, that can dynamically grow as needed. It is called std::vector and you can read about it here. A tutorial can be found here.
With that you can get rid of any C-Style array at all. But please continue to study the language C++ further and you will understand more and more.
Ther are more subtle problems in your code like while(!inFile.eof()), but this should be solved later.
I hope I could help

why is the sort() changing my input array?

i am stuck on a problem where, after taking input of an array and sorting it and not doing any operation on it at all, the output shows a different array?
#include <bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
int t;
cin>>t;
while(t--){
int n;
cin>>n;
long long int c[n],h[n],a[n];
for(int i=0;i<n;i++){
cin>>c[i];
}
for(int i=0;i<n;i++){
cin>>h[i];
}
sort(h,h+n);
for(int i=0;i<n;i++){
a[i]=0;
}
int i=0;
int begin=(i+1)-c[i];
int end = (i+1)+c[i];
int j=begin;
while(i<n){
a[j-1]++;
j++;
if(j>end){
i++;
begin=(i+1)-c[i];
end= (i+1)+c[i];
j=begin;
}
}
sort(a,a+n);
for(int i=0;i<n;i++){
cout<<h[i]<<" ";
}
}
return 0;
}
input for h[]={8,8,8,8,8}..n=5
output h[]={10,10,9,9,8}
Here is a version of your code written in reasonably decent C++. I didn't touch the loop in the middle because I have no clue what it's doing. You're using obscure variable names and no comments and doing all kinds of bizarre things with indexes and mixing them up with user input.
Now, reading indexes from user input and using them isn't bad, though in a real program you'd want to be doing lots of bounds checking on that input to make sure people weren't feeding you bad data. But doing all that stuff with such poorly named variables with no explanation is going to leave anybody looking at it scratching their head. Don't do that.
Also, avoid the use of begin and end as variable names, especially if they hold indexes. In most cases it will confuse things terribly as begin and end are important identifiers in the standard library and always refer to iterators, which are sort of like indexes, but most definitely not indexes, adding greatly to the confusion. beginidx and endidx could be acceptable substitutes in this case.
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
using ::std::vector;
using ::std::sort;
using ::std::copy_n;
using ::std::copy;
using ::std::fill;
using ::std::istream_iterator;
using ::std::ostream_iterator;
using ::std::cin;
using ::std::cout;
int main() {
// your code goes here
using vec_el_t = long long int;
int t;
cin >> t;
while (t--) {
int const n = []() { int n; cin >> n; return n; }();
vector<vec_el_t> c{n}, h{n}, a{n};
copy_n(istream_iterator<vec_el_t>{cin}, n, c.begin());
copy_n(istream_iterator<vec_el_t>{cin}, n, h.begin());
// Suggested debugging code:
// cout << "h before sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
sort(h.begin(), h.end());
// Suggested debugging code:
// cout << "h after sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
fill(a.begin(), a.end(), 0);
// Weird, unexplained algorithm begins here
int i = 0;
int begin = (i + 1) - c[i];
int end = (i + 1) + c[i];
int j = begin;
while (i < n) {
a[j - 1]++;
j++;
if (j > end){
i++;
begin = (i + 1) - c[i];
end = (i + 1) + c[i];
j = begin;
}
}
// Weird unexplained algorithm ends here
sort(a.begin(), a.end());
copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
}
return 0;
}
Changes made... Use vector not a variable length array, which isn't valid C++ anyway and will only work in g++ and clang. Don't use explicit loops if there is an algorithm that will do the job. Try to make as many things const as you can so you can make sure that the compiler catches it if you try to change things you didn't mean to change. Avoid using std; and if you want to import names from ::std import exactly the ones you need. Don't use compiler or library implementation specific header files and use the ones from the standard instead (i.e. no bits/stdc++.h).
As for your problem, I have no idea. I suspect that the index manipulation combined with looping isn't doing what you expect. If you print out the arrays before and after sorting, you will discover that sort only alters order, and not content.
As a general rule, always suspect your own code first and make absolutely sure it's correct. And if you really think it's the library code, prove it beyond a shadow of a doubt before coming here to ask why the library isn't doing what it says it does.
The complicated code I didn't touch looks rife with opportunities for out-of-bounds access, and that results in undefined behavior, which means your program might do absolutely anything in that case. You might change uses of operator [] with calls to the at function (one of the many perks of using vector) instead. That way, attempts at out-of-bounds access will throw an exception.
Within these lines you are accessing a outside its limits:
int i=0;
int begin=(i+1)-c[i]; // begin = 1 - c[0]; <<-- this could be arbitrarily small!
int end = (i+1)+c[i]; // unrelated
int j=begin; // also equal to 1-c[0]
while(i<n){
a[j-1]++; // increment a[-c[0]] which is UB unless c[0]==0
This means undefined behavior (UB), i.e., it could do nothing, it could segfault, or (what apparently happened in your case) access elements of an adjacent data structure.

control reaches end of non-void function

This code should perfectly run and give the right result but it doesn't. I used the debugger and everything is ok. c.i and c.j have the right values before the function returns. I make sure there is always a path between start and end so that's not the problem. The path and vis array are filled with the right values too. So the only problem is when it returns. It gives random, big numbers. It works only when i put a return statement at the end of the function. But i can make a function with only one return statement placed in if clause and it works. Is there some kind of rule, so there must be any kind of return statement at the end of a function? To test it, i enter 3x3 two dimensional array with 1's. Any solutions?
Edit: I run it on ideone and it works without return statement at the end of the function. Also a friend of mine tested on his computer it also worked. I use codeblocks on windows 7. What can the problem be?
link to ideone
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;
struct crd {
int i,j;
};
bool vis[50][50];
int map[50][50];
int path[50][50];
int di[4] = {1,-1,0,0};
int dj[4] = {0,0,1,-1};
int bfs(crd start, crd end, int n, int m)
{
queue<crd> q;
crd t,c;
q.push(start);
vis[start.i][start.j] = 1;
path[start.i][start.j] = 0;
while (!q.empty()) {
t = q.front();
q.pop();
for (int i=0; i<4; i++) {
c.i = t.i + di[i];
c.j = t.j + dj[i];
if (c.i >= 0 && c.j >= 0 && c.i < n && c.j < m) {
if (map[c.i][c.j] != -1 && vis[c.i][c.j] != 1) {
q.push(c);
vis[c.i][c.j] = 1;
path[c.i][c.j] = path[t.i][t.j] + 1;
if (c.i == end.i && c.j == end.j)
return path[end.i][end.j];
}
}
}
}
// if i put this: return path[end.i][end.j]; it works
}
int main()
{
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++)
cin >> map[i][j];
}
crd s,e;
s.i = s.j = 0;
e.i = e.j = 2;
int sp = bfs(s,e,3,3);
cout << sp << endl;
return 0;
}
The compiler is pretty basic - it has no way of knowing your function will always reach the return inside your if inside the if inside the other if inside the for loop inside the while loop. So it warns you that you might not return anything from the function. The easiest fix would be to return the appropriate value at the end and only break outside the loops at the point you now have your return.
If you declare a function with non-void return type, this functions should return a value. If execution reaches the end of the function, and there is no return <value>; statement there, the result of function would be undefined.
When you "fall off the edge" of a function, the return value is undefined (meaning it could be anything, including values that aren't valid for the type you were returning).
So, every function should have a return at the end. Or some way to say "I didn't expect to get here, stop now" if that's the appropriate thing (say, for example you were looking for a someting in a list, and you don't expect to NOT find it, then having something to print "I couldn't find , expected to. Stopping..." and then exit the program).
I'm not entirely sure what is the RIGHT thing to return if you don't find end.i and end.j, but you certainly should return SOMETHING.
You have two bugs.
It is fine to have no return statement at the end of a function that returns a value, but only if the end of the function can never be reached. In this case, your search algorithm could conceivably fail to find a path (depending of course on the contents of the input data), and then the outer loop will terminate without the return statement ever having been executed. You must have another return statement after the while loop, to account for this possibility. It should not return path[end.i][end.j]; Instead it should return a special value that means the search failed. This is the bug which the compiler has detected and is telling you about.
There is an error somewhere in your breadth-first search logic which is causing paths not to be found even when they do exist. You need to debug that yourself.

C++ Need help iterating through cards, locating pairs and flush's

The program below is suppose to be looking for "Pair's" and "Flush's". It iterates through 10 Trials consisting of 10,000 hands, each hand consisting of 5 cards. The result should (of course it doesn't right now) consist of 10 rows reflecting unique results for each trial. I am stuck...thanks in advance.
#include "card.h"
#include "deck.h"
#include "game1.h"
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
int main() {
int pair = 0;
int flush = 0;
int h; //Hands
int c; //Cards
int t; //Trials
const int MAXTRIALS = 10;
const int MAXHANDS = 10000;
const int MAXCARDS = 5;
const int MAXSHUFFLE = 100;
Deck myDeck;
Card myCards[MAXCARDS];
myDeck.shuffle(MAXSHUFFLE); //How often would you shuffle?
srand((unsigned)time(NULL)); //Randon initilizer
for (t = 0 ; t < MAXTRIALS; ++t) //Outermost loop for the Trials
{
for (h = 0; h < MAXHANDS; ++h) //InnerLoop for Hands
{
myCards[0] = myDeck.getCard();
for (c = 1; c < MAXCARDS; ++c) //InnerMost Loop for Cards
{
myCards[c] = myDeck.getCard();
if (myCards[c].getValue() == myCards[0].getValue())
{
pair++;
}
if (myCards[c].getSuit() == myCards[0].getSuit())
{
flush++;
}
myDeck.addCard(myCards[c]);
c++;
}
myDeck.shuffle(MAXSHUFFLE);
h++;
}
cout << "pairs: " << pair << "\tflushes: " << flush << endl;
}
cin.get();
}
If I understand your question, "the result should ... consist of 10 rows reflecting unique results for each trial", the problem is simply that you don't reset the pair and flush counter variables between each trial. Something like the following where the 'trial' for loop starts should do the trick:
for (t = 0 ; t < MAXTRIALS; ++t)
{
pair = 0;
flush = 0;
// the remainder as is...
With a lot of guessing what exactly should happen...
1) Is it made sure, that myDeck.getCard() does not draw the same card twice? Or does it not matter for your task?
2) What is myDeck.addCard(myCards[c]) exactly doing?
3) Why do you increment the loop counter a second time? c++
If this is made sure, you are only comparing against the first card. If you want to compare a complete hand, your code should look something like this:
// first draw the complete hand
for(int card = 0; card < MAX_CARDS; ++card)
{
myCards[card] = myDeck.getCard();
}
// now that we have the full hand, compare each card against each other card
for(int start = 0; start < MAXCARDS-1; ++start)
{
for(int compare = start+1; compare < MAXCARDS; ++compare)
{
if (myCards[start].getValue() == myCards[compare].getValue())
{
pair++
}
// do similar for flushs
}
}
I didn't test this code, but this should give you a start.
This would count every pair, even if there are two pairs in one hand. It would need additional code to break out of the loops, if a pair was found.
btw: looks like homework to me...
The c++ and h++ are a little bit suspicious (did you really mean to only touch every other item)? But without more information as to what you are observing, it would be hard to give a definitive answer.
Also, some minor stylistic recommendations regarding your code:
I recommend putting off the declaration of "h", "c", and "t" to the first point at which they are needed, so I would declare them in the for-loop (e.g. "for (int h = 0; h < ... ; h++)").
It is more idiomatic to use static_cast in C++ code (i.e. srand(static_cast(time(NULL)))), than it is to use a C-style cast, however both forms are correct.