Skip to content

Commit bf4f292

Browse files
c, b made behave like C
1 parent 0baf2b4 commit bf4f292

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
All notable changes to the pyprintf project will be documented in this file.
44

5+
## [0.0.8] - 2025-04-18
6+
7+
**Character Handling (`%c`):**
8+
* Added modulo 256 truncation to align with C's `unsigned char` behavior, ensuring values wrap within 0-255.
9+
* Negative inputs now wrap via modulo 256 (e.g., `-1` becomes `255`).
10+
11+
**Binary Handling (`%b`):**
12+
* Negative numbers now use 32-bit two's complement (e.g., `-5` becomes `11111111111111111111111111111011`).
13+
* Values are truncated to 32 bits via `& 0xFFFFFFFF` to mimic C's integer overflow.
14+
515
## [0.0.7] - 2025-04-18
616

717
* Normalized scientific notation format (`e`, `E`) to align with C++ conventions.

src/pyprintf/core.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,14 +508,20 @@ def sprintf_format(
508508
# Process argument based on format specifier
509509
if placeholder.type == "b": # Binary
510510
try:
511-
arg = bin(int(arg))[2:] # Remove '0b' prefix
511+
num = int(arg)
512+
# Truncate to 32 bits (like C's `int`)
513+
num = num & 0xFFFFFFFF
514+
# Convert to two's complement for negatives
515+
if num < 0:
516+
num += 0x100000000
517+
arg = bin(num)[2:]
512518
except (ValueError, TypeError):
513519
arg = "0"
514520

515521
elif placeholder.type == "c": # Character
516522
try:
517-
arg = chr(int(arg))
518-
except (ValueError, TypeError, OverflowError):
523+
arg = chr(int(arg) % 256) # Wrap to 0-255 like C's unsigned char
524+
except (ValueError, TypeError):
519525
arg = "\0"
520526

521527
elif placeholder.type in ("d", "i"): # Integer

tests/test_sprintf.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,23 @@ def test_format_a_percentage_sign(self):
1919
assert sprintf("%%") == "%"
2020

2121
def test_format_a_binary_number(self):
22-
assert sprintf("%b", 2) == "10"
22+
assert sprintf("%b", 10) == "1010"
23+
24+
def test_format_a_binary_negative_number(self):
25+
assert sprintf("%b", -5) == "11111111111111111111111111111011"
26+
27+
def test_format_a_binary_number_overflow(self):
28+
assert sprintf("%b", 256) == "100000000"
2329

2430
def test_format_a_character(self):
2531
assert sprintf("%c", 65) == "A"
2632

33+
def test_format_a_character_overflow(self):
34+
assert sprintf("%c", 256) == "\x00"
35+
36+
def test_format_a_character_negative(self):
37+
assert sprintf("%c", -1) == "ÿ"
38+
2739
def test_format_a_decimal_integer(self):
2840
assert sprintf("%d", 2) == "2"
2941

@@ -333,7 +345,7 @@ def test_format_a_large_number_exceeding_32_bits_correctly_as_a_hexadecimal_stri
333345

334346
def test_format_a_binary_number_using_lambda(self):
335347
cfg = config().allow_computed_value(True)
336-
assert cfg.sprintf("%b", lambda: 2) == "10"
348+
assert cfg.sprintf("%b", lambda: 10) == "1010"
337349

338350
def test_format_a_character_using_lambda(self):
339351
cfg = config().allow_computed_value(True)

0 commit comments

Comments
 (0)