CS50 - pset2 - Vigenere - vigenere

I am currently struggling with pset2, specifically with vigenere.
Here is my code :
# include <cs50.h>
# include <ctype.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
int main (int argc, string argv[])
{
//Assess the fact that there is only 1 command line argument
if(argc != 2)
{
printf("You should only have 1 command line argument !\n") ;
return 1 ;
}
string k = argv[1] ;
int klength = strlen(k) ;
for(int i = 0; i < klength; i++)
{
if(!isalpha(k[i]))
{
printf("Please make sure the argument is only composed of alphabetical characters\n") ;
return 1 ;
}
}
//Get the text to be crypted
string s = GetString() ;
int slength = strlen(s) ;
//Deliver the crypted text
for( int i = 0, j = 0 ; i < slength ; i++)
{
int kindex = j % klength ;
if(isalpha(s[i]))
{
if(isupper(s[i]))
{
if(isupper(k[kindex]))
{
int crypt = (((s[i] - 'A') + (k[kindex] - 'A') % 26)) + 'A' ;
printf("%c", crypt ) ;
}
else
{
int crypt = (((s[i] - 'A') + (k[kindex] - 'a')) % 26) + 'A' ;
printf("%c", crypt ) ;
}
}
if(islower(s[i]))
{
if(isupper(k[kindex]))
{
int crypt = (((s[i] - 'a') + (k[kindex] - 'A')) % 26) + 'a' ;
printf("%c", crypt) ;
}
else
{
int crypt = (((s[i] - 'a') + (k[kindex] - 'a')) % 26) + 'a' ;
printf("%c", crypt ) ;
}
}
j++ ;
}
else
{
printf("%c" , s[i]) ;
}
}
printf("\n") ;
return 0 ;
}
With check50, here are the errors I receive :
:( encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword
\ expected output, but not "CakGon\n"
:( encrypts "BARFOO" as "CAQGON" using "BAZ" as keyword
\ expected output, but not "CAkGOh\n"
Here is my sandbox : sandbox
I don't understand why the two outputs are not the same (cakgon vs cakoh) and why it differs from what is expected. The problem probably resides in the part "//Deliver the crypted test".
I have spent a few hours trying to figure it out without success.
Thanks in advance for any help / tip / piece of advice.
Baptiste

I finally get it.
Parentheses were missing before one of the "%26".

Related

Why am I getting same characters with any key I type?

Why am I getting this return 4 repeated characters for Pset2 Substition CS50
Everything seems to work fine except for the checking for repeated characters in the command line argument. Rest of the code works fine when I remove this return for the checking repeated characters. Everything I type gives me this error
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
int main(int argc, string argv[])
{
if (argc == 2)
{
//When there are 26 characters in string
if (strlen(argv[1]) == 26)
{
string check = argv[1];
//Checking each characters in string(array) where [i] is the array number
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
//If the characters in the string is alphabet or not
if (!isalpha(argv[1][i]))
{
printf("Key must only contain Alphabetic Characters\n");
return 3;
}
//Check for repeated alphabet
for (int l = 0; l < n; l++)
{
if (argv[1][i] == check[l])
{
printf("Key must not contain repeated Characters\n");
return 4;
}
}
}
//Get Plaintext
string plaintext = get_string("Plaintext: ");
//Going through each characters in string
for (int j = 0, n = strlen(plaintext); j < n; j++)
{
//For LOWERCASE CHARACGERS
if (plaintext[j] >= 'a' && plaintext[j] <= 'z')
{
plaintext[j] = argv[1][plaintext[j] - 97];
plaintext[j] = tolower(plaintext[j]);
}
//For UPPERCASE CHARACTERS
else if (plaintext[j] >= 'A' && plaintext[j] <= 'Z')
{
plaintext[j] = argv[1][plaintext[j] - 65];
plaintext[j] = toupper(plaintext[j]);
}
}
printf("Ciphertext: %s\n",plaintext);
}
//If Characters are not 26 in string
else
{
printf("Key must contain 26 Characters\n");
return 2;
}
}
//When Location is other than argv[1]
else
{
printf("./substitution KEY\n");
return 1;
}
}
When i is 0 and l is 0 what is being compared here if (argv[1][i] == check[l])? Actually whenever i and l are equal it is comparing a character to itself. Program does not need to compare any characters it has already processed. The compare should start at the current char + 1.

Caesar problem code generating "error: implicitly declaring library function 'strlen' with type 'unsigned long (const char *)'

I am doing the CS50 course and am on week 2. One of the problems of week 2 is called "Caesar". Essentially you have to write code which cyphers text by shifting letters that use the users inputted preferred number. After running my code I keep getting this error
"error: implicitly declaring library function 'strlen' with
type 'unsigned long (const char *)'
[-Werror,-Wimplicit-function-declaration]
for(i = 0, l = strlen(text); i < n; i++)"
This is the code:
int main(int argc, string argv[])
{
string n = argv[1];
int y = argc;
int key = get_int("./caesar ");//getting the number from the user
int k = (key);//assigning key a variable name.
string text = get_string("plaintext: ");//letting the user input their text.
if (key < 1)//Trying to make limit for acceptable input.
{
printf("ERROR");
return 1;
}
int l;
int i;
//for loop containing the encipher process
for(i = 0, l = strlen(text); i < n; i++)
{
if(isalpha(i))
{
if (isupper[i])
{
printf("ciphertext: %c",(text[i] + k)%26 + 65);
}
else (islower[i])
{
printf("ciphertext: %c",(text[i] + k)%26 + 65);
}
}
}
printf("ciphertext: %c", d || c);
return;
int checking_key(int y,string n)
int num = argc;
string key = y;
int num_key = atoi(key);
if(argc != 2)
{
return 0;
}
else
{
if (num_key > 0)
{
return num_key;
}
else
{
return 0;
}
}
}
From man strlen:
Synopsis
#include <string.h>
size_t strlen(const char *s);
Just like one needs to "include" cs50.h to use any of the get_* functions, string.h must be "include"d to access its functions, eg strlen.
Additionally (per comments):
The "ordered comparison" in the compile error
ordered comparison between pointer and integer ('int' and 'string' (aka 'char *')) [-Werror] for(i = 0, l = strlen(text); i < n; i++)
is i < n. Error says one of them is an int and one of them is a string.
On closer inspection this program is a long way from a clean compile. Recommend you follow along with the spec and "approach this problem one step at a time"

How to use vector acsess element through function

This code is made for the multiplication of two arrays given by the user
typedef vector<vector<int> > arr ;
void multiply (arr &arr1 ,arr &arr2 )
{
arr res ;
unsigned new_row = arr1.size() ;
unsigned new_col = arr2.at(0).size();
for(int i = 0 ; i < new_row ; i++)
{
vector <int> vec ;
res.push_back(vec ) ;
for(int j = 0 ; j<new_col ;j++)
{
int x = 0 ;
res.at(i).push_back(x);
for(unsigned k =0 ; k <arr2.size();k++)
{
res.at(i).at(j) += arr1.at(i).at(k)*arr2.at(k).at(j);
}
cout<< res.at(i).at(j) ;
}
}
}
int main()
{
unsigned rows_number1 = 0 , columns_number1 = 0 ;
arr arr1 ;
cout<<"MATRIX A "<<endl<<endl ;
cout << "The Rows : " ;
cin >> rows_number1 ;
cout << "The Columns :" ;
cin>> columns_number1 ;
for(int i = 0 ; i<rows_number1;i++)
{
vector<int> newr ;
arr1.push_back(newr);
for(int j = 0; j<columns_number1 ;j++)
{
int x ;
cout<<"The Member ("<<i+1<<","<<j+1 <<") :" ;
cin>>x ;
arr1.at(i).push_back(x);
}
}
unsigned rows_number2 = 0 , columns_number2 = 0 ;
arr arr2 ;
cout<<"MATRIX B "<<endl<<endl ;
cout << "The Rows : " ;
cin >> rows_number2 ;
cout << "The Columns :" ;
cin>> columns_number2 ;
for(int i = 0 ; i<rows_number2;i++)
{
vector<int> newr ;
arr1.push_back(newr);
for(int j = 0; j<columns_number2 ;j++)
{
int x ;
cout<<"The Member ("<<i+1<<","<<j+1 <<") :" ;
cin>>x ;
arr1.at(i).push_back(x);
}
}
system("cls");
if(columns_number1!=rows_number2)
{
cout<<"Error Multiplication Dimensions" <<endl ;
}
else
{
cout << "A * B ="<<endl;
multiply(arr1,arr2);
}
}
why there is an error and what is the other way ??
how i can improve the code to multiplicate two arrays
Edited : i tried with two 2*2 arrays using console input and output and this is my full code
The problem is out_of_range exception but i don't know why
When you mulitply to matrices, there are strict constraints on the input.
The number of columns of the first matrix must be the same as the number of rows of the second matrix.
When your matrix is represented by a std::vector<std::vector<int>>, you'll have to make sure that ALL the nested std::vectors are of the same size.
Also, don't assume that arr2 is non-empty. When it is empty, arr2.at(0) will thrown an exception.
Here's a more robust version of your function.
void multiply (arr &arr1 ,arr &arr2 )
{
arr res;
unsigned num_rows1 = arr1.size();
if ( num_rows1 == 0 )
{
// Can't do much.
// Return.
return res;
}
unsigned num_cols1 = arr1[0].size();
if ( num_cols1 == 0 )
{
// Can't do much.
// Return.
return res;
}
// Inner vector size check of arr1.
for(unsigned int i = 1 ; i < num_rows1 ; i++)
{
if ( num_cols1 != arr1[i].size() )
{
throw std::runtime_error("Bad input");
}
}
// Make sure the number of columns in arr1 is the same as
// number of rows in arr2.
unsigned num_rows2 = arr2.size();
if ( num_cols1 != num_rows2 )
{
throw std::runtime_error("Bad input");
}
unsigned num_cols2 = arr2[0].size();
if ( num_cols2 == 0 )
{
// Can't do much.
// Return.
return res;
}
// Inner vector size check of arr2.
for(unsigned int i = 1 ; i < num_rows2 ; i++)
{
if ( num_cols2 != arr2[i].size() )
{
throw std::runtime_error("Bad input");
}
}
// All inputs appear to be valid.
// Now, do the multiplication.
unsigned new_row = num_rows1;
unsigned new_col = num_cols2;
res.resize(num_rows1);
for(unsigned i = 0 ; i < new_row ; i++)
{
for(unsigned j = 0 ; j<new_col ;j++)
{
int x = 0 ;
res.at(i).push_back(x);
for(unsigned k =0 ; k < num_cols1; k++)
{
res.at(i).at(j) += arr1.at(i).at(k)*arr2.at(k).at(j);
}
cout<< res.at(i).at(j) ;
}
}
}

Stack around the variable A (array) or n (size of the array) was corrupted

This program checks distinctness in an array. (no repeated values in an array I.e if 1 2 3 3 4 is an array it is not distinct). this code Won't compile although (I believe that) index of array did not go out of range in for loop.
theRun-Time Check Failure says stack around variable 'n' was corrupted when I enter n =12. BUT says stack around variable 'A' was corrupted when I enter n = 10. with exactly the same variables entered in the array in the second step. (the error shows up after entering the fourth integer)
#include <iostream>
using namespace std;
int main()
{
int n;
int A[] = {0};
int integer;
cout<<"Enter the size of the array\n";
cin>>n;
cout<<"enter "<<n<<" integers\n";
for (int i = 0 ; i < n ; i++)
{
cin>>A[i];
}
for (int i = 0 ; i < n ; i++)
{
for (int j = 0 ; j < n - i; j++)
{
if(A[j+1] > A[j])
{
int temp;
temp = A[j];
A[j+1] = A[j];
A[j+1] = temp;
}
}
}
for (int i = 0 ; i < n; i++)
{
if (A[i] - A[i+1] ==0 ){
cout<<"\nThe Array Is Not Distinct !\n";
break;
}
else
{
cout<<"\nThe Array Is Distinct !\n";
}
}
system("pause");
return 0;
}

Vigenere.c CS50 Floating Point Exception (Core Dumped)

I am working on the Vigenere exercise from Harvard's CS50 (in case you noticed I'm using string and not str).
My program gives me a Floating Point Exception error when I use "a" in the keyword.
It actually gives me that error
when I use "a" by itself, and
when I use "a" within a bigger word it just gives me wrong output.
For any other kind of keyword, the program works perfectly fine.
I've run a million tests. Why is it doing this? I can't see where I'm dividing or % by 0. The length of the keyword is always at least 1. It is probably going to be some super simple mistake, but I've been at this for about 10 hours and I can barely remember my name.
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main (int argc, string argv[])
{
//Error message if argc is not 2 and argv[1] is not alphabetical
if (argc != 2)
{
printf("Insert './vigenere' followed by an all alphabetical key\n");
return 1;
}
else if (argv[1])
{
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if (isalpha((argv[1])[i]) == false)
{
printf("Insert './vigenere' followed by an all alphabetical key\n");
return 1;
}
}
//Store keyword in variable
string keyword = argv[1];
//Convert all capital chars in keyword to lowercase values, then converts them to alphabetical corresponding number
for (int i = 0, n = strlen(keyword); i < n; i++)
{
if (isupper(keyword[i])) {
keyword[i] += 32;
}
keyword[i] -= 97;
}
//Ask for users message
string message = GetString();
int counter = 0;
int keywordLength = strlen(keyword);
//Iterate through each of the message's chars
for (int i = 0, n = strlen(message); i < n; i++)
{
//Check if ith char is a letter
if (isalpha(message[i])) {
int index = counter % keywordLength;
if (isupper(message[i])) {
char letter = (((message[i] - 65) + (keyword[index])) % 26) + 65;
printf("%c", letter);
counter++;
} else if (islower(message[i])) {
char letter = (((message[i] - 97) + (keyword[index])) % 26) + 97;
printf("%c", letter);
counter++;
}
} else {
//Prints non alphabetic characters
printf("%c", message[i]);
}
}
printf("\n");
return 0;
}
}
This behavior is caused by the line keyword[i] -= 97;, there you make every 'a' in the key stream a zero. Later you use strlen() on the transformed key. So when the key starts with an 'a', keywordLength therefor is set to zero, and the modulo keywordLength operation get into a division by zero. You can fix this by calculating the keyword length before the key transformation.

Resources