Recursive function printing in reverse order - c

(I'll start by noting this lab is low level 1st year programing, so high level stuff isn't usable right now for us)
I was given a lab to write a program in C that would accept a number between 1 and 36, six times, then print out those numbers as a bar graph, where the 'bar graph' is a number of # equal to the input number.
e.g. 5 would be:
So far I have this:
#include <stdio.h>
void graphCreate();
int main(void)
{
graphCreate();
}
void graphCreate()
{
static int chartLoop = 1;
int graphLength = 0;
int graphNumber = chartLoop;
while(graphLength > 36 || graphLength < 1)
{
printf("How long is chart %d?\t", graphNumber);
scanf("%d", &graphLength);
}
if(chartLoop < 6)
{
chartLoop++;
graphCreate();
}
printf("\n%d.\t%d|", graphNumber, graphLength);
while(graphLength > 0)
{
printf("#");
graphLength--;
}
}
And it does the output as expected... mostly:
How long is chart 1? 5
How long is chart 2? 10
How long is chart 3? 15
How long is chart 4? 20
How long is chart 5? 25
How long is chart 6? 30
6. 30|##############################
5. 25|#########################
4. 20|####################
3. 15|###############
2. 10|##########
1. 5|#####
However, I need the final outputs (the bars) in 1 -> 6 order, and it's reversed. What am I doing wrong that it's in reverse?

If using the recursive way to solve the problem is a requirement, you need to store the outputs and then print them in reverse order.
If recursive is not a requirement, you can loop 6 times to get and store the input numbers and print the bars in sequence.

Related

Valid VISA: 4222222222222 outputted as invalid

When running my program through cs50's submit50 check, everything works besides validating 4222222222222 as VISA (instead of INVALID) is output. When I print out the count variable before, then sometimes VISA is output. Any solutions would be much appreciated as I cannot seem to properly fix this.
INSTRUCTIONS: Write a program that prompts the user for a credit card number and then reports (via printf) whether it is a valid American Express, MasterCard, or Visa card number, per the definitions of each’s format herein. So that we can automate some tests of your code, we ask that your program’s last line of output be AMEX\n or MASTERCARD\n or VISA\n or INVALID\n, nothing more, nothing less
#include <stdio.h>
#include <cs50.h>
int main(void)
{
//get input from user
long CardNum = get_long("Input credit card number:");
bool nvalid = true;
//count number of digits
int count = 0;
long temp1num = CardNum;
while (temp1num > 0)
{
temp1num = temp1num / 10;
count++;
}
//printf("%i\n", count);
if (!(count == 13 || count == 15 || count == 16))
{
printf("INVALID\n");
}
else
{
.....
The problem arises in the beginning of the code so I only copied that part.
Mastercards always starts with either 5 or 2 and has a length of 16.
Visa cards always start with a 4 and can have a length of 13-16-19.
You are close. Try adding an additional condition for the supported lengths for VISA in your if statement it should solve your problem. Or, why not just check if the card length is either 13 - 19? It seems like it's failing because Visa supports different card lengths.
I have an awesome helper method that determines card types that's extremely handy but it's in C#.

Arrays and for loops trouble

I am doing an array exercise and I almost finished it.I have trouble finishing the last part.I create two arrays that store coursework points and exam points and then using a third array I calculate the module result(it is determined by both exam and coursework points). I got this part working and assuming I have 5 modules the output is 5 numbers.However I want to calculate my stage mark so if I have 5 modules I get their marks,add them together and then divide them by 5.Here is my problem I am using for loop because that is the only way it will work(as far as I know) so given that I already have my module result I use this for loop to calculate the stage result:
for(int i = 0; i < module_result.length; i++)
{
sum = sum + module_result[i];
System.out.println(sum/5);
}
I saw in this site similar question and I used the code in the answers.I can use enhanced for loop as well.
So given that coursework array={45,70,60,55,80} and exam array={83,72,45,25,89} my module results are 64,71,60,87. By using the above for loop I get anticipated outcome:
10
22
32
37
52
So I get my result. It is 52. But I don't want the rest of the numbers.
My question is how can I get just that number(52). I guess it is not possible by using for loop because it will inevitably is going to loop 5 times not one. I thought about using while loop but I don't see how I will get much different outcome.
I'm not sure if I totally understand the question, but I think this is what you're going for:
for(int i = 0; i < module_result.length; i++)
{
sum = sum + module_result[i];
}
System.out.println(sum/5);
All you have to do is simply move the println statement outside of the loop (if I understand the question correctly).
If you just want to print out the last number, just do a condition in the for loop that would print out at the index just before the length like this:
for (int i = 0; i < module_result.length; i++) {
if (i == module_result.length - 1) {
// print results
}
else {
// Do calculations
}
}
OK here is my code.
public int[] computeResult(int []courseWork,int[] examMarks ){
int[] module_result = new int[6];
for(int i=0;i<module_result.length;i++){//CALCULATE EACH MODULE
module_result[i]= ((courseWork[i] * cw[i]) + (examMarks[i] * (100 - cw[i]))) / 100;//THIS LINE IS SIMPLY A CONDITION HOW TO CALCULATE A MODULE YOU DON'T NEED TO KNOW WHAT IS HAPPENING INSIDE
}
int sum = 0;
for(int i = 0; i < module_result.length; i++)//USE THIS FOR LOOP TO ADD THE MODULES TOGETHER.
{
sum = sum + module_result[i];
// Add this extra line
// This allows you to only print out the value when you reach the end
if (i == module_result.length - 1) {
System.out.println(sum/6);
}
}
return module_result;
}
However here is what happens-the first for loop calculate the module results.Say they are as follows in the output console:
64
71
60
31
87
33
Next the second for loop is adding them together-first is 64,next loop at 71 to 64 and you get 135,next add to 135 the next module result 60 and so on until I get the total sum of all 6 modules which is just in this example 346 and then divide it by 6 to get my stage result.So I need in my output console just 346/6.Nothing else no zeros no nothing.
What my current code does is this-the second loop star running,it already knows my module results(they have been calculated) and so it starts- the first one is 64,divide it by 6 I get outcome 10,then the loop add 71 to 64 get 135 and divide it by 6 and so on until it reaches the number 346 and divide it by 6.So I get this output:
10
22
32
37
52
57
I don't need 10,22,32,37 and 52 they hold no meaning.I just need 57.What your solution will give me is this outcome:
0
0
0
0
0
57
It still gives unnecessary numbers.

Find the longest sequence of ascending numbers in unsorted array

Suppose the Array[10] = {10,6,11,9,-18,0,91,18,24,32}
The largest sequence will be 10,11,18,24,32 or -18,0,18,24,32
The solution to this is make another Array[10] which will store the number of sequences. Starting from the last element 32 which makes just 1 sequence i.e. the number itself.
24 makes 2
18 makes 3
91 makes 1
0 makes 4
-18 makes 5
9 makes 4
11 makes 4
6 makes 4
10 makes 5
The output should be either 5 starting from -18 or 5 starting from 10.
Can anyone help me with the code please.
more or less it will look like that, now you need to translate this to language what you are using
largestSequience = [];
temporaryArray = [];
for (element in array)
{
if (temporatySize not empty and temporarySize[lastElement]>=element)
{
if (temporaryArray.length > largestSequence.length) largestSequence = temporaryArray;
temporaryArray = [element]
}
temporaryArray.add(element)
}
What you want in C++. The running time is O(NlogN), in which N is the size of Array[]
#include<stdio.h>
#include<map>
using namespace std;
int main(void) {
int Array[10] = {10,6,11,9,-18,0,91,18,24,32};
int p[10],next[10];
int i,j,n=10;
map<int,int> places;
for(i=n;i>=0;i--){
map<int,int>::iterator ii=places.upper_bound(Array[i]);
if(ii==places.end()){ //no item on the right is larger
p[i]=1;
next[i]=-1;
}else{
next[i]=ii->second;
p[i]=p[ii->second]+1;
}
places[Array[i]]=i;
ii=places.find(Array[i]);
while(ii!=places.begin()){
ii--;
if(p[ii->second]<=p[i]){
places.erase(ii);
}else
break;
ii=places.find(Array[i]);
}
}
int longestI=0;
for(i=1;i<n;i++){
if(p[i]>p[longestI])
longestI=i;
}
for(i=longestI;i>=0;i=next[i]){
printf("%d\n",Array[i]);
}
return 0;
}

C Primer 5th - Task 14-6

A text file holds information about a softball team. Each line has data arranged as follows:
4 Jessie Joybat 5 2 1 1
The first item is the player's number, conveniently in the range 0–18. The second item is the player's first name, and the third is the player's last name. Each name is a single word. The next item is the player's official times at bat, followed by the number of hits, walks, and runs batted in (RBIs). The file may contain data for more than one game, so the same player may have more than one line of data, and there may be data for other players between those lines. Write a program that stores the data into an array of structures. The structure should have members to represent the first and last names, the at bats, hits, walks, and RBIs (runs batted in), and the batting average (to be calculated later). You can use the player number as an array index. The program should read to end-of-file, and it should keep cumulative totals for each player.
The world of baseball statistics is an involved one. For example, a walk or reaching base on an error doesn't count as an at-bat but could possibly produce an RBI. But all this program has to do is read and process the data file, as described next, without worrying about how realistic the data is.
The simplest way for the program to proceed is to initialize the structure contents to zeros, read the file data into temporary variables, and then add them to the contents of the corresponding structure. After the program has finished reading the file, it should then calculate the batting average for each player and store it in the corresponding structure member. The batting average is calculated by dividing the cumulative number of hits for a player by the cumulative number of at-bats; it should be a floating-point calculation. The program should then display the cumulative data for each player along with a line showing the combined statistics for the entire team.
team.txt (text file I'm working with):
4 Jessie Joybat 5 2 1 1
4 Jessie Joybat 7 3 5 3
7 Jack Donner 6 3 1 2
11 Martin Garder 4 3 2 1
15 Jaime Curtis 7 4 1 2
2 Curtis Michel 3 2 2 3
9 Gillan Morthim 9 6 6 7
12 Brett Tyler 8 7 4 3
8 Hans Gunner 7 7 2 3
14 Jessie James 11 2 3 4
12 Brett Tyler 4 3 1 3
Since I'm a beginner in C, either I misinterpreted the task from what was asked originally or it's unfairly complex (I believe the former is the case). I'm so lost that I can't think of the way how could I fill in by the criteria of index (player number) every piece of data, keep track of whether he has more than one game, calculate and fetch bat average and then print.
What I have so far is:
#define LGT 30
struct profile {
int pl_num;
char name[LGT];
char lname[LGT];
int atbat[LGT/3];
int hits[LGT/3];
int walks[LGT/3];
int runs[LGT/3];
float batavg;
};
//It's wrong obviously but it's a starting point
int main(void)
{
FILE *flx;
int i,jc,flow=0;
struct profile stat[LGT]={{0}};
if((flx=fopen("team.txt","r"))==NULL) {
fprintf(stderr,"Can't read file team!\n");
exit(1);
}
for( jc = 0; jc < 11; jc++) {
fscanf(flx,"%d",&i);
stat[i].pl_num=i;
fscanf(flx,"%s",&stat[i].name);
fscanf(flx,"%s",&stat[i].lname);
fscanf(flx,"%d",&stat[i].atbat[flow]);
fscanf(flx,"%d",&stat[i].hits[flow]);
fscanf(flx,"%d",&stat[i].walks[flow]);
fscanf(flx,"%d",&stat[i].runs[flow]);
flow++;
}
}
Advice 1: don't declare arrays like atbat[LGT/3].
Advice 2: Instead of multiple fscanf you could read the whole line in a shot.
Advice 3: Since the number of players is limited and the player number has a good range (0-18), using that player number as an index into the struct array is a good idea.
Advice 4: Since you need cumulative data for each player (no need to store his history points), then you don't need arrays of integers, just an integer to represent the total.
So:
#include <stdio.h>
#define PLAYERS_NO 19
typedef struct
{
char name[20+1];
char lastName[25+1];
int atbat;
int hits;
int walks;
int runs;
float batavg;
} Profile;
int main(int argc, char** argv)
{
Profile stats[PLAYERS_NO];
int i;
FILE* dataFile;
int playerNo;
Profile tmpProfile;
int games = 0;
for(i=0; i<PLAYERS_NO; ++i)
{
stats[i].name[0] = '\0';
stats[i].lastName[0] = '\0';
stats[i].atbat = 0;
stats[i].hits = 0;
stats[i].walks = 0;
stats[i].runs = 0;
}
dataFile = fopen("team.txt", "r");
if ( dataFile == NULL )
{
fprintf(stderr, "Can't read file team!\n");
exit(1);
}
for(i=0; i<PLAYERS_NO && !feof(dataFile); ++i, ++games)
{
fscanf(dataFile, "%d", &playerNo);
if ( playerNo <0 || playerNo > PLAYERS_NO )
{
fprintf(stderr, "Player number out of range\n");
continue;
}
fscanf(dataFile, "%s %s %d %d %d %d",
&tmpProfile.name,
&tmpProfile.lastName,
&tmpProfile.atbat,
&tmpProfile.hits,
&tmpProfile.walks,
&tmpProfile.runs);
printf("READ: %d %s %s %d %d %d %d\n",
playerNo,
tmpProfile.name,
tmpProfile.lastName,
tmpProfile.atbat,
tmpProfile.hits,
tmpProfile.walks,
tmpProfile.runs);
strcpy(stats[playerNo].name, tmpProfile.name);
strcpy(stats[playerNo].lastName, tmpProfile.lastName);
stats[playerNo].atbat += tmpProfile.atbat;
stats[playerNo].hits += tmpProfile.hits;
stats[playerNo].walks += tmpProfile.walks;
stats[playerNo].runs += tmpProfile.runs;
}
/* exercise: compute the average */
fclose(dataFile);
for(i=0; i<PLAYERS_NO; ++i)
{
if ( stats[i].name[0] == '\0' )
continue;
printf("%d %s %s %d %d %d %d\n",
i,
stats[i].name,
stats[i].lastName,
stats[i].atbat,
stats[i].hits,
stats[i].walks,
stats[i].runs);
}
return 0;
}
The first rule of programming: Divide and conquer.
So you need to identify individual operations. One such operation is "load one row of input", another is "look up a player". If you have some of those operations (more will come up as you go), you can start building your program:
while( more_input ) {
row = load_one_row()
player = find_player( row.name )
if( !player ) {
player = create_player( row.name )
add_player( player )
}
... do something with row and player ...
}
when you have that, you can start to write all the functions.
An important point here is to write test cases. Start with a simple input and test the code to read a row. Do you get the correct results?
If so, test the code to find/create players.
The test cases make sure that you can forget about code that already works.
Use a framework like Check for this.
If I were doing this, I'd start with a structure that only held one "set" of data, then create an array of those structs:
struct profile {
char name[NAMELEN];
char lname[NAMELEN];
int atbat;
int hits;
int walks;
int runs;
float batavg;
};
Since you're using the player's number as the index into an array, you don't need to store it into the structure too.
I think that will simplify the problem a little bit. You don't need to store multiple data items for a single player -- when you get a duplicate, you just ignore some of the new data (like the names, which should be identical) and sum up the others (e.g., at-bats, hits).

C array is displaying garbage data (memory problems?)

I'm making a driver for an 8x8 LED matrix that I'm driving from a computer's parallel port. It's meant to be a clock, inspired by a design I saw on Tokyoflash.
Part of the driver is an array of 3*5 number "sprites" that are drawn to the matrix. A coordinate of the matrix is assigned to a coordinate of the sprite and so forth, until the entire sprite is drawn on it. This process is repeated for the other digit with an offset. I have verified I have drawn the sprites correctly, and that the matrix is blank when it is written to. However, when I draw a number on the matrix I get errant 1s at Numpad6 for the left digit, Numpad1 for the right (Example with the left digit not drawn.)
I have a week of experience in C and this is baffling me.
Here is the driver in full if you want to compile it yourself. It is nowhere near finished.
//8x8 LED MATRIX DRIVER VER 0.1 APR062009
//CLOCK
//
// 01234567
// 0 BXXXXXXH B: Binary Mode Indicator
// 1 DXXXXXXM D: Decimal Mode Indicator
// 2 NNNNNNNN H: Hour Centric Display
// 3 LLLNNRRR M: Minute Centric Display
// 4 LNLNNRNR X: Secondary Information
// 5 LLLNNRRR L: Left Digit
// 6 LNLNNRNR R: Right digit
// 7 LLLNNRRR N: Not Used
#include <stdio.h>
#include <unistd.h>
//#include <math.h>
#include <time.h>
#include </usr/include/sys/io.h>
#define BASEPORT 0x378
int main()
{
//Increasing array parameters to seems to reduce glitching [best 10 5 3]
int Dig[10][5][3] = {0}; //ALPHANUMERIC ARRAY [NUMBER (0..9)][Y(0..4)][X(0..2)]
int Mat[7][7] = {0}; //[ROW][COL], Top L corner = [0][0]
int Aux1[7] = {0}; //Topmost Row
int Aux2[7] = {0}; //Second to Topmost Row
int Clk; //Clock
int Wait; //Delay; meant to eventually replace clock in its current state
int C1; //Counters
int C2;
int C3;
int L; //Left Digit
int R; //Right Digit
//break string left undefined atm
//ioperm (BASEPORT, 3, 1);
//outb(0, BASEPORT);
printf("Now running.\n");
//Set Variables
//3D DIGIT ARRAY [Num][Row][Col] (INITIALIZED BY INSTRUCTIONS)
//Dig array is meant to be read only once initialized
//3D arrays are unintuitive to declare so the numbers are
//"drawn" instead.
//Horizontals
//Some entries in the loop may have the variable in the middle
//coordinate instead of the 3rd and/or with a +2. This is to
//incorporate the incomplete columns some numbers have (eg "2") and
//saves coding additional loops.
for(C1=0; C1<=2; C1++){
Dig[0][0][C1]=1; Dig[0][4][C1]=1;
Dig[2][0][C1]=1; Dig[2][2][C1]=1; Dig[2][4][C1]=1; Dig[2][C1][2]=1; Dig[2][C1+2][0]=1;
Dig[3][0][C1]=1; Dig[3][2][C1]=1; Dig[3][4][C1]=1;
Dig[4][2][C1]=1; Dig[4][C1][0]=1;
Dig[5][0][C1]=1; Dig[5][2][C1]=1; Dig[5][4][C1]=1; Dig[5][C1][0]=1; Dig[5][C1+2][2]=1;
Dig[6][0][C1]=1; Dig[6][2][C1]=1; Dig[6][4][C1]=1; Dig[6][C1+2][2]=1;
Dig[7][0][C1]=1;
Dig[8][0][C1]=1; Dig[8][2][C1]=1; Dig[8][4][C1]=1;
Dig[9][0][C1]=1; Dig[9][2][C1]=1; Dig[9][4][C1]=1; Dig[9][C1][0]=1;
}
//Verticals
for(C1=0; C1<=4; C1++){
Dig[0][C1][0]=1; Dig[0][C1][2]=1;
Dig[1][C1][2]=1;
Dig[3][C1][2]=1;
Dig[4][C1][2]=1;
Dig[6][C1][0]=1;
Dig[7][C1][2]=1;
Dig[8][C1][0]=1; Dig[8][C1][2]=1;
Dig[9][C1][2]=1;
}
Clk=10000;
L=2; //Think about incorporating overflow protection for L,R
R=4;
//Print Left Digit to Matrix # (3, 0)
for(C1=0; C1<=4; C1++){ //For some reason produces column of 1s at numpad 6
for(C2=0; C2<=2; C2++){
Mat[C1+3][C2]=Dig[L][C1][C2];
printf("%d", Dig[L][C1][C2]); //Debug
}
printf(" %d %d %d\n", L, C1, C2); //Debug
}
//Print Right Digit to Matrix # (3, 5)
for(C1=0; C1<=4; C1++){ //For some reason produces column of 1s at numpad 1
for(C2=0; C2<=2; C2++){
Mat[C1+3][C2+5]=Dig[R][C1][C2];
}
}
//X Test Pattern
//for(C1=0; C1<=7; C1++){
// Mat[C1][C1]=5;
// Mat[7-C1][C1]=5;
//}
usleep(Clk);
//while(1){
//Breakfree [NOT FUNCTIONAL]
//Break_String=getch(); (Getch is not ANSI, need ncurses)
//if(Break_String != -1){
// if(Break_String = 27){
// break;
// }
//}
//Terminal Display
//for(C3=0; C3<=9; C3++){ //Debug Digit array [Successful, numbers draw correctly]
// for(C2=0; C2<=4; C2++){
// for(C1=0; C1<=2; C1++){
// printf("%d", Dig[C3][C2][C1]);
// }
// printf("\n");
// }
//printf("\n");
//usleep(1000000); //Debug
//}
usleep(3000000); //Debug
for(C1=0; C1<=7; C1++){ //Prints to terminal every second, when looping
for(C2=0; C2<=7; C2++){
printf("%d", Mat[C1][C2]);
}
printf("\n");
}
printf("\n");
//Hardware Display
for(C1=0; C1<=29; C1++){ //30 Hz
for(C3=0; C3<=7; C3++){ //COLUMN
//printf("%d %d \n", C3, C1); //Loop Debug
usleep(1000);
//CLOCK GROUND TO GO HERE, OUT STATUS
//for(C2=0; C2<=7; C2++){ //PX
//outb(Mat[C3][C2], BASEPORT);
//}
}
usleep(4*Clk);
}
//}
//ioperm(BASEPORT, 3, 0);
exit(0);
}
Also, I had to make my Sprite array bounds each one bigger than they should have been to make it work. I figure this is all some some memory snafu but I'm nowhere near that proficient in C to know what to do.
I would greatly appreciate any help.
I need to look through it more but one problem off the bat is that you're driving an 8x8 LED matrix but using a 7x7 matrix to hold the data. Declare your matrix as:
int Mat[8][8];
Bryan, I think you are just missing the fundamental understanding of how array indices work in C.
When you declare
int array[N]
you access the elements in a range of
array[0] ... array[N-1]
which gives you a total of N elements.
For example:
int array[4]
gives you
array[0]
array[1]
array[2]
array[3]
for a total of 4 elements.
When looping over this array, this is the convention that's almost always used:
for(i = 0; i < 4; i++)
I think that this issue is causing multiple problems in your code and if you go back over your arrays after understanding this you'll be able to fix the problems.
Bryan, I don't see the problem offhand, but what you're describing sounds like you are having an array indexing issue. (Rule of thumb, any time you think that there's something wrong with the computer causing your errors, you're mistaken.)
Two places new C programmers run into trouble with this is getting confused by 0 based indices -- an array of size 7 has indices from 0..6 -- and by not realizing that arrays are just laid out on top of one blob of memory, so an array that's [10][5][2] is really just one 100-cell piece of memory. If you make an indexing mistake, you can put things in what appear to be random places.
I'd go through the code and check what's where in smaller steps; what happens after one initialization, that sort of thing.

Resources