Wrap around in C for Ceasar's Code - c

Hey guy's last time I posted I was a bit sloppy. Hopefully this time it'll look a lot better . Thank you for your time if you decide to help me. I really need it. Anyways heres the question. I need to have wrap around for my Code and i heard you can do it with modulus but I am not sure i am doing it correctly because I do not get the right results.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main () {
char s[200]; //blank array//
int mess;
printf("Generations have wondered how the Ceasar Code works\n");
printf("Please choose a number to mess up (encode) the current file\n");
scanf("%d", &mess);
mess = mess % 26;
FILE *ptof = fopen("Rock.txt", "r");
char a[200];//fill array with characters from file//
int i=0;
while( (a[i++]=fgetc(ptof)) != EOF && i < 89) { //get character from file//
}
a[i] = '\0'; /* null-terminate the string */
i = 0;
do{
printf("%c",a[i++]);
} while (a[i] != '\0'); /* print until hit \0 */
int j = 0;
for (j = 0; j < 89; j++){
s[j] = a[j] + mess;
}
printf("%s\n", s);
fclose(ptof);
return 0;
}

s[j] = a[j] + mess needs a modulo operation as well

There's a lot of room for improvement here. Do you really want to map printable characters into (potentially) non-printable characters? Or do you merely want to do a ceaser shift on letters in the alphabet? Why the arbitrary limit of 90 characters of input? Using scanf is never a good idea (in 20 some years writing code, I have never used it since I left school). Passing the shift on stdin rather than as an argument makes it hard to use your program as a filter. For instance, it would be really nice if you could take a string and shift it by 4, then by 13, then by 9 and see that you get the original text back. (eg < file ceaser 4 | ceaser 13 | ceaser 9 | diff - file should report no diffs).
Here's a few ideas:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
FILE *
xfopen( const char *path, const char *mode )
{
FILE *ifp = fopen( path, mode );
if( ifp == NULL ) {
perror( path );
exit( 1 );
}
return ifp;
}
int
main( int argc, char **argv )
{
int mess = argc > 1 ? strtol( argv[1], NULL, 10 ) % 26 : 13;
FILE *ptof = argc > 2 ? xfopen( argv[2], "r" ) : stdin;
int c;
while( ( c = fgetc( ptof )) != EOF ) {
if( isupper( c ))
c = 'A' + ( c - 'A' + mess ) % 26;
if( islower( c ))
c = 'a' + ( c - 'a' + mess ) % 26;
putchar( c );
}
return 0;
}

Related

decoding message using c

I was solving a codewars problem called "decoding a message" using C.
My code passed the sample tests but can't pass the random tests as it adds random chars after the required chars like in the image enter image description here
What's the problem here?
problem's link : [https://www.codewars.com/kata/565b9d6f8139573819000056]
#include <string.h>
#include <ctype.h>
char *decode (const char *encoded, char *decoded)
{
for (int i = 0; i < strlen(encoded); i++)
{
if (isalpha(encoded[i]))
{
if (encoded[i] <= 109)
{
decoded[i] = encoded[i] + 25 - ((encoded[i] - 'a')*2);
}
else if (encoded[i] >= 110)
{
decoded[i] = encoded[i] - 25 + (('z' - encoded[i])*2);
}
}
else
{
decoded[i] = encoded[i];
}
}
return decoded; // return it
}
As indicated in the comments, the symptom described by the OP suggests the receiving buffer is not terminated properly to make a C string.
Further, one should avoid using "magic numbers" like 109 and 110 in code... What do those numbers mean?? They certainly won't work if the constraint of being "all lowercase" is lifted. Would one then copy/paste/adapt many lines of code merely to deal with both upper and lower case alphabets?
Below is LESS code that not only deals with the OP problem (unterminated string) but also deals with both upper and lower case letters (recognising that 'case' would weaken any encryption. Included here to demonstrate technique, only.)
Have fun with these learning challenges.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char *decode( const char *s, char *d ) {
for( size_t i = 0; ( d[i] = s[i] ) != '\0'; i++ ) { // copy every byte
if( isalpha( d[i] ) ) { // transform needed ?
char c = islower( d[i] ) ? 'a' : 'A'; // basis to transpose ASCII char to 0-25
d[i] = (char)( c + ( 25 - ( d[i] - c ) ) ); // 0->25 ==> 25->0
}
}
return d; // return it
}
int main() {
char *hidden = "R slkv MLYLWB wvxlwvh gsrh nvhhztv";
char buf[ 128 ];
printf( "%s\n%s\n", hidden, decode( hidden, buf ) );
return 0;
}
R slkv MLYLWB wvxlwvh gsrh nvhhztv
I hope NOBODY decodes this message
If any of this is unclear, please post a question below...

Exercise problem - Returning the longest lign of a txt file

Starting C on my own following Kerningan & Ritchie 2nd edition ANSCI book.
Here, I am supposed to return the longest lign of a text.
very early in the book, so few functions are cited.
My program returns the ligns AFTER the longest lign
A lign being only defined by ending with '.'
I'm probably overstepping on this forum with my beginner level, but i'd appreciate the insight :) thanks a lot.
#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 1000
void copcol(char cop[], char retour[]);
int main(void)
{
int nbmax, nbnew, c, i;
nbmax = nbnew = i = 0 ;
char lignmax[MAXLEN] ;
char lignnew[MAXLEN] ;
while((c=getchar()) != EOF)
{
lignnew[i] = c ;
i++;
nbnew++ ;
if( (c == '.') && (nbmax < nbnew) && ( c != '\0'))
{
nbmax = nbnew ;
copcol(lignmax, lignnew);
nbnew = 0 ;
i=0 ;
}
}
if ( nbmax > 0 )
printf("%s",lignmax);
return 0;
}
void copcol(char new[], char max[])
{
int i ;
i=0;
while((new[i] = max[i]) != '\0')
++i;
}
also if a forum is more apropriate for this kind of questions, feel free to let me know.
You need to skip shorter lines when you encounter period (.)
#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 1000
void copcol (char new[], char max[]) {
int i = 0;
while ((new[i] = max[i]) != '\0')
++i;
}
int main (void) {
char lignmax[MAXLEN] ;
char lignnew[MAXLEN] ;
int nbmax, nbnew, c;
nbmax = nbnew = 0 ;
while ( (c = getchar()) != EOF) {
// nbnew also tracks the new-line-len
lignnew[nbnew++] = c ;
if ('.' == c) { // line ended, skip shorter, copy longer line
if (nbnew > nbmax) { // copying only when longer than current max-line
nbmax = nbnew ;
lignnew[nbnew] = '\0'; // terminate string
copcol (lignmax, lignnew);
}
//also ignores shorter-lines
nbnew = 0 ; // new line begins after the period (.)
}
}
if (nbmax > 0)
printf ("MaxLength: %d\n MaxLine: [%s]", nbmax, lignmax);
return 0;
}
Note: Input period(.) terminated lines cannot be longer than (MAXLEN -1), it'll cause buffer-overflow otherwise.

How to get rid of garbage characters in this program?

This program is supposed to print an input string backwards. Every single time it happens, though, I get garbage characters such as \340 or of the like. Why is it doing that? Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char mattsentence[51];
mattsentence[50] = '\0';
gets(mattsentence);
char mask[sizeof(mattsentence)];
int i, j;
j = sizeof(mattsentence);
for (i = 0; i < sizeof(mask); i++)
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
printf("\n");
}
Your approach is wrong because you reverse the entire character array while it can be filled only partially. You should use standard C function strlen declared in header <string.h> that to determine the size of the entered string. Also to use gets is unsafe because you can overwrite memory beyond the character array. It now is excluded from the C Standard
Here is shown how the program can be written.
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
char mask[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[--n] = '\0';
for ( size_t i = 0; n != 0; i++ )
{
mask[i] = mattsentence[--n];
printf( "%c", mask[i] );
}
printf( "\n" );
return 0;
}
If to enter
Hello, Christiana S. F. Chamon
then the program output will be
nomahC .F .S anaitsirhC ,olleH
Take into account that to output a string in the reverse order there is no need to define a second character array.
If you want only to output the source string in the reverse order then the program can look like
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[n-1] = '\0';
while ( n != 0 )
{
printf( "%c", mattsentence[--n] );
}
printf( "\n" );
return 0;
}
sizeof() operator gives the size of the datatype. So, sizeof(mattsentence) will give you a value of 51. Then, sizeof(mask) will give you 51 again.
When you use that sizeof(mask) as for loop condition, you're basically going past the actual input values, thus pritning out garbage values.
What you want here is to use strlen() to find out the actual valid length of the entered string.
So, basically you need to take care of
Point 1: replace sizeof with strlen().
Point 2: Use of gets() is dangerous. Please use fgets() instead of gets().
Point 3: int main() should be int main(void). Put an expilicit return statement at the end of main(). Good Practice.
The modified code should look like
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char mattsentence[51] = {0}; //always initalize local variables, here it's covering null termination , too.
fgets(mattsentence, 51, stdin); //fgets()
char mask[strlen(mattsentence) + 1]; // one more to store terminating '\0'
int i = 0, j = 0, k = 0;
j = strlen(mattsentence);
k = j;
for (i = 0; i < k; i++) // make use of k, don't call `strlen()` repeatedly
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
return 0; //added return statement
}
See changed code:
int main()
{
char mattsentence[51];
mattsentence[0] = '\0'; // initialization
gets(mattsentence);
char mask[strlen(mattsentence) + 1]; // +1 for string terminator '\0'
int i, j;
j = strlen(mattsentence);
for (i = 0; i < strlen(mattsentence); i++) // strlen of original string
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
}
There are several errors:
strlen() should be used to get length of string
for loop should be controlled according to input string, not output string
it is better to use fgets() instead of gets(): that way you can control how many character will be read from the input

K & R section 1.10 example program skipping 'printf()' line

I'm learning C through K & R. I have reached to section 1.10 External Variables and Scope.
In that section they have written and explained program regarding external variable and their scope. I typed that code myself and tried to execute it. It does not show any run time or compile time error. However, it does not print any output also, which should be longest line from given input. I did debug the program and I found that program is skipping 'printf()' statement. I tried both on sublime text 2 + gcc and Turbo c++ v4.5, but still I don't get an output. I'm using Windows xpsp 3.
Here is my code :
#include<stdio.h>
/* program to pring longest line using external variables */
#define MAXSIZE 1000
int max;
char line[ MAXSIZE ];
char longest[ MAXSIZE ];
int getline( void );
void copy( void );
main()
{
int len;
extern int max;
extern char longest[];
max = 0;
while( ( len = getline() ) > 0 )
{
if( len > max )
{
len = max;
copy();
}
}
if( max > 0)
printf("\n%s\n", longest); /* This line is skipped */
return 0;
}
int getline( void ) /* Check if there is line */
{
int c, i;
extern char line[];
for( i = 0; i < MAXSIZE -1 && ( c = getchar()) != EOF && c != '\n'; ++i )
line[ i ] = c;
if( c == '\n' )
{
line[ i ] = c;
++i;
}
line[ i ] = '\0';
return i;
}
void copy( void ) /* copy current line to longest if it is long */
{
int i = 0;
extern char line[];
extern char longest[];
while( ( longest[ i ] = line[ i ] ) != '\0' )
++i;
}
So my questions are :
Why is this happening?
What should I do so that program won't skip 'printf()' and will print an output?
Please help. Thank you.
The intent of this code is to start max at zero then, for every line longer than the current max, copy the line and update max to the longer value:
max = 0;
while( ( len = getline() ) > 0 )
{
if( len > max )
{
len = max;
copy();
}
}
However, the line that's supposed to update max is assigning in the wrong direction. It sets len to be the current value of max and never updates max at all. This is something that would have been obvious with a bit of "Debugging 101", placing the following line after the call to copy():
printf ("New long line, len = %d, str = '%s'\n", max, longest);
That fact that you would never have seen the length changing would have (hopefully) narrowed down the problem pretty fast. The line in question should instead be:
max = len;

How To Replace A Certain Character in C

I am writing a program that replaces characters in the user's input in C but I don't know how to replace the certain characters. Is there a certain method for C that replaces characters in a string? If you know python, then I want something a bit like this in python:
string.replace('certain_character','replacement_character')
Something like that, except for C, and not python.
This is my code that I have written so far:
#include <stdio.h>
int main(){
char str[BUFSIZ];
printf("Welcome To My Secret Language encoder!Enter some text: \n");
scanf("%s",str);
/*
Where I want to replace certain characters
*/
printf("Here is your text in secret language mode: %s \n",str);
}
I'm writing this code to learn C more, and that's why i'm not doing it in a higher level language like python.So, how do you replace certain characters in a string?
Nothing like that in C. You'll have to scan the string yourself:
#include <string.h>
char str[] = "I love cats";
int i;
for(i = 0; i < strlen(str); i++)
{
if(str[i] == 'c')
str[i] = 'b';
}
Now, if you're looking for a substring, you'll need something like strstr.
strchr finds the given character in a string, or returns NULL.
int main() {
int c;
while ( ( c = getchar() ) != EOF ) {
char const * found, * source = "abc", * dest = "xyz";
if ( ( found = strchr( "abc", c ) ) != NULL ) {
putchar( dest[ found - source ] );
} else {
putchar( c );
}
}
return 0;
}
If you have a lot of characters that you want to replace with other characters (like a Caesar cypher) you can build a lookup for yourself as follows:
#include <string.h>
char plain[] = "Hello there good people";
char encoder[26] = "ghijklmnopqrstuvwxyzabcdef";
char secret[100]; // long enough
int n = strlen(plain);
for(ii = 0; ii < n; ++ii) {
secret[ii] = encoder[(tolower(plain[ii]) - 'a')%26];
}
secret[n] = '\0';
This uses a couple of tricks:
cast all characters to lower case
subtract 'a' from the lowercase number - since a char is really just a number, we now have a == 0
Perform a modulo operation on the result so things that fall outside of the range of good characters don't cause a memory access error.
Add a '\0' at the end to make sure the string is properly terminated.
Copying things into a new string; obviously you could do an in-place replacement.
As written this will turn numbers (digits) and punctuation / symbols / spaces into characters. You could decide that anything that is not a letter is maintained - and maybe that only lower case letters are converted. In that case
#include <string.h>
char plain[] = "Hello there good people";
char encoder[26] = "ghijklmnopqrstuvwxyzabcdef";
char secret[100]; // long enough
int n = strlen(plain);
for(ii = 0; ii < n; ++ii) {
if(plain[ii] >= 'a' && plain[ii] <= 'z') {
secret[ii] = encoder[plain[ii] - 'a'];
}
else {
secret[ii] = plain[ii];
}
}
secret[n] = '\0';
there is no such function, you have to write one using strstr.
if you can use std::string, you can use string.replace()
Say you want to replace: A with z and b with X
char *replace(char *src, int replaceme, int newchar)
{
int len=strlen(src);
char *p;
for(p=src; *p ; p++)
{
if(*p==replaceme)
*p=newchar;
}
return src;
}
usage:
replace(string, 'A', 'z');
replace(string, 'b', 'X');
This is just the logic to do it, you need more statements in your code.

Resources