How to add 1 to each letter in a string and print? - c

I am trying to access each character in a string and add 1 to it before printing out the text. Eg. my code will prompt the user for a text ie. hello and it should print that text plus 1 character(i.e. output "ifmmp" when the input is "hello"). From my code below, instead of a for loop, I am trying to use a while loop to do this however I am running into some issues and it doesn't seem to print the response. Any help greatly appreciated.
// Libraries
#include <cs50.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, string argv[])
{
// If
if (argc == 2 && (atoi(argv[1]) > 0))
for(int i = 0, len = strlen(argv[1]); i < len; i++)
{
char n = argv[1][i];
int digit = isdigit(n);
if (!digit)
{
printf("Usage: ./caesar key\n");
return 1;
}
else
{
string plain = get_string("plaintext: ");
int k = 0;
int len_plain = strlen(plain);
while (len_plain > k)
k++;
char cipher = plain[k];
{
printf("%c\n", cipher);
}
}
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}

Your question seems to be:
am trying to access each character in a string and add 1 to it before printing out the text
That can be done in many different ways - here is one example:
#include <stdio.h>
int main(void) {
char str[10] = "hello";
int i = 0;
while(str[i])
{
++str[i]; // Add 1
++i;
}
printf("%s\n", str);
return 0;
}
Output:
ifmmp

Related

cs50 - Caesar Cipher - I keep seeing this, error handling non numeric key

I'm working on project work and when I try checking if I've got everything in the code as expected, I see this error,
handles non-numeric key
timed out while waiting for the program to exit.
The code decrypts words or letters being passed into the input with a key. (I just thought I should let you know about that)
here is my actual code. everything seems right except that error code I keep getting each time I check to see all went well.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
//declaration of function prototype
bool only_digits(string s);
char rotate(char c, int n);
int main(int argc, string argv[])
{
// string s = argv[1];
//command line argument
if(argc != 2 || !only_digits(argv[1]))
{
printf("Usage: ./caesar key\n");
return 1;
}
//convert argv[1] to an int
int key = atoi(argv[1]);
//prompt user for plaintext
string text = get_string("plaintext: ");
//output of plaintext
printf("ciphertext: ");
for(int i = 0; text[i]; i++)
{
text[i] = rotate(text[i], key);
printf("%c", text[i]);
}
printf("\n ");
return 0;
}
bool only_digits(string s)
{
for(int i = 0; i < strlen(s); i++)
{
//check whether the character inputed is a digit 0 - 9
if(isdigit(s[i]))
{
return true;
}
else{
return false;
}
}
return false;
}
char rotate(char c, int n)
{
char cipher_text = c;
if(islower(c))
{
cipher_text = 'a' + ((c - 'a') + n) % 26;
return cipher_text;
}
else if(isupper(c))
{
cipher_text = 'A' + ((c - 'A') + n) % 26;
return cipher_text;
}
return cipher_text;
}
any help will be much appreciated.
Here is a working self-contained solution. It hard-codes the clear text:
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
bool only_digits(const char *s);
char rotate(char c, int n);
int main(int argc, char *argv[]) {
if(argc != 2 || !only_digits(argv[1])) {
printf("Usage: ./caesar key\n");
return 1;
}
int key = atoi(argv[1]);
char *cleartext = "test";
printf("ciphertext: ");
for(; *cleartext; cleartext++) {
printf("%c", rotate(*cleartext, key));
}
printf("\n");
return 0;
}
bool only_digits(const char *s) {
for(; *s && isdigit(*s); s++);
return !*s;
}
char rotate(char c, int n) {
#define ROTATE2(a, c, n) (a) + (((c) - (a)) + (n)) % 26
if(islower(c)) {
return ROTATE2('a', c, n);
}
if(isupper(c)) {
return ROTATE2('A', c, n);
}
return c;
}
It fixes the only_digits() to look at all characters unless s contains a non-digit in which case it would fail early. Simplified the rotate a bit using a macro to avoid the duplicate code. You could write a 2nd function instead of the macro if you so choose.

Struggling with wraparound counting in C

I'm a newbie, so apologies if I don't explain myself well. If it helps, I'm doing this for the Caesar problem set as part of the Harvard CS50x OpenCourseWare.
I'm trying to convert user generated plain text to cipher text using a simple key. To accomplish this I'm attempting to use a wraparound counting formula in my last function. However, sometimes I get blanks that print out instead of the new characters... Help!
EDIT: I'm using a key of 5 and the plaintext "Helloz!" to test. Expect to see Mjqqte!
instead am seeing blank spaces.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
int convert(string n);
string k, text;
char text;
int r, c, t,x;
bool validate(string n);
//int encrypted(string n);
int main(int argc, string argv[])
{
//accept single command-line argument, non negative integer, k with appropriate error
k = argv[1];
if (argc > 1 && argc <= 2)
{
//printf("Success\n%s\n", argv[1]);
// print individual characters of argv[i]
validate(k);
}
else //if wrong input then print error message and main should return 1
{
printf("Usage: ./caesar key\n");
return 1;
}
text = get_string("plaintext:");
t = atoi(k);
printf("%i\n", t);
convert (text);
printf("\n");
}
//output "ciphertext:" without a newline, with the characters roated by k positions
//after output, print a newline and exit by returning 0 from main
bool validate(string n)
{
for (int i = 0; k[i] != '\0'; i++)
{
if (48 <= k[i] && k[i] <= 57)
{
//printf("%c\n", k[i]);
}
else
{
printf("./caesar key\n");
return 1;
// save for later: printf("%s \n", k);
}
}
return r;
}
int convert(string n)
{
//if fits within a range, Reads individual characters
for (int i = 0; i < text[i]; i++)
{
if (isalpha(text[i]))
{
x = text[i];
//printf("%i\n", x);
c = (x+t) % 26;
// printf("%i\n",c);
printf("%c", c);
}
else
{
printf("%i", text[i]);
}
}
return 0;
}
Here's an implementation that could work for you:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void convert(char *text, unsigned char k) {
for (unsigned int i = 0; i < strlen(text); i++) {
if (isalpha(text[i])) {
// Contains the 3 leftmost bits, containing the uppercase/lowercase part.
char c = (text[i] / 32) * 32;
// Perform the shifting with modulo on the alphabetic index of the letter.
text[i] = c + ((text[i] % 32) + k) % 26;
}
}
}
int main(int argc, char *argv[]) {
unsigned char k = strtol(argv[1], NULL, 10);
char text[64];
printf("Using key %d.\n", (int) k);
printf("Plaintext: ");
fgets(text, 64, stdin);
// Remove newline.
text[strlen(text) - 1] = 0;
convert(text, k);
printf("Ciphertext: %s.\n", text);
return 0;
}
Test run:
>>> cipher 4
Using key 4.
Plaintext: Test mE Right Away!!1
Ciphertext: Xiwx qI Vmklx Eaec!!1.

Segmentation fault in C while using isdigit() and argc

I am having the following issue: Segmentation fault (core dumped).
I looked around at the other questions on StackOverflow and didn't see the correct answer to my question. Here is my code :
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("missing command-line argument\n");
return 1;
}
for (int i = 0; i < argc; i++)
{
printf("Made it inside");
if (isdigit(argv[i]) == 0)
{
return 1;
}
}
string plain_text = get_string("plaintext: ");
int key = atoi(argv[1]); //function to convert a string to int.
for (int i = 0, n = strlen(plain_text); i < n; i++)
{
int c = (int) plain_text[i];
c += key;
printf("%c", c);
}
printf("\n");
return 0;
}
The error is coming from "if (isdigit(argv[i]) == 0)".
EDIT:
Here is the solution, thanks all!
for (int i = 0; i < strlen(argv[1]); i++)
{
if (isdigit(argv[1][i]) == 0)
{
return 1;
}
}
You are passing a string which is actually a char * to isdigit. You need to pass the first character of the string instead
isdigit(*argv[i][0])
isdigit expects an int, you're giving it a string (actually a null terminated group of chars)
http://pubs.opengroup.org/onlinepubs/009696699/functions/isdigit.html
While the behavior is listed as "undefined" in this case, I'm not actually sure why you would get a segfault from it.

Vigenere Cipher. Code output

I've been working on cs50 pset2, and I thought I had the vigenere cipher down after working on it for a few days. This code is meant to take an alphabetical argument(argv[]) given by the user, and use that as a key to crypt a phrase given by the user(string) by its number in the alphabetical index. For example, if you give the argument 'abc' and the string 'cat' then the output should be 'cbv'(a moving 0, b moving 1, c moving 2) The argument should also wrap around so that if the string is longer, the argument will wrap to its first character and continue until the string has ended.
This is what I have for code:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[])
{
if(argc != 2)
{
printf("Try again\n");
return 1;
}
string k = (argv[1]);
int klen = strlen(k);
for(int x = 0; x < klen; x++)
{
if(isalpha(k[x]))
{
if(isupper(k[x]))
{
k[x] = tolower(k[x]);
}
k[x] -= 'a';
}
else
{
printf("Try again\n");
return 1;
}
}
string code = GetString();
int clen = strlen(code);
for(int a = 0, b = 0; a < clen; a++)
{
if(isalpha(code[a]))
{
int key = k[b%klen];
if(isupper(code[a]))
{
printf("%c", (((code[a] - 'A') + key)%26) + 'A');
b++;
}
else
{
printf("%c", (((code[a] - 'a') + key)%26) + 'a');
b++;
}
}
else
{
printf("%c", code[a]);
}
}
printf("\n");
}
The code seems to work for the length of the key +1.
For example,
I input an argument of 'aaaa'
Then input a string of 'bbbbb'
and receive 'bbbbb' correctly.
However, if I input the same 'aaaa'
Then input a string longer than the key +1 'bbbbbbb'
I receive 'bbbbbNN'
I believe I have an issue with my order of operations but have tried moving parenthesis around to no avail. I was hoping someone could point me in the right direction as to why my key isn't wrapping properly.
Your biggest risk with code like this is all the similar, repetitive clauses. A bug in just one is hard to track done. And doing any processing on the key, while processing the code, is just inefficient.
Here's a rework that completely processes the key before processing the code and tries to get the processing down to just one case. See if it works any better for you:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
fprintf(stderr, "Try again\n");
return EXIT_FAILURE;
}
string key = strdup(argv[1]);
size_t key_length = strlen(key);
for (int x = 0; x < key_length; x++)
{
if (isalpha(key[x]))
{
if (isupper(key[x]))
{
key[x] = tolower(key[x]);
}
key[x] -= 'a';
}
else
{
fprintf(stderr, "Try again\n");
return EXIT_FAILURE;
}
}
string code = GetString();
int code_length = strlen(code);
for (int a = 0, b = 0; a < code_length; a++)
{
if (isalpha(code[a]))
{
int start = isupper(code[a]) ? 'A' : 'a';
printf("%c", (((code[a] - start) + key[b++ % key_length]) % 26) + start);
}
else
{
printf("%c", code[a]);
}
}
printf("\n");
free(key);
return EXIT_SUCCESS;
}

C - Better method for replacing

I'm looking to replace words from a file where words.txt contains "banana test apple" would output -> "banana Replaced! apple" The words it would be looking to replace would come as an argument to stdin ("test" in this case)
Not sure where my code is going wrong, and I'm also wondering if there's a better way to do it than get getchar() function, as I find it confusing to work with, and annoying as you cannot backup characters.
Any suggestions? Thanks
$ ./a.exe test < words.txt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
int c = getchar();
int counter = 0;
int i,index;
for (i = 1; i < argc; i++){
for (index = 0; index < strlen(argv[i]); index++){
while (c == argv[i][index]){
counter++;
c = getchar();
index++;
if (counter == strlen(argv[i])){
printf("Replaced!");
}
}
printf("%c ",c);
c = getchar();
counter = 0;
}
}
return (0);
}
I would do it as follows :
read all the file into a buffer using fgets
looking for the key work (test) using strstr
replace it with your new string using strncpy
write to file (or output to stdout) whatever you want to do
You could use scanf to read in a word at a time:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char wordbuffer[100];
while (scanf("%99s", wordbuffer) == 1)
{
int replace = 0;
for (int i = 1; i < argc && !replace; i++)
if (strcmp(wordbuffer, argv[i]) == 0)
replace = 1;
if (replace)
printf("Replaced! ");
else
printf("%s ", wordbuffer);
}
}
If you are using a modern system that compliant with the latest POSIX specification, you can take advantage of the m assignment-allocation character, and have the appropriate amount of space allocated for you, so that you don't have to use some arbitrary maximum number of characters.
int main(int argc, char *argv[])
{
char *wordbuffer;
while (scanf("%ms", &wordbuffer) == 1)
{
int replace = 0;
for (int i = 1; i < argc && !replace; i++)
if (strcmp(wordbuffer, argv[i]) == 0)
replace = 1;
if (replace)
printf("Replaced! ");
else
printf("%s ", wordbuffer);
free(wordbuffer);
}
}

Resources