Skip to content

Add Makefile and README; refactor Caesar cipher CLI to interactive stdin/stdout implementation - #1

Open
ukis666 wants to merge 1 commit into
mainfrom
codex/complete-project
Open

Add Makefile and README; refactor Caesar cipher CLI to interactive stdin/stdout implementation#1
ukis666 wants to merge 1 commit into
mainfrom
codex/complete-project

Conversation

@ukis666

@ukis666 ukis666 commented Mar 16, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Provide a simple build target and clearer project description to ease compilation and usage on Linux systems.
  • Replace fragile file-based I/O with a terminal-driven interactive interface for encoding and decoding Caesar cipher texts.
  • Improve correctness and readability by normalizing shift values, preserving case, and removing ad-hoc goto/file handling.

Description

  • Added a Makefile with CC, CFLAGS, TARGET, and a default all/clean target and path to sifreleyicim/sifreleyicim1/sifreleyici.c.
  • Updated README.md with Turkish usage notes, features, build instructions, and examples for make and direct gcc compilation.
  • Heavily refactored sifreleyicim/sifreleyicim1/sifreleyici.c by removing file-based operations and global I/O, adding normalize_shift, satir_oku, kaydir_char, sifrele_metin, tum_cozumleri_yazdir, sayi_oku, and menu_yazdir, and converting main into an interactive CLI that reads from stdin and writes to stdout.
  • Fixed buffer handling and edge cases: removed BOM, introduced ALFABE_UZUNLUGU constant, ensured newline trimming, preserved upper/lower case letters, and implemented normalized shift wrapping for negative/large values.

Testing

  • Built the project successfully using make which invokes gcc -Wall -Wextra -pedantic -std=c11 -o sifreleyici sifreleyicim/sifreleyicim1/sifreleyici.c.
  • Verified direct compilation with the provided gcc command completed without compiler errors.
  • No automated unit tests were added or run as part of this change.

Codex Task

Summary by CodeRabbit

  • New Features

    • Transitioned application to an interactive command-line menu interface with in-memory processing pipeline.
  • Documentation

    • Updated README with Turkish documentation including build and run instructions, and feature descriptions.
  • Chores

    • Added build configuration enabling project compilation from source.

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR adds a Makefile for building a Caesar cipher project from source using gcc with C11 standard, translates the README to Turkish with expanded build and usage instructions, and refactors the core cipher implementation from file-oriented processing to a CLI-driven, in-memory pipeline with new helper functions for shift normalization, character manipulation, and text encryption.

Changes

Cohort / File(s) Summary
Build Configuration
Makefile
New Makefile with targets for compiling the sifreleyici binary from C source using gcc with C11 standard and warning flags (-Wall -Wextra -pedantic).
Documentation
README.md
Documentation translated from English to Turkish with expanded sections for Özellikler (features), Derleme (build), and Çalıştırma (run) instructions.
Core Implementation
sifreleyicim/sifreleyicim1/sifreleyici.c
Major refactoring from file-based I/O to CLI-driven in-memory processing. Added helper functions: normalize_shift(), satir_oku(), kaydir_char(), sifrele_metin(), tum_cozumleri_yazdir(), sayi_oku(), menu_yazdir(). Replaced file operations with console I/O and interactive menu-driven control flow.

Sequence Diagram

sequenceDiagram
    participant User
    participant Menu as Menu System
    participant TextProc as Text Processing
    participant Output as Output Handler

    loop CLI Loop
        User->>Menu: Start/Display menu
        Menu->>User: Show options
        User->>Menu: Select operation
        alt Encrypt Text
            Menu->>User: Prompt for text
            User->>Menu: Enter text
            Menu->>TextProc: Call sifrele_metin()
            TextProc->>TextProc: Apply shift to each char
            TextProc->>Output: Return encrypted text
        else Decrypt All Variants
            Menu->>User: Prompt for text
            User->>Menu: Enter text
            Menu->>TextProc: Call tum_cozumleri_yazdir()
            TextProc->>TextProc: Generate 26 shift variants
            TextProc->>Output: Print all variants
        else Exit
            Menu->>User: Exit program
        end
        Output->>User: Display results
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A cipher once read from dusty files,
Now dances through the CLI with style,
New helpers shift each letter bright,
In memory it flows—oh what delight!
From build to menu, all comes together,
This Turkish refactor, smooth as leather. 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding build/documentation files (Makefile and README) and refactoring the Caesar cipher into an interactive CLI implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/complete-project
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can make CodeRabbit's review stricter and more nitpicky using the `assertive` profile, if that's what you prefer.

Change the reviews.profile setting to assertive to make CodeRabbit's nitpick more issues in your PRs.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sifreleyicim/sifreleyicim1/sifreleyici.c`:
- Around line 68-76: Include <errno.h> and <limits.h>, set errno = 0 before
calling strtol(satir, &endptr, 10), then after the call reject the parse if
errno == ERANGE or if deger < INT_MIN || deger > INT_MAX; keep the existing
empty-string and endptr checks (satir[0] == '\0' || (endptr != NULL && *endptr
!= '\0')) and return 0 on those failures, only cast and assign *sonuc =
(int)deger and return 1 when no errors and value is within int range.
- Around line 17-27: satir_oku currently treats fgets()==NULL as an empty string
and never signals EOF; change its signature to return an int status (0 for EOF,
1 for success), on fgets()==NULL return 0 (do not set dizi to ""), after a
successful read check if the newline was present and if not drain stdin until
'\n' to discard the remainder of the overlong input; update sayi_oku to
propagate EOF by returning -1 when satir_oku returns 0, and update main to check
for -1 from sayi_oku and break/exit the input loop instead of treating it as an
invalid choice.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 58973acb-ae97-4f62-ab6b-2640885d58af

📥 Commits

Reviewing files that changed from the base of the PR and between 7c71cae and 82824bf.

📒 Files selected for processing (3)
  • Makefile
  • README.md
  • sifreleyicim/sifreleyicim1/sifreleyici.c

Comment on lines +17 to 27
void satir_oku(char dizi[], size_t boyut) {
if (fgets(dizi, (int)boyut, stdin) == NULL) {
dizi[0] = '\0';
return;
}

dizi[i] = '\0';
size_t len = strlen(dizi);
if (len > 0 && dizi[len - 1] == '\n') {
dizi[len - 1] = '\0';
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the EOF/truncation path from satir_oku() into sayi_oku() and main().
sed -n '17,27p' sifreleyicim/sifreleyicim1/sifreleyici.c
printf '\n-- sayi_oku --\n'
sed -n '62,76p' sifreleyicim/sifreleyicim1/sifreleyici.c
printf '\n-- main loop --\n'
sed -n '91,98p' sifreleyicim/sifreleyicim1/sifreleyici.c

Repository: ukis666/Ceasar_Cipher_Decoder_and_Encoder

Length of output: 879


🏁 Script executed:

sed -n '85,110p' sifreleyicim/sifreleyicim1/sifreleyici.c

Repository: ukis666/Ceasar_Cipher_Decoder_and_Encoder

Length of output: 570


Differentiate EOF/truncation from ordinary invalid input.

When fgets() returns NULL (EOF from Ctrl-D or closed stdin), the code converts it to an empty string, treating it as invalid input rather than a signal to exit. This traps the loop in an infinite "Gecersiz secim" cycle with no way to break. If input exceeds the buffer size, the missing newline goes undetected, and unread characters remain in stdin, causing the next prompt to consume stale input.

To fix: return a read status from satir_oku() (0 for EOF, 1 for success), drain unread input when no newline is found, have sayi_oku() return -1 on EOF, and let main() check for EOF and break before treating empty input as an invalid choice.

Suggested direction
-void satir_oku(char dizi[], size_t boyut) {
+int satir_oku(char dizi[], size_t boyut) {
     if (fgets(dizi, (int)boyut, stdin) == NULL) {
         dizi[0] = '\0';
-        return;
+        return 0;
     }
 
     size_t len = strlen(dizi);
     if (len > 0 && dizi[len - 1] == '\n') {
         dizi[len - 1] = '\0';
+    } else {
+        int ch;
+        while ((ch = getchar()) != '\n' && ch != EOF) {
+        }
     }
+
+    return 1;
 }
-        if (!sayi_oku("", &secim)) {
+        int ok = sayi_oku("", &secim);
+        if (ok < 0) {
+            break;
+        }
+        if (!ok) {
             printf("Gecersiz secim.\n");
             continue;
         }

Also applies to: 95-98

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sifreleyicim/sifreleyicim1/sifreleyici.c` around lines 17 - 27, satir_oku
currently treats fgets()==NULL as an empty string and never signals EOF; change
its signature to return an int status (0 for EOF, 1 for success), on
fgets()==NULL return 0 (do not set dizi to ""), after a successful read check if
the newline was present and if not drain stdin until '\n' to discard the
remainder of the overlong input; update sayi_oku to propagate EOF by returning
-1 when satir_oku returns 0, and update main to check for -1 from sayi_oku and
break/exit the input loop instead of treating it as an invalid choice.

Comment on lines +68 to +76
char* endptr = NULL;
long deger = strtol(satir, &endptr, 10);

FILE* input_file = fopen("sifreli_text.txt", "w");
FILE* output_file = fopen("sifresiz_text.txt", "r");
if (can_file_open(output_file, input_file)) {
// Dosya açılamadıysa programı sonlandırıyoruz
return 1;
}
if (satir[0] == '\0' || (endptr != NULL && *endptr != '\0')) {
return 0;
}

system("clear"); // Linux'ta ekran temizleme
printf("DON'T FORGET TO SAVE\n");
*sonuc = (int)deger;
return 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm that sayi_oku() currently uses strtol() without range/error guards.
sed -n '62,76p' sifreleyicim/sifreleyicim1/sifreleyici.c
printf '\n-- guard search --\n'
rg -n 'strtol|errno|ERANGE|INT_(MIN|MAX)' sifreleyicim/sifreleyicim1/sifreleyici.c || true

Repository: ukis666/Ceasar_Cipher_Decoder_and_Encoder

Length of output: 486


🏁 Script executed:

head -20 sifreleyicim/sifreleyicim1/sifreleyici.c

Repository: ukis666/Ceasar_Cipher_Decoder_and_Encoder

Length of output: 532


Reject out-of-range numeric input before narrowing to int.

strtol() parses into long, but *sonuc = (int)deger; happens without checking errno or bounds. Values outside the platform int range (e.g., 2147483648 on a 32-bit int system) are accepted and silently truncated instead of triggering validation error.

Add the missing headers:

+#include <errno.h>
+#include <limits.h>

Then guard the parse and cast:

+    errno = 0;
     char* endptr = NULL;
     long deger = strtol(satir, &endptr, 10);
 
-    if (satir[0] == '\0' || (endptr != NULL && *endptr != '\0')) {
+    if (satir[0] == '\0' || *endptr != '\0' ||
+        errno == ERANGE || deger < INT_MIN || deger > INT_MAX) {
         return 0;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
char* endptr = NULL;
long deger = strtol(satir, &endptr, 10);
FILE* input_file = fopen("sifreli_text.txt", "w");
FILE* output_file = fopen("sifresiz_text.txt", "r");
if (can_file_open(output_file, input_file)) {
// Dosya açılamadıysa programı sonlandırıyoruz
return 1;
}
if (satir[0] == '\0' || (endptr != NULL && *endptr != '\0')) {
return 0;
}
system("clear"); // Linux'ta ekran temizleme
printf("DON'T FORGET TO SAVE\n");
*sonuc = (int)deger;
return 1;
errno = 0;
char* endptr = NULL;
long deger = strtol(satir, &endptr, 10);
if (satir[0] == '\0' || *endptr != '\0' ||
errno == ERANGE || deger < INT_MIN || deger > INT_MAX) {
return 0;
}
*sonuc = (int)deger;
return 1;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sifreleyicim/sifreleyicim1/sifreleyici.c` around lines 68 - 76, Include
<errno.h> and <limits.h>, set errno = 0 before calling strtol(satir, &endptr,
10), then after the call reject the parse if errno == ERANGE or if deger <
INT_MIN || deger > INT_MAX; keep the existing empty-string and endptr checks
(satir[0] == '\0' || (endptr != NULL && *endptr != '\0')) and return 0 on those
failures, only cast and assign *sonuc = (int)deger and return 1 when no errors
and value is within int range.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant