THE SYLLABUS TASK
What you need to solve
Implement the Folding Method hash function.
Nonnegative key (0–1,000,000), then table size m (1–1000). Split into two-digit decimal groups from the right, sum them without reversing groups, then reduce modulo m.
UNDERSTAND THE IDEA
Explanation
Shift folding divides a key into equal-sized digit groups and sums them. For 1234, the groups are 12 and 34, whose sum is 46.
This page uses two-digit groups read from the right. A shorter leading group is accepted; no alternating reversal is applied.
The sum must be mapped into the table range with modulo m. Returning only the raw sum, as in the manual, is not always a valid hash index.
TURN THE IDEA INTO STEPS
Step-by-step algorithm
- Start sum at zero.
- Extract a group with key % 100.
- Add the group and remove it with key /= 100.
- Repeat until no groups remain, including a single zero group for key zero.
- Return sum % size.
SEE THE CONTROL FLOW
Flowcharts
Diamonds show decisions; labeled arrows select a branch. Returning arrows repeat work. Helper-function steps group the operations explained above and in the code. These charts focus on the named core operation. On a phone, scroll within the diagram or open the full-size version.
Compute one hash index
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
/* Read one entire token; reject malformed, oversized and out-of-range input. */
int readToken(char text[], size_t capacity) {
int ch; size_t used = 0; int fits = 1;
while ((ch = getchar()) != EOF && isspace((unsigned char)ch)) { }
if (ch == EOF) return 0;
do {
if (ch == 0) fits = 0;
if (used + 1 < capacity) text[used++] = (char)ch;
else fits = 0;
ch = getchar();
} while (ch != EOF && !isspace((unsigned char)ch));
text[used] = '\0';
return fits;
}
int readInt(int *value) {
char token[64], *end;
if (!readToken(token, sizeof token)) return 0;
errno = 0; long result = strtol(token, &end, 10);
if (errno || end == token || *end || result < -1000000 || result > 1000000) return 0;
*value = (int)result; return 1;
}
int invalid(void) { puts("Invalid or incomplete input."); return 1; }
int hash(int key, int size) {
int sum = 0;
do { sum += key % 100; key /= 100; } while (key);
return sum % size;
}
/* Nonnegative key (0..1,000,000), table size (1..1000). Index only, no table insertion. */
int main(void) {
int key, size;
if (!readInt(&key) || !readInt(&size) || key < 0 || size < 1 || size > 1000) return invalid();
printf("Hash index: %d\n",hash(key,size)); return 0;
}
Local compile: gcc -std=c17 folding-hash.c -o program -lm
Open in C compiler transfers the source. Copy the sample input into the compiler’s input box separately before running.
UNDERSTAND THE CODE
Line-by-line explanation
Follow the exact source above, from input handling through the algorithm and its result. Line numbers count blank lines; related statements are grouped into steps. Start with main to follow execution, then open the functions it calls.
Start with main → · Algorithm and data structure →
Lines 1–5Include input, conversion and validation declarations
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>stdio.h supplies terminal input/output. stdlib.h declares conversion and allocation functions. string.h supplies string and memory utilities. ctype.h supplies isspace, and errno.h supplies conversion error reporting. Headers declare facilities; including them does not execute an operation.
Lines 7–9Define a complete-token reader and initialise its state
/* Read one entire token; reject malformed, oversized and out-of-range input. */
int readToken(char text[], size_t capacity) {
int ch; size_t used = 0; int fits = 1;readToken receives a writable buffer and its capacity. ch is int so it can represent EOF as well as input characters. used counts stored characters, and fits starts as a success flag. One slot must remain for the null terminator.
Lines 10–11Skip leading whitespace and recognise end-of-file
while ((ch = getchar()) != EOF && isspace((unsigned char)ch)) { }
if (ch == EOF) return 0;Read until a non-whitespace character appears. The unsigned-char cast supplies an allowed value to isspace. Return 0 if EOF arrives before a token begins.
Lines 12–15Collect a token without silently truncating it
do {
if (ch == 0) fits = 0;
if (used + 1 < capacity) text[used++] = (char)ch;
else fits = 0;The do body handles the character already read. An embedded zero byte marks the token invalid. Store a character only while there is room for it and a null terminator; otherwise clear fits. Continue reading even after the buffer fills.
Lines 16–20Consume the full token and terminate the buffer
ch = getchar();
} while (ch != EOF && !isspace((unsigned char)ch));
text[used] = '\0';
return fits;
}Read through the next whitespace or EOF, add a null character after the stored prefix, then return fits. A too-long token returns 0 rather than pretending that its stored prefix is the complete token.
Lines 21–23Wrap token input as a checked integer read
int readInt(int *value) {
char token[64], *end;
if (!readToken(token, sizeof token)) return 0;value is an output address. A 64-slot local buffer receives the token; a failed token read returns 0 before attempting conversion.
Lines 24–25Convert base-ten text and check the whole result
errno = 0; long result = strtol(token, &end, 10);
if (errno || end == token || *end || result < -1000000 || result > 1000000) return 0;Reset errno before strtol. &end receives the stopping address. Reject conversion errors, no converted digits, leftover characters, or values outside -1,000,000 to 1,000,000. Thus 12x is not accepted as the integer 12.
Lines 26–28Return the accepted value or a standard error status
*value = (int)result; return 1;
}
int invalid(void) { puts("Invalid or incomplete input."); return 1; }Store a validated integer through *value and return 1 from readInt. invalid is a separate helper that prints the error and returns 1 as main’s failure status; the same number has different roles in these two function contracts.
Lines 30–32Split the decimal key into two-digit groups
int hash(int key, int size) {
int sum = 0;
do { sum += key % 100; key /= 100; } while (key);sum begins at zero. Repeatedly add key % 100 and remove those final two digits with key /= 100. The do-while also handles key 0 once. For 123456, the groups are 56, 34 and 12, whose sum is 102.
Lines 33–34Reduce the group sum to an index
return sum % size;
}Return sum % size so the result fits the table. This is simple additive folding; the groups are not reversed or weighted.
Lines 35–36Document an index-only hash demonstration
/* Nonnegative key (0..1,000,000), table size (1..1000). Index only, no table insertion. */
int main(void) {The input is a nonnegative key followed by a table size. The program calculates an index only; it does not store keys or resolve collisions.
Lines 37–38Read a valid key and positive table size
int key, size;
if (!readInt(&key) || !readInt(&size) || key < 0 || size < 1 || size > 1000) return invalid();readInt already limits integer magnitude. Require key >= 0 and size from 1 to 1000, preventing zero-divisor calculations and negative table indexes.
Lines 39–40Print the calculated index and finish
printf("Hash index: %d\n",hash(key,size)); return 0;
}Call hash(key,size), display the returned index and return success. A valid hash index need not be unique: different keys can still collide.
FOLLOW THE VALUES
Dry run
- For 123456, groups from the right are 56,34,12.
- Their sum is 102.
- For m = 100, the final index is 102 % 100 = 2.
- Changing group order alone does not change this shift-folding sum.
CHECK THE BEHAVIOUR
Sample input & output
These outputs were captured by running the exact C source shown above. Commands use the stated input format; the programs omit repeated menu prompts so the same sample can be pasted and run.
Sample 1
1234 100
Hash index: 46
Sample 2
123456 100
Hash index: 2
Sample 3
0 11
Hash index: 0
Common mistakes
- Do not return the raw sum as an index without range reduction.
- State whether groups are reversed; this is shift folding.
- Preserve the original input if it is needed later, since grouping consumes the working copy.
WHY THIS GROWTH RATE?
Time and space complexity
O(g) grouping work for g two-digit groups; O(1) extra space.
Each iteration removes up to two decimal digits, so an unbounded key with D digits requires ceil(D/2) groups.
The loop uses only a running sum and a reduced key. In this bounded machine-integer example there are at most four groups, so the work is effectively constant.
Group summation can create collisions; it should not be described as preserving every digit arrangement uniquely.
Big-O describes growth in the stated input quantity. The educational limits keep examples safe; complexity discussions state which bounds depend on a generalized input size. Arithmetic on the accepted native numeric types is treated as constant-time.
PREPARE FOR YOUR LAB VIVA
Related viva questions & answers
Try answering aloud, then expand the answer to check your reasoning. These questions focus on the concepts used in this program.
Why are remainder and division by 100 used together?
Remainder extracts the rightmost two-digit group, and division removes it. Repeating the pair processes all groups without needing a string representation.
How is a short leading group handled?
It contributes its ordinary numeric value. For 12345, the groups are 45,23,1, and the one-digit group 1 is added normally.
How does shift folding differ from boundary folding?
Shift folding adds groups as they are. Boundary folding may reverse selected groups before addition; this implementation deliberately does not use that variation.
Why can 1234 and 3412 have the same folding result?
Their two groups are the same values in opposite order. Addition is commutative, so both sums are 46 before table-size reduction.
Why is modulo still needed after adding groups?
The sum can be larger than the number of table slots. For groups summing to 102 and m=100, modulo produces valid index 2.
What does the do-while grouping loop do for key zero?
It processes one zero group, then stops. The sum and resulting hash index are zero, without requiring a special separate case.