Flowcharts in C — practice with the band’s streak, a palindrome number and the week’s average (flowchart first, code second)
My activity band congratulated me one Tuesday on a «3-day streak» and I wanted to check it with my own program. My first version went through the weeks separately, with one loop for each, and reset the streak to 0 at the start of the second week. Result: I got a streak of 2. The band was right: Sunday, Monday and Tuesday are consecutive days, even if they fall in different weeks. The bug was not in the code but in the flowchart I never drew: had I drawn it, I would have seen that the «streak = 0» at the change of week did not come from any diamond.
In the flowcharts theory we saw the symbols, the two-diamond template and where i = i + 1 goes. Here we use it in three medium-level programs, always in the same order: flowchart first, C second. We use the band data from the theory, with its weak days and its ties, because that is exactly where easy flowcharts break: a streak that crosses the change of week, a number read as text and an average that forces you to go through the array twice.
Table of Contents
Before you start
It helps to be clear about:
- The five symbols and the diamond rules (two exits, Yes and No, and the branches meet again).
- How a
foris taken apart in a flowchart: initialisation before, condition in the diamond,i = i + 1at the end. - The two-diamond template (loop on top,
ifbelow). - That
&&only looks at the second condition if the first is true.
If any of these sounds shaky, go over the theory before carrying on.
Programs 2 and 3 read from the keyboard with scanf. Compile them with gcc -Wall program.c -o program and run them with ./program; type the data when asked and press Enter. In the article you will see the output together with what was typed.
Program 1: the longest streak
The band stores the steps of two weeks (14 days). We want the longest streak of consecutive days reaching the 10,000-step goal and the day it starts on. What makes it tricky: a streak can cross the change of week, there may be two streaks of the same length, and you have to remember where the best one started once it has already ended.
The idea
We go through the 14 days in a single loop (so Sunday and the following Monday are consecutive). We keep three variables: streak (how many days in a row up to today), best (the longest streak seen) and best_start (where it started). For each day:
- If it reaches the goal, the streak goes up and, if it beats the best, we save it.
- If it does not, the streak goes back to 0.
It is an if / else with another if inside the Yes branch. This is how it looks drawn:
Before programming, think about where streak > best? is asked. It only makes sense on days that add to the streak: that is why it goes inside the Yes, not after the meeting point.
The code
#include <stdio.h>
#define N 14 // two weeks of data
#define GOAL 10000
int main(void) {
int steps[N] = {6420, 11250, 8900, 12030, 4100, 9870, 10500,
10200, 11800, 7300, 10050, 12400, 13100, 9100};
const char *days[7] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
int streak = 0; // days in a row reaching the goal (up to today)
int best = 0; // the longest streak seen so far
int best_start = 0; // position of the first day of that streak
int i;
for (i = 0; i < N; i++) {
if (steps[i] >= GOAL) {
streak = streak + 1; // the streak goes on
if (streak > best) { // > and not >=: in a tie the first streak wins
best = streak;
best_start = i - streak + 1; // today's position less the length of the streak
}
} else {
streak = 0; // a weak day breaks the streak
}
// i % 7 gives the day of the week (0 = Monday) and i / 7 + 1, the week
printf("Week %d, %s: %d steps -> streak %d\n", i / 7 + 1, days[i % 7], steps[i], streak);
}
printf("Longest streak: %d days, starts on %s of week %d\n",
best, days[best_start % 7], best_start / 7 + 1);
return 0;
}
The hard part is the heart of the loop. Let’s look at it on its own:
if (steps[i] >= GOAL) {
streak = streak + 1; // the streak goes on
if (streak > best) { // > and not >=: in a tie the first streak wins
best = streak;
best_start = i - streak + 1; // today's position less the length of the streak
}
} else {
streak = 0; // a weak day breaks the streak
}
streak = streak + 1comes first: today counts for the streak before comparing it with the best.if (streak > best)uses>and not>=. With>=, a streak that ties with the best would replace it, and the program would say it starts with the latest one. With>, in a tie the first one wins.best_start = i - streak + 1: if today is dayiand we havestreakdays in a row, the first one wasstreak − 1days earlier. For example, ati = 8with a streak of 3: 8 − 3 + 1 = 6.- The
elsesets the streak to 0. It is the only way the streak breaks: a weak day, never a change of week.
The printf line does two integer calculations: i % 7 gives the day of the week (8 % 7 = 1, Tuesday) and i / 7 + 1 the week (8 / 7 + 1 = 2).
Output
Week 1, Monday: 6420 steps -> streak 0 Week 1, Tuesday: 11250 steps -> streak 1 Week 1, Wednesday: 8900 steps -> streak 0 Week 1, Thursday: 12030 steps -> streak 1 Week 1, Friday: 4100 steps -> streak 0 Week 1, Saturday: 9870 steps -> streak 0 Week 1, Sunday: 10500 steps -> streak 1 Week 2, Monday: 10200 steps -> streak 2 Week 2, Tuesday: 11800 steps -> streak 3 Week 2, Wednesday: 7300 steps -> streak 0 Week 2, Thursday: 10050 steps -> streak 1 Week 2, Friday: 12400 steps -> streak 2 Week 2, Saturday: 13100 steps -> streak 3 Week 2, Sunday: 9100 steps -> streak 0 Longest streak: 3 days, starts on Sunday of week 1
Let’s check it by hand with a table of the days that decide the result:
| i | Day | steps | >= 10000? | streak | streak > best? | best | best_start |
|---|---|---|---|---|---|---|---|
| 1 | Tuesday W1 | 11250 | Yes | 1 | 1 > 0 Yes | 1 | 1 |
| 6 | Sunday W1 | 10500 | Yes | 1 | 1 > 1 No | 1 | 1 |
| 7 | Monday W2 | 10200 | Yes | 2 | 2 > 1 Yes | 2 | 7 − 2 + 1 = 6 |
| 8 | Tuesday W2 | 11800 | Yes | 3 | 3 > 2 Yes | 3 | 8 − 3 + 1 = 6 |
| 9 | Wednesday W2 | 7300 | No | 0 | (not asked) | 3 | 6 |
| 12 | Saturday W2 | 13100 | Yes | 3 | 3 > 3 No | 3 | 6 |
Position 6 is Sunday of week 1 (6 % 7 = 6, 6 / 7 + 1 = 1), exactly what it prints. And the Thursday-to-Saturday streak of week 2 also reaches 3, but it does not replace the first one because 3 > 3 is false.
If you wanted the most recent streak to win a tie, changing > to >= would be enough. It is a decision, not a mistake, but it must be written the same way in the diamond and in the code.
Questions you might ask
Why one loop of 14 and not two of 7? Because with two loops you would have to decide what happens to the streak when moving from one to the other, and the natural thing is to reset it (my mistake in the story). With a single array of 14 days, Sunday and Monday are simply i = 6 and i = 7.
Why store best_start instead of working it out at the end? Because at the end the current streak is no longer the best one (on the last day it is 0). You have to note where it started at the moment it becomes the best.
What if no day reached the goal? best would stay at 0 and best_start at 0, and the program would say «0 days, starts on Monday of week 1». The right thing would be one more diamond at the end: best == 0? → «There is no streak».
Where does each day’s printf go in the flowchart? In a parallelogram after the meeting point, because it runs whether the streak goes up or breaks. If you drew it inside one branch, only some days would be shown.
Is the else with streak = 0 needed? Yes. Without it, the streak would never break and would end up counting every day with 10,000 or more, even if they were not consecutive (8, with this data).
Resetting the streak somewhere other than the diamond’s No (when the week changes, at the start of each lap…). The streak only breaks because of a weak day; any other streak = 0 is a logic error.
Try it yourself
- Change
>to>=instreak > bestand check that the longest streak now starts on Thursday of week 2. - Add the
best == 0?diamond at the end of the flowchart and the code, and test it by setting the goal to 20,000.
Program 2: is your step count a palindrome?
One day I walked 11,211 steps and the number caught my eye: it reads the same forwards and backwards. The program reads the steps from the keyboard as text and says whether they are a palindrome. What makes it tricky: you have to compare the first digit with the last, the second with the second-to-last… and stop as soon as a pair does not match.
The idea
Two indexes: i starts at the first digit and j at the last. While they do not cross and their digits match, i moves forward and j moves back. When the loop stops there are two possibilities, and a second diamond tells them apart:
i >= j: they crossed (or met in the center) without finding any different pair → it is a palindrome.i < j: they stopped becausenumber[i] != number[j]→ it is not.
It is the same scheme as the search in the theory (loop with && + diamond that checks why it stopped):
Before programming, think about why we read the number as text and not as an int. With an int you would have to extract the digits with % 10 and / 10; with a string, each digit is already in its own cell.
The code
#include <stdio.h>
#include <string.h>
int main(void) {
char number[20]; // the steps are read as text to look at them digit by digit
int i, j;
printf("Today's steps: ");
scanf("%19s", number); // %19s: leaves room for the '\0'
i = 0; // one index from the left
j = strlen(number) - 1; // and another from the right (the last character, not the '\0')
// They move towards the center while they do not cross AND the digits match
while (i < j && number[i] == number[j]) {
i = i + 1;
j = j - 1;
}
// If they crossed (or met in the center), every pair matched
if (i >= j) {
printf("%s is a palindrome\n", number);
} else {
printf("%s is not a palindrome: digit %d ('%c') does not match digit %d ('%c')\n",
number, i, number[i], j, number[j]);
}
return 0;
}
The loop is short, but each piece has its reason:
i = 0; // one index from the left
j = strlen(number) - 1; // and another from the right (the last character, not the '\0')
// They move towards the center while they do not cross AND the digits match
while (i < j && number[i] == number[j]) {
i = i + 1;
j = j - 1;
}
j = strlen(number) - 1:strlencounts the characters without the'\0'. For “11211” it gives 5, and the last character is at position 4. Without the- 1,jwould point at the'\0'.i < jgoes before the comparison: once the indexes cross, there is no point comparing further.- Both indexes change inside the loop. If you forget
j = j - 1, you would always compare with the last digit.
Output
Real output, typing 11211:
Today's steps: 11211 11211 is a palindrome
By hand, with strlen = 5:
| Lap | i | j | number[i] | number[j] | i < j and equal? |
|---|---|---|---|---|---|
| 1 | 0 | 4 | ‘1’ | ‘1’ | Yes → i = 1, j = 3 |
| 2 | 1 | 3 | ‘1’ | ‘1’ | Yes → i = 2, j = 2 |
| — | 2 | 2 | ‘2’ | ‘2’ | No: i < j is false |
On leaving, i >= j (2 >= 2), so it is a palindrome. The middle digit is never compared with another one: it does not need to be. If you type 12341, the loop stops on lap 2 with '2' against '4' and the program says it is not a palindrome (you will see it in Python Tutor, further down).
Questions you might ask
Why does the final diamond ask i >= j and not whether the digits are equal? Because once the indexes cross, number[i] and number[j] can be anything (with 4 digits, i ends at 2 and j at 1). The only safe question is whether they crossed.
Does it work with an even number of digits? Yes. With “1221”: lap 1 compares 0 and 3, lap 2 compares 1 and 2, and then i = 2, j = 1: they crossed, palindrome.
Why %19s in the scanf? Because the array has 20 cells and one is for the '\0'. If someone types 30 characters, %19s reads 19 and does not write outside the array.
How is strlen drawn in the flowchart? Like any other calculation: in the initialisation rectangle, j = strlen(number) - 1. Functions need no special symbol.
j = strlen(number) without the - 1. The first comparison would be '1' against the '\0', the loop would stop on lap 1 and the program would say no number is a palindrome.
Try it yourself
- Run it with 1221, 12341 and 7 (a single digit: what does the loop do if
iandjstart equal?). - Change the program so it also says how many pairs of digits it has compared.
Program 3: the week’s average and the days above it
This time the user types the steps, one per day. The program works out the average and then says which days were above it. What makes it tricky: to know whether a day is above the average you need the average… and the average is only known once every day has been read.
The idea
Two loops in a row, not nested:
- Loop 1: read the 7 days and add them up at the same time.
- After it,
average = total / Nand it is shown. - Loop 2: go through the array again and, with an
if, show and count those above the average.
Between the two loops, i goes back to 0. In the flowchart it looks like two «blocks» of diamond + way back, one under the other:
Before programming, think about why it cannot be done in a single loop. When you read Monday (6420) you do not yet know whether it will end up above or below: the average depends on the days still to come.
The code
#include <stdio.h>
#define N 7
int main(void) {
const char *days[N] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
int steps[N];
int total = 0;
int above = 0; // days above the average
double average;
int i;
// Loop 1: read the seven days (parallelogram inside the loop)
for (i = 0; i < N; i++) {
printf("Steps on %s: ", days[i]);
scanf("%d", &steps[i]);
total = total + steps[i]; // added up while it is read
}
average = (double) total / N; // the average is only known when loop 1 ends
printf("Average: %.1f steps\n", average);
// Loop 2: with the average already worked out, go through the array again
for (i = 0; i < N; i++) {
if (steps[i] > average) {
printf(" %s: %d (above)\n", days[i], steps[i]);
above = above + 1;
}
}
printf("Days above the average: %d of %d\n", above, N);
return 0;
}
The two loops, up close:
// Loop 1: read the seven days (parallelogram inside the loop)
for (i = 0; i < N; i++) {
printf("Steps on %s: ", days[i]);
scanf("%d", &steps[i]);
total = total + steps[i]; // added up while it is read
}
average = (double) total / N; // the average is only known when loop 1 ends
printf("Average: %.1f steps\n", average);
// Loop 2: with the average already worked out, go through the array again
for (i = 0; i < N; i++) {
if (steps[i] > average) {
printf(" %s: %d (above)\n", days[i], steps[i]);
above = above + 1;
}
}
- In loop 1, the
scanf(«Read steps[i]» parallelogram) and the addition happen in the same lap: that way there is no need for a third loop to add up. (double) total / N: without the(double), C would do an integer division.- In loop 2,
steps[i] > averagecompares anintwith adouble; C converts the integer todoublebefore comparing, so it works.
Output
Real output, typing the week’s steps:
Steps on Monday: 6420 Steps on Tuesday: 11250 Steps on Wednesday: 8900 Steps on Thursday: 12030 Steps on Friday: 4100 Steps on Saturday: 9870 Steps on Sunday: 10500 Average: 9010.0 steps Tuesday: 11250 (above) Thursday: 12030 (above) Saturday: 9870 (above) Sunday: 10500 (above) Days above the average: 4 of 7
The trace of loop 1 shows how the total grows:
| Lap | Day | steps[i] read | total after |
|---|---|---|---|
| 1 | Monday | 6420 | 6420 |
| 2 | Tuesday | 11250 | 17670 |
| 3 | Wednesday | 8900 | 26570 |
| 4 | Thursday | 12030 | 38600 |
| 5 | Friday | 4100 | 42700 |
| 6 | Saturday | 9870 | 52570 |
| 7 | Sunday | 10500 | 63070 |
63070 / 7 = 9010.0. In loop 2, the days above it are Tuesday (11250), Thursday (12030), Saturday (9870) and Sunday (10500): 4 out of 7. Saturday does not reach the 10,000 goal, but it does beat the average.
Questions you might ask
Why does the «Steps on Monday» printf go inside the loop? Because it is the message that goes with each reading. In the flowchart, the «Read steps[i]» parallelogram includes it: there is no need to draw the prompt separately.
What if we did not set i = 0 before loop 2? In C with for it cannot happen, because the header does it. But in the flowchart (and with while) it is a rectangle you have to draw: otherwise i would be 7 and the loop 2 diamond would say No straight away.
Why > and not >= the average? The task says «above». A day with exactly the average is not above it. With this data nothing changes (no day has 9010), but the diamond must say what the task says.
Can the average be stored as an int? For the diamond it would make no difference: if a whole number of steps beats the truncated average, it also beats the real one. But the average that is shown would lose its decimals: with 63071 steps you would see 9010 instead of 9010.1. With double, what is shown and what is compared is the exact value.
Trying to do it in a single loop by comparing with the «average so far». The average changes with each day read, so Monday would be compared with itself and the results would depend on the order of the days.
Try it yourself
- Add an
elseto loop 2 that counts the days below, and check that above + below = 7. - Change the program so it also says which day was closest to the average (hint: the difference in absolute value, with one more diamond).
Common mistakes in this practice
- Resetting a counter or a streak outside its diamond. If the flowchart has no No leading to
streak = 0, the code must not have it either. - Using
>=when the task asks for «more than». The diamond’s sign is part of the task: «above», «longer», «beats» are>. - Forgetting the second diamond after a
whilewith&&. The loop can stop for two reasons and the program needs to know which. strlenwithout the- 1when starting an index at the end of a string.- Dividing integers for an average without
(double). - Merging two loops into one when the second needs a value that only exists once the first has finished.
Watch it step by step in Python Tutor
Python Tutor draws the variables at each step of the run. Choose C and paste this version of the palindrome with a fixed number (it does not read from the keyboard) that is not a palindrome, to see where it stops:
#include <stdio.h>
#include <string.h>
int main(void) {
char number[] = "12341"; // fixed data: Python Tutor does not read from the keyboard
int i = 0;
int j = strlen(number) - 1;
while (i < j && number[i] == number[j]) {
i = i + 1;
j = j - 1;
}
if (i >= j) {
printf("%s is a palindrome\n", number);
} else {
printf("%s is not a palindrome (%c vs %c)\n", number, number[i], number[j]);
}
return 0;
}
Real output:
12341 is not a palindrome (2 vs 4)
What to watch step by step:
- At the start,
numberappears as an array of 6 characters:'1' '2' '3' '4' '1'and the'\0'.jis 4 becausestrlengives 5. - On the first lap, cells 0 and 4 are compared (
'1'and'1'): the loop enters andiandjchange at the same time. - On the second
whilequestion,i = 1andj = 3:'2'against'4'. Notice that the arrow does not enter the body: it is the diamond’s No. - Since
i < j(1 < 3), the finalifgoes through theelse: it is the flowchart’s second diamond saying No. - Change
"12341"to"12321"and run it again: the loop does two laps and stops withi = j = 2.
Summary
- Draw the flowchart before programming: a
streak = 0that does not come from any diamond is a mistake the flowchart gives away. - An
ifinside another is drawn as a diamond inside the Yes branch; the outer meeting point collects both branches. - A
whilewith&&needs a diamond afterwards to know why it stopped. - Two indexes moving towards the center (
iup,jdown) solve palindromes, reversals and end-to-end comparisons. - If a calculation needs a value that only exists at the end (the average), you need two loops in a row, with
i = 0between them. - The sign in each diamond (
>,>=,<) is decided by the task, and it must be the same in the flowchart and in the code.
Checklist: have you practised it?
- Have you drawn the flowchart of each program before looking at the code?
- Can you explain why the longest streak starts on Sunday and not on Thursday?
- Do you know what happens in the palindrome check if you remove the
- 1fromstrlen? - Can you explain why the average needs two loops?
- Have you run the three programs and checked the outputs?
- Have you tried the «Try it yourself» tasks without looking at the theory?
If you answered yes to almost everything, you are ready for the flowcharts exercises, where I no longer give you the code. See you there!
Next step: exercisesFlowcharts in C — exercises with counters, passwords and two weeks of steps (and a program that hung)Did this article help you? Here is how you can support SergioLearns →



