Segmentation fault in substitution ciphertext - c

I am implementing a substitution ciphertext scheme. It's an assignment
from the CS50 course.
The input are the substitution scheme and the plaintext and the
program should write back the ciphertext.
$ ./encrypt QWERTYUIOPASDFGHJKLZXCVBNM HE
IT
I keep getting segmentation fault and I am not sure why. This is the source of my solution.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int result (string words);
int main (int argc, string argv[])
{
if (argc == 2)
{
if (strlen (argv[1]) == 26)
{
int k = 0;
for (int i = 0; i<strlen(argv[1]); i++)
{
if (((int)argv[1][i] > 64 && (int)argv[1][i] < 91) || ((int)argv[1][i] > 96 && (int)argv[1][i] < 123))
{
k +=1;
}
}
if (k==26)
{
char new_var[strlen(argv[1])];
for (int j = 0, n = strlen(argv[1]); j < n; j++)
{
new_var[j] = toupper((char)argv[1][j]) ;
}
string key = new_var;
printf ("%i", result(key));
if (result (key) == 3)
{
string word = get_string("plaintext: ") ;
char mutated_word [strlen(word)];
for (int i = 0; word[i] != '\0'; i++)
{
if ((int)word[i]>64 && (int)word[i]<91)
{
mutated_word[i] = key[(int)word[i] - 65] ;
}
else if ((int)word[i]>96 && (int)word[i]<123)
{
mutated_word[i] = (char) ((int)(key[(int)word[i]-97]) + 32) ;
}
else
{
mutated_word[i] = word[i] ;
}
}
printf("ciphertext: %s\n", mutated_word);
return 0;
}
else
{
printf ("Usage: ./substitution keya\n");
return 1;
}
}
else
{
printf ("Usage: ./substitution keyb\n");
return 1;
}
}
else
{
printf ("Usage: ./substitution keyc\n");
return 1;
}
}
else
{
printf ("Usage: ./substitution keyd\n");
return 1;
}
}
int result (string words)
{
int conclusion = 3;
for (int j = 0; j< strlen(words) - 1 ; j++)
{
for(int i =j+1; i<strlen(words) - 1; j++)
{
if ((int)words[i] == (int)words[j])
{
conclusion = 4;
}
}
}
return conclusion;
}

Check your 'Result' function
In it, check your 2nd for loop...
int result (string words)
{
int conclusion = 3;
for (int j = 0; j< strlen(words) - 1 ; j++)
{
for(int i =j+1; i<strlen(words) - 1; j++)
{
if ((int)words[i] == (int)words[j])
{
conclusion = 4;
}
}
}
return conclusion;
}
Don't think you have replaced 'i' with 'j'. j++
No Segmentation fault
Then it will not show segmentation fault, pls check your code thoroughly always.

Related

Why does this code return junk values along with the right output?

I was writing a program that would act as a Caesar Cipher encoder. However for only single letter inputs, the encrypted charecter is sometimes returned along with junk charecters.
#include<stdio.h>
#include<cs50.h>
#include<string.h>
int check_validity(string);
int atoi(string);
void cipher(int ,string, int);
int main(int argc, string argv[])
{
if(argc == 2)
{
check_validity(argv[1]);
if(check_validity(argv[1]) == 0)
{
string c = get_string("plaintext: ");
int key = atoi(argv[1]);
int cipher_key = key%26;
int length = strlen(c);
cipher(cipher_key, c, length);
return 0;
}
else printf("Usage: ./caesar key\n");
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
int check_validity(string w)
{
int j = 0;
string a;
for(int i = 0;w[i] != 0; i++)
{
if(w[i]<47 || w[i]>58)
{
j++;
}
}
return j;
}
int atoi(string w)
{
int number = 0;
for (int i = 0; w[i] != 0; i++)
{
number = number*10 + (w[i]-'0');
}
return number;
}
void cipher(int x, string q, int l)
{
char b[l];
for(int i=0; q[i] != 0; i++)
{
if(q[i]>64 && q[i]<91)
{
if(q[i]<91-x)
{
b[i] = q[i] + x;
}
else b[i] = q[i] + x - 26;
}
else if(q[i]>96 && q[i]<123)
{
if(q[i]<123-x)
{
b[i] = q[i] + x;
}
else b[i] = q[i] + x - 26;
}
else b[i] = q[i];
}
printf("ciphertext: %s\n",b);
}
Input:
./caesar 1
plaintext: a
Output 1:
b
Output 2:
b>
Output 3:
b2
Changing the key lends the same problem. However this seems to be absent for all other string of letters entered.

CS50 Vigenere's Cipher: Can't fix the problem with the spaces in the plaintext

I'm having a problem with my code, which is supposed to be the
Vigenere's cipher from Harvard's CS50 program. I have met all the
requirements, except when the key is "baz" and the plaintext is "hello,
world!". Because there is a comma and a space, my code accepts that, and
shifts from z to a to b, etc. I want it to ignore the spaces and
punctuation so that the "b" "a" "z" only change for the characters.
You should only have to look at the first "else if" line, as that is
when the plaintext is longer than the key, and the key will have to
alternate.
Please help! I've been on this problem for hours, and I can't figure out
the solution.
https://gyazo.com/3a7b3e692d210262ae15f580b10f296d
https://gyazo.com/0b25bfc010d937840f09ff4294d0dd41
https://gyazo.com/c1b85208ecae1b9ad57d48d5b5af59b5
This is my code:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
int main(int argc, string argv[])
{
if (argc == 2)
{
string key = argv[1];
int key_length = strlen(key);
for (int i = 0; i < key_length; i++)
{
key[i] = toupper(key[i]);
}
for (int k = 0; k < key_length; k++)
{
if (key[k] < 'A' || key[k] > 'Z')
{
printf("Not a valid key!\n");
return 1;
}
}
for (int i = 0; i < key_length; i++)
{
key[i] = key[i] - 'A';
}
string plain = get_string("Plaintext: ");
int plain_length = strlen(plain);
if (key_length == plain_length)
{
for (int i = 0; i < key_length; i++)
{
if (islower(plain[i]))
{
for (int q = 0; q < key[i]; q++)
{
plain[i]++;
if (plain[i] > 'z')
{
plain[i] = 'a';
}
}
}
if (isupper(plain[i]))
{
for (int q = 0; q < key[i]; q++)
{
plain[i]++;
if (plain[i] > 'Z')
{
plain[i] = 'A';
}
}
}
}
printf("ciphertext: %s\n", plain);
}
else if (key_length < plain_length)
{
float truncate_not = plain_length / key_length;
int truncate = trunc(truncate_not);
int mod = strlen(plain) % key_length;
for (int i = 0; i < truncate; i++)
{
for (int k = 0; k < key_length; k++)
{
int pos = k + (i * key_length);
if (islower(plain[pos]))
{
for (int q = 0; q < key[k]; q++)
{
plain[pos]++;
if (plain[pos] > 'z')
{
plain[pos] = 'a';
}
}
printf("%c\n", plain[pos]);
}
else if (isupper(plain[pos]))
{
for (int q = 0; q < key[k]; q++)
{
plain[pos]++;
if (plain[pos] > 'Z')
{
plain[pos] = 'A';
}
}
printf("%c\n", plain[pos]);
}
else
{
printf("error\n");
}
}
}
for (int j = 0; j < mod; j++)
{
int pos = j + (truncate * key_length);
if (islower(plain[pos]))
{
for (int q = 0; q < key[j]; q++)
{
plain[pos]++;
if (plain[pos] > 'z')
{
plain[pos] = 'a';
}
}
}
else if (isupper(plain[pos]))
{
for (int q = 0; q < key[j]; q++)
{
plain[pos]++;
if (plain[pos] > 'Z')
{
plain[pos] = 'A';
}
}
}
else
{
plain[j] = plain[j];
}
}
printf("ciphertext: %s\n", plain);
}
else
{
int mod = plain_length % key_length;
for (int i = 0; i < mod; i++)
{
if (islower(plain[i]))
{
for (int q = 0; q < key[i]; q++)
{
plain[i]++;
if (plain[i] > 'z')
{
plain[i] = 'a';
}
}
}
if (isupper(plain[i]))
{
for (int q = 0; q < key[i]; q++)
{
plain[i]++;
if (plain[i] > 'Z')
{
plain[i] = 'A';
}
}
}
}
printf("ciphertext: %s\n", plain);
}
}
else
{
printf("Incorrect number of arguments!\n");
return 1;
}
}
Actual results: iekmo, wnslc!
Expected results: iekmo, vprke!
As you can see, my code shifted the "baz", when it shouldn't have in the
space and comma places.
The overriding problem in this program is tying key_length to plain_length. They are discrete and must be treated separately; they "move" at different rates and should use separate and distinct indices.
First I suggest you rewatch the walkthrough. You probably want to write out (yes, pencil and paper) the "baz" example using the same format that Zamyla does with the "panda" example. And then write pseudo-code.
You will probably have to abandon much of the code you have written; generally this pset can be done with one loop that cycles through the plaintext by index, and then manages the keyword index independently within that loop.

Print the correct Morse code for alpha entry

I now need to output the Morse code equivalent of alphanumeric input. My condition for check this is an if loop: I try to look at each element of input array with each element of the alpha array but a match never seems to be found. I am not sure if I am using the correct method. I try to de-reference the point to input and compare the value with each element of alpha until a match is found. If no match is found then an error occurs.
Not working:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
int main(void)
{
char *morse[] = {"/",
".-","-...","-.-.","-..",".","..-.","--","....","..",".---",
"-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-",
"..-","...-",".--","-..-","-.--","--..",
"-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
char *alpha[]= {" ",
"A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y", "Z",
"0", "1","2","3","4","5","6","7","8","9"};
char *print_array[50];
int print_array_index = 0;
char hold[50];
int hold_index = 0;
char input[200];
int i = 0;
printf("welcome to the Morse translator.\n");
printf("Enter input: ");
fgets(input, sizeof(input), stdin);
char *p;
for (p=input; *p !='\0';++p)
{
*p = toupper(*p);
}
if (input[0]=='-' || input[0]=='.')
{
while (input[i] !='\0') {
if (input[i] ==' ' || input[i] == '\n')
{
hold[hold_index] = '\0';
bool found = false;
for (int x = 0; x < sizeof(morse) / sizeof(char *); x++)
{
if (strcmp(morse[x], hold) == 0)
{
print_array[print_array_index++] = alpha[x];
found = true;
break;
}
}
if (!found)
{
fprintf(stderr, "invalid Morse code!\n");
}
hold_index = 0;
}
else
{
hold[hold_index++] = input[i];
}
i++;
}
for (int x = 0; x < print_array_index; x++)
{
printf("%s", print_array[x]);
}
printf("\n");
}
else if (isalnum(input[0]))
{
while (input[i]!='\0')
{
if (input[i] ==' ' || input[i] == '\n')
{
bool found = false;
for (int x=0; x < sizeof(alpha)/sizeof (char*);x++)
{
if (alpha[x]==input[i])
{
print_array [print_array_index++] = alpha[x];
found = true;
break;
}
}
if (!found)
{
fprintf(stderr, "Invalid input!\n");
}
hold_index = 0;
}
i++;
}
for (int x=0; x < print_array_index; x++)
{
printf("%s",print_array[x]);
}
printf("\n");
}
return 0;
}
part of else if (isalnum(input[0])){ should be something like
else if (isalnum(input[0])){
while (input[i]!='\0' && input[i]!='\n'){
bool found = false;
for (int x=0; x < sizeof(alpha)/sizeof(char*);x++){
if (*alpha[x]==input[i]){
print_array[print_array_index++] = morse[x];
found = true;
break;
}
}
if(!found){
fprintf(stderr, "Invalid input!\n");
}
i++;
}
for (int x=0; x < print_array_index; x++){
printf("%s", print_array[x]);
}
printf("\n");
}

segmentation fault anagram project

Hey guys im working on this project. It wants me to find anagrams. My code works when im writing like 2 sentences. But it shows me a segmentation fault if i write more sentences then 5. I tried to find the problem but i cant figure it out. can some one check it for me? here is my code. Thanks alot!
int klinkercheck(char z)
{
if (z =='a')
return 1000;
else if (z == 'e')
return 10000;
else if (z == 'i')
return 100000;
else if (z == 'o')
return 1000000;
else if (z == 'u')
return 10000000;
else if (z == 10)
return 0;
else if (z == '.' || z== ' ')
return 0;
else
return 1;
}
int main()
{
int a,k,i,m,l,*tablecost,*testcost;
int **table, **test, **result;
char character;
scanf("%d",&a);
table = (int **)malloc(sizeof(int)*a);
tablecost = (int *)malloc(sizeof(int)*a);
for(k=0; k<a; k++) {
table[k]= (int *)malloc(sizeof(int)*26);
/*printf("tablecost = %d",tablecost[k]);*/
}
for(k=0; k<a; k++) {
for(i=0; i<2; i=i) {
scanf("%c",&character);
tablecost[k]= tablecost[k]+klinkercheck(character);
if(character=='.') {
/*printf("%d\n",k);*/
break;
} else if(character < 97) {
/* do nothing*/
} else {
table[k][character%97]++;
}
}
}
scanf("%d",&m);
test = (int **)malloc(sizeof(int)*m);
result = (int **)malloc(sizeof(int)*m);
testcost = (int *)malloc(sizeof(int)*m);
for(k=0; k<m; k++) {
test[k]= (int *)malloc(sizeof(int)*26);
result[k] = (int *)malloc(sizeof(int)*a);
}
for (k = 0 ; k < m ; k++) {
testcost[k]=0;
for(i=0; i<20; i=i) {
scanf("%c",&character);
testcost[k] =testcost[k]+klinkercheck(character);
if(character=='.') {
break;
} else if(character < 97) {
/* do nothing*/
} else {
test[k][character%97]++;
}
}
}
for (i = 0 ; i < m ; i++) {
for (k = 0 ; k < a ; k++) {
if (testcost[i] == tablecost[k]) {
for (l = 0 ; l < 26 ; l++) {
if (test[i][l] != table[k][l]) {
break;
} else if (l == 25) {
printf("%d ", k + 1);
}
}
}
}
printf("\n");
}
return 0;
}
table = (int **)malloc(sizeof(int)*a);
should be
table = malloc(sizeof(int *)*a);
and also
test = malloc(sizeof(int *)*m);
result = malloc(sizeof(int *)*m);
Dont cast malloc()
Unless sizeof(int)==sizeof(int*) on your platform the line:
table = (int **)malloc(sizeof(int)*a);
Will cause trouble. Use:
table = malloc(sizeof(*table)*a);
NB: Old boys get ventilated about casting the return of malloc().

Calculating characters apperances in a row

Program i've wrote is calculating how many times each letter appears in a string. I want to change it that it will find the character that appears the great amount of times in a row i.e. for the string "aabbbcccca" i want to printf "c" (as there are four c in a row and only two a and three b).
How to change my program that it will do the things i want? I am looking for the solution that will be as simple as possible and I want to use the existing code as much as possible.
#include "stdafx.h"
#include "string.h"
#include "ctype.h"
int count_nonspace(const char* str)
{
int count = 0;
while (*str)
{
if (!isspace(*str++))
count++;
}
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[127];
int i = 0, j = 0, count[127] = { 0 };
char string[100] = "Hello world";
for (i = 0; i < strlen(string); i++)
{
for (j = 33; j<127; j++)
{
if (string[i] == (j))
{
count[j]++;
}
}
}
for (j = 0; j< 127; j++)
{
if (count[j] > 0)
if (j < ' ' + 1)
printf("\n%d -> %d", count[j], j);
else
printf("\n%d -> %c", count[j], char(j));
}
}
My idea for changing the code is the following (posted only the changed part):
but still results are not as anticipated, why is that?
for (i = 0; i < strlen(string); i++)
{
for (j = 33; j<127; j++)
{
if (string[i] == (j))
{
count[j]++;
if (string[i] == string[i + 1])
count[j]++;
else
best[j] = count[j];
}
}
}
#include "stdafx.h"
#include "string.h"
#include "ctype.h"
int count_nonspace(const char* str)
{
int count = 0;
while (*str)
{
if (!isspace(*str++))
count++;
}
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[127];
int i = 0, j = 0, count[127] = { 0 };
int cur_count = 1; /* Gets compared with value in count[] */
char cur_char = '\0';
char string[100] = "Hello world";
for (i = 0; i < strlen(string); i++)
{
if(cur_char == string[i])
{
cur_count++;
}
else
{
if(32 < cur_char && cur_char < 127)
{
if(cur_count > count[cur_char])
{
count[cur_char] = cur_count;
}
}
cur_char = string[i];
cur_count = 1;
if(32 < cur_char && cur_char < 127)
{
if(!(count[cur_char]))
{
count[cur_char] = cur_count;
}
}
}
}
/* Find the most consecutive char and print it. */
char max_char = '\0';
int max_count = 0;
for(j = 0; j < 127; j++)
{
if(max_count < count[j])
{
max_count = count[j];
max_char = j;
}
}
printf("%c\n", max_char);
}

Resources