Shift a character forward by three spaces in C - c

Write a function that, using the strrot function,
modifies each string of the given array s out of n strings.
The function prototype is:
void rot_all(char *s[], int n);
Here's my code I only don't know how to do the last function.
char rot3(char c) // Function shifts a letter by three spaces (eg 'a' -> 'd')
{
if (c >= 'A' && c <= 'Z') return c += 3;
if (c >= 'a' && c <= 'z') return c += 3;
return c;
}
void strrot(char *str)
{
int d = strlen (str);
for (int i = 0; i < d; i++)
{
str[i] = rot3(str[i]);
}
}
void rot_all(char *s[], int n)
{
}
int main ()
{
char str[23];
scanf("%s",str);
strrot(str);
printf("%s",str);
return 0;
}

The assumption is that c is a either lower or upper case letter. Using an assert() to document this.
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char rot3(char c) {
assert(isalpha(c));
char offset = isupper(c) ? 'A' : 'a';
return offset + (c - offset + 3) % ('Z' - 'A' + 1);
}
void strrot(char *str) {
for (int i = 0; str[i]; i++) {
str[i] = rot3(str[i]);
}
}
void rot_all(char *s[], int n) {
for(int i = 0; i < n; i++) {
strrot(s[i]);
}
}
int main () {
char *strs[] = {
strdup("Hello"),
strdup("World")
};
rot_all(strs, sizeof(strs) / sizeof(*strs));
for(int i = 0; i < sizeof(strs) / sizeof(*strs); i++) {
printf("%s\n", strs[i]);
free(strs[i]);
}
return 0;
}
and the output is:
Khoor
Zruog

Related

Struggling with CS50 Readability

so I'm struggling with why I continue to get undeclared identifiers and can't seem to understand why the code isn't running properly. I'd appreciate any suggestions on how to work through this.
#include <cs50.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
int count_letters(string text);
int count_words(string text);
int count_sentences(string text);
int main(void) {
int a;
int b;
int c;
string text = get_string("Text: ");
for (int i = 0; i < strlen(text); i++) {
// Count letters
a = count_letters(text);
// Count words (between spaces), words = space + 1
b = count_words(text);
// Count sentences (# of .?! in text)
c = count_sentences(text);
}
float L = a / (float)b * 100;
float S = c / (float)b * 100;
int CLI = round((0.0588 * L) - (0.296 * S) - 15.8);
if (CLI < 1) {
printf("Before Grade 1\n");
} else if (CLI > 16) {
printf("Grade 16+\n");
} else {
printf("Grade %i\n", CLI);
}
}
int count_letters(string text) {
int letters = 0;
if (text[i] > 'a' && text[i] < 'z' || text[i] > 'A' && text[i] < 'Z') {
letters++;
}
}
int count_words(string text) {
int word = 1;
if (text[i] == ' ') {
words++;
}
}
int count_sentences(string text) {
int sentence = 0;
if (text[i] == '.' || text[i] == '?' || text[i] == '!') {
sentence++;
}
}
I defined the symbol MISSING and implemented the functionality of cs50.h you did not share with us. You can delete all but #include <cs50.h> from that first section.
You iterate over your text in main, so you only need to operate on a single letter c in your count functions (and words is incremented if there were letters but no spaces). This was your main issue.
Moved main() to the end, so you don't need the function declarations for the count functions. Used better variable names and initialized those variables. Not sure what L, S, or CLI are. It would be a good idea to define constants for your magical values (0.0588, 0.296, 15.8).
#define MISSING
#ifndef MISSING
#include <cs50.h>
#else
#include <stdio.h>
#include <stdlib.h>
typedef char * string;
#define MAX_STR 1000
// caller frees returned string
string get_string(const char *prompt) {
char *s = malloc(MAX_STR);
if(!s) return NULL;
printf("%s", prompt);
fgets(s, MAX_STR, stdin);
return s;
}
#endif
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
int count_letters(char c) {
return isalpha(c);
}
int count_words(char c) {
return c == ' ';
}
int count_sentences(char c) {
return (c == '.') || (c == '?') || (c == '!');
}
int main(void) {
string text = get_string("Text: ");
int letters = 0;
int words = 0;
int sentences = 0;
for (int i = 0; i < strlen(text); i++) {
letters += count_letters(text[i]);
words += count_words(text[i]);
sentences += count_sentences(text[i]);
}
if(!words && letters) words++;
float L = 100.0 * letters / words;
float S = 100.0 * sentences / words;
int CLI = round((0.0588 * L) - (0.296 * S) - 15.8);
if (CLI < 1) {
printf("Before Grade 1\n");
} else if (CLI <= 16) {
printf("Grade %i\n", CLI);
} else {
printf("Grade 16+\n");
}
return 0;
}

Setting individual indices of a char array equal to ints

#include <stdio.h>
int any(char s1[], char s2[]) {
//converts to lower case
int c = 'a';
int i1 = 0;
while (s1[i1] != '\0') {
if (s1[i1] >= 'A' && s1[i1] <= 'Z')
s1[i1] += 32;
++i1;
}
int i2 = 0;
while (s2[i2] != '\0') {
if (s2[i2] >= 'A' && s2[i2] <= 'Z')
s2[i2] += 32;
++i2;
}
i1 = 0;
while (s1[i1] != '\0') {
i2 = 0;
while (s2[i2] != '\0') {
if (s1[i1] == s2[i2])
return i1;
++i2;
}
++i1;
}
return -1;
}
main() {
//printf("test");
printf("%d", any("This is fun", "fin"));
}
This code causes a segmentation fault and I'm pretty sure it happens when I try to set one of the chars in the array equal to an int. How do I not get a seg fault?
You are calling any with pointers to string constants. Attempting to modify these strings invokes undefined behavior.
Also note that the prototype for main should be int main(void) or int main(int argc, char *argv[]), and main should return 0 for successful operation.
You are implementing a case insensitive version of a generalized version of strchr with multiple characters, but you should not modify the argument strings, and you should rely on the functions from <ctype.h> instead of assuming ASCII.
Here is a better version:
#include <ctype.h>
#include <stdio.h>
int any(const char s1[], const char s2[]) {
int i1 = 0;
while (s1[i1] != '\0') {
int i2 = 0;
while (s2[i2] != '\0') {
if (tolower((unsigned char)s1[i1]) == tolower((unsigned char)s2[i2]))
return i1;
++i2;
}
++i1;
}
return -1;
}
int main(void) {
//printf("test");
printf("%d", any("This is fun", "fin"));
return 0;
}

What's wrong with my CS50 Vigenere code?

I've been going round in circles with this now for a few hours. It manages the first word of the recommended test (Meet me at the park at eleven am) gets over the first spaces, gives a correct letter for m then prints several spaces before ending. Many thanks in advance.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int allstralpha();
int main(int argc, string argv[])
{
string keyw = argv[1];
if(argc == 2 && allstralpha(keyw))
{
string plaint = GetString();
int c = 0;
int kl = strlen(keyw);
int k = 0;
int p = 0;
int j = 0;
for(int i = 0, n = strlen(plaint); i < n; i++)
{
if(isalpha(plaint[i]))
{
if(isupper(keyw[j]))
{
k = keyw[(j % kl)] - 65;
if(isupper(plaint[i]))
{
p = plaint[i] -65;
c = ((k + p) % 26) + 65;
printf("%c", (char) c);
}
else if(islower(plaint[i]))
{
p = plaint[i] -97;
c = ((k + p) % 26) + 97;
printf("%c", (char) c);
}
}
else if(islower(keyw[j]))
{
k = keyw[(j % kl)] - 97;
if(isupper(plaint[i]))
{
p = plaint[i] - 65;
c = ((k + p) % 26) + 65;
printf("%c", (char) c);
}
else if(islower(plaint[i]))
{
p = plaint[i] - 97;
c = ((k + p) % 26) + 97;
printf("%c", (char) c);
}
}
j++;
}
else
{
printf("%c", (char) plaint[i]);
}
}
}
else
{
printf("Sorry that is not a vaild parameter\n");
return 1;
}
}
int allstralpha(string s)
{
for(int i = 0, n = strlen(s); i < n; i++)
{
if(!isalpha(s[i]))
{
return 0;
}
}
return 1;
}
int allstralpha();
int allstralpha(string s)
{
...
}
Your function definition and declaration don't match. You should declare int allstralpha(string s);
In first line of main:
int main(int argc, string argv[])
{
string keyw = argv[1];
...
}
First you should check if (argc > 1) before accessing argv[1]
For the actual code itself, you provide the plain text, but I can't see the keyword.
I use these values from wikipedia, vigenère cipher for testing:
Plaintext: ATTACKATDAWN
Key: LEMONLEMONLE
Ciphertext: LXFOPVEFRNHR
Minimum code to finish this:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, const char* argv[])
{
const char *str = "Meet me at the park at eleven am";
const char *key = "bacon";
int keylen = strlen(key);
int len = strlen(str);
for (int i = 0, j = 0; i < len; i++)
{
int c = str[i];
if (isalnum(c))
{
//int k = function of key and `j`...
//offset k...
if (islower(c))
{
c = (c - 'a' + k) % 26 + 'a';
}
else
{
c = (c - 'A' + k) % 26 + 'A';
}
j++;
}
putchar(c);
}
putchar('\n');
return 0;
}

Hex/Dec Program in C getting the wrong output and cant use Scanf

Whenever I run my program, I think that I am getting the wrong output using the included test strings, though I think my first function is working. Tthe files I have are xbits.c xbits.h and two versions of showxbits.c, one that is instructor provided and the other is the one I am trying to use scanf with. The program is supposed to convert an integer to a hex string and then a hex string to an integer. My main problem is, while I think that my code works with the instructor test input, I know it doesn't work with the scanf showxbits because it gives answers such as 0xS when 127 is inputed.
Here is the xbits.c
#include <stdio.h>
#include <math.h>
int hex_To_dec(int c) {
char hex_values[] = "aAbBcCdDeEfF";
int i;
int answer = 0;
for (i=0; answer == 0 && hex_values[i] != '\0'; i++) {
if (hex_values[i] == c) {
answer = 10 + (i/2);
}
}
return answer;
}
/* function represents the int n as a hexstring which it places in the
hexstring array */
void itox(char* s, int n)
{
char *digits = "0123456789ABCDEF";
int i=0,j;
char temp;
while(n > 0)
{
s[i] = digits[n % 16];
n /= 16;
i++;
}
s[i] = '\0'; // Add null terminator
i--;
// Now reverse it in place
for(j=0; j < i / 2; j++)
{
temp = s[j];
s[j] = s[i - j];
s[i - j] = temp;
}
}
/* function converts hexstring array to equivalent integer value */
int xtoi(char hexstring[]) {
//printf("in xtoi, processing %s\n", hexstring);
int answer = 0;
int i = 0;
int valid = 1;
int hexit;
if (hexstring[i] == '0') {
++i;
if (hexstring[i] == 'x' || hexstring[i] == 'X') {
++i;
}
}
while(valid && hexstring[i] != '\0') {
answer = answer * 16;
if(hexstring[i] >='0' && hexstring[i] <= '9') {
answer = answer + (hexstring[i] - '0');
}
else {
hexit = hex_To_dec(hexstring[i]);
if (hexit == 0) {
valid = 0;
}
else {
answer = answer + hexit;
}
}
++i;
}
if(!valid) {
answer = 0;
}
return answer;
}
Here is the showxbits.c provided by the instructor:
/*
* stub driver for functions to study integer-hex conversions
*
*/
#include <stdio.h>
#include <string.h>
#include "xbits.h"
#define ENOUGH_SPACE 1000 /* not really enough space */
int main() {
char hexstring[ENOUGH_SPACE];
int m=0, n = 0x79FEB220;
itox(hexstring, n);
/* for stub testing: create a fake input string */
strcpy(hexstring, "6BCD7890");
m = xtoi(hexstring);
printf("\t%12d %s %12d\n", n, hexstring, m);
return 0; /* everything is just fine */
}
And here is the showxbits that has scanf in it:
/*
* stub driver for functions to study integer-hex conversions
*
*/
#include <stdio.h>
#include <string.h>
#include "xbits.h"
#define ENOUGH_SPACE 100 /* not really enough space */
int main() {
char hexstring[ENOUGH_SPACE];
//int m=0, n = 0x79FEB220;
int n, m;
while ((scanf("%d", &n)) == 1) {
itox(hexstring, n);
m = xtoi( hexstring);
printf("%12d %s %12d\n", n, hexstring, m);
}
return 0; /* everything is just fine */
}
Like I said, I am getting weird outputs when using the scanf function. I am a complete beginner programmer and would really appreciate any help that can be offered. Thanks!
Because there is a mistake in the function itox , which would cause the wrong result when reverse string. Then, the wrong hexstring from itox will result in the abnormal output finally.
The quick fix is to replace j < i / 2 with j < i / 2 + 1
void itox(char* s, int n)
{
//......
// Now reverse it in place
for(j=0; j < i / 2 + 1 ; j++)
{
temp = s[j];
s[j] = s[i - j];
s[i - j] = temp;
}
}
You don't need to reverse the string to convert to hex ascii:
#include <stdio.h>
const char* hexlat="0123456789ABCDEF";
char *binaryToHex(unsigned int answer, char *result){
if(answer==0) return result;
else{
result=binaryToHex(answer>>4,result);
*result=hexlat[answer & 0x0F];
return result+1;
}
};
int main(void) {
unsigned int answer=0x12340ADF;
char hexAnswer[32];
*binaryToHex(answer,hexAnswer)='\0';
printf("%s",hexAnswer);
return 0;
}

Strange unwanted three digit code printouts from caesar cipher

The cipher code actually works; it's just that I get some odd three digit codes separated with slashes too.
Any help would be greatly appreciated. Here's my code.
The codes look like this but have random numbers /354/233/645/810/236
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cs50.h"
int i, len;
string sentance, encrypted;
int k, argvLen;
int caesar (int k){
printf("Hi I'm Ceaser! What would you like me to cipher?\n");
sentance = GetString();
len = strlen(sentance);
char encrypted[len];
for (i=0; i<len; i++) {
if (sentance[i] >='a' && sentance[i] <='z') {
encrypted[i] = ((sentance[i] - 'a' + k) % 26) + 'a';
}
else if (sentance[i] >='A' && sentance[i] <='Z') {
encrypted[i] = ((sentance[i] - 'A' + k) % 26) + 'A';
}
else if (sentance[i] >=' ' && sentance[i] <= '#'){
encrypted[i] = sentance[i];
}
}
printf("%s", encrypted);
return 0;
};
int main (int argc, const char * argv[]) {
if (argc==2) {
k = atoi(argv[1]);
argvLen = strlen(argv[1]);
for (i=0; i<argvLen; i++){
if (isdigit(argv[1][i])){
caesar(k);
}
else {
printf("please enter a number for the key!");
return 1;
}
}
return 0;
}
};
You are not terminating the encrypted string properly.
You need:
To make sure you have room for the terminating character, by using char encrypted[len + 1];.
encrypted[len] = '\0'; after the loop.

Resources