I have an array of 1's and 0's which is compressed in such a way that when the number of 1's is greater than 10 it writes +n+ when n in the number of 1's and when the number of 0's is greater than 10 it writes -n- when n in the number of 0's otherwise it writes them as it is.
Now the issue is, I need to decompress the array to write it back to the file. But I can't find a way to convert the number of zeros or ones to integer. It keeps giving me an error which says initializing argument 1 of ‘int atoi(const char*) and another one on the same line which says invalid conversion from ‘char’ to ‘const char*’
I'm working in Linux.
Here's a peice of my code
else if(str[i]=='+')
{
n=atoi(str[i+1]);
for(int j=0;j<n;j++)
{
strcat(temp,"1");
i=i+n-1;
}
}
This is an algorithm do "expansion" - don't ever use it in production - for example, there is no error checking, so it is not safe. It is a quick example.
char *decode(char *q)
{
char *all=NULL;
long i=0;
int n='0';
char *p;
if(*q== '+')
n='1';
++q;
i=strtol(q, NULL, 10);
all=calloc( i + 1, 1);
for(p=all; i; i--)
*p++=n;
return all;
}
char *decompress(char *dest, char *str)
{
char *p=str;
char *q=dest;
for(; *p; p++)
{
if( isdigit((int)*p) )
{
*q++=*p;
*q=0x0;
}
else // - or +
{
char *tmp=decode(p);
strcpy(q, tmp);
q=strchr(q, '\0');
free(tmp);
p=strchr(p+1, *p); // next
}
}
return dest;
}
Related
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"
The program was throwing error.I figured out that while loop was not terminating because A.size()-1 resulted in some large no even when A.size()
has become 0.
I instead used a variable n to store A.size() and used it in while loop
it worked.But I want to know why A.size()-1 prints such large no.
//Input: A:"nnnn"
int i=0;
while(i<A.size()-1){
if(A[i]==A[i+1]){
A.erase(A.begin()+i);
A.erase(A.begin()+i);
if(i!=0)i--;
}
else i++;
cout<<i<<" "<<A.size()-1<<endl;
}
if(A=="")return "empty";
return A;
}
/* //below code works fine
int i=0;
int n=A.size();
while(i<n-1){
if(A[i]==A[i+1]){
A.erase(A.begin()+i);
A.erase(A.begin()+i);
if(i!=0)i--;
}
else i++;
n=A.size();
}
if(A=="")return "empty";
return A;
*/
//output
0 1
0 18446744073709551615
Since std::string.length returns a size_t which is an unsigned integer you get unsigned underflow for the empty string (which has the length of 0).
One solution is to change the condition in your while to:
while(A.size() && i<A.size()-1)
My doubts are as follows :
1 : how to send 'str' from function 'fun' , So that i can display it in main function.
2 : And is the return type correct in the code ?
2 : the current code is displaying some different output.
char * fun(int *arr)
{
char *str[5];
int i;
for(i=0;i<5;i++)
{
char c[sizeof(int)] ;
sprintf(c,"%d",arr[i]);
str[i] = malloc(sizeof(c));
strcpy(str[i],c);
}
return str;
}
int main()
{
int arr[] = {2,1,3,4,5},i;
char *str = fun(arr);
for(i=0;i<5;i++)
{
printf("%c",str[i]);
}
return 0;
}
how to send 'str' from function 'fun' , So that i can display it in main function.
This is the way:
char* str = malloc( size );
if( str == NULL ) {
fprintf( stderr,"Failed to malloc\n");
}
/* Do stuff with str, use str[index],
* remember to free it in main*/
free(str);
And is the return type correct in the code ?
No, Probably char** is the one you need to return.
the current code is displaying some different output.
Consider explaining what/why do you want to do ? The way you have written, seems completely messed up way to me. You're passing array of integer but not its length. How is the fun() supposed to know length of array? Another problem is array of pointers in fun().
You can't write a int to a char (See the both size). So I used char array instead.
However, I'm not sure if this is what you want to do (might be a quick and dirty way of doing it):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char**
fun(int *arr, int size)
{
char **str = malloc( sizeof(char*)*size );
if( str == NULL ) {
fprintf( stderr, "Failed malloc\n");
}
int i;
for(i=0;i<5;i++) {
str[i] = malloc(sizeof(int));
if( str == NULL ) {
fprintf( stderr, "Failed malloc\n");
}
sprintf(str[i],"%d",arr[i]);
}
return str;
}
int
main()
{
int arr[] = {2,1,3,4,5},i;
char **str = fun(arr, 5);
for(i=0;i<5;i++) {
printf("%s\n",str[i]);
free(str[i]);
}
free(str);
return 0;
}
I made these changes to your code to get it working:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **fun(int *arr)
{
char **str = malloc(sizeof(char *) * 5);
int i;
for(i = 0; i < 5; i++) {
if ((arr[i] >= 0) && (arr[i] <= 9)) {
char c[2] ;
sprintf(c, "%d", arr[i]);
str[i] = (char *) malloc(strlen(c) + 1);
strcpy(str[i],c);
}
}
return str;
}
int main()
{
int arr[] = {2, 1, 3, 4, 5}, i;
char **str = fun(arr);
for(i = 0; i < 5; i++) {
printf("%s", str[i]);
free(str[i]);
}
printf("\n");
free(str);
return 0;
}
Output
21345
I added a check to make sure that arr[i] is a single digit number. Also, returning a pointer to a stack variable will result in undefined behavior, so I changed the code to allocate an array of strings. I don't check the return value of the malloc calls, which means this program could crash due to a NULL pointer reference.
This solution differs from the others in that it attempts to answer your question based on the intended use.
how to send 'str' from function 'fun' , So that i can display it in main function.
First, you need to define a function that returns a pointer to array.
char (*fun(int arr[]))[]
Allocating variable length strings doesn't buy you anything. The longest string you'll need for 64bit unsigned int is 20 digits. All you need is to allocate an array of 5 elements of 2 characters long each. You may adjust the length to suit your need. This sample assumes 1 digit and 1 null character. Note the allocation is done only once. You may choose to use the length of 21 (20 digits and 1 null).
For readability on which values here are related to the number of digits including the terminator, I'll define a macro that you can modify to suit your needs.
#define NUM_OF_DIGITS 3
You can then use this macro in the whole code.
char (*str)[NUM_OF_DIGITS] = malloc(5 * NUM_OF_DIGITS);
Finally the receiving variable in main() can be declared and assigned the returned array.
char (*str)[NUM_OF_DIGITS] = fun(arr);
Your complete code should look like this:
Code
char (*fun(int arr[]))[]
{
char (*str)[NUM_OF_DIGITS] = malloc(5 * NUM_OF_DIGITS);
int i;
for(i=0;i<5;i++)
{
snprintf(str[i],NUM_OF_DIGITS,"%d",arr[i]); //control and limit to single digit + null
}
return str;
}
int main()
{
int arr[] = {24,1,33,4,5},i;
char (*str)[NUM_OF_DIGITS] = fun(arr);
for(i=0;i<5;i++)
{
printf("%s",str[i]);
}
free(str);
return 0;
}
Output
2413345
With this method you only need to free the allocated memory once.
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.
i would like to know how can i use a set of numbers as a KEY for the rc4 encryption.
According to the internet and wiki the KEY is actually a string of letters but the bytes are used . But in my program i need to use a 6 digit number as a KEY. Should i covert it to a string or how.
Key Sheudling Algorithm is indicated below.
void ksa(u_char *State, u_char *key) {
int byte, i, keylen, j=0;
keylen = (int) strlen((char *) key);
for(i=0; i<256; i++) {
j = (j + State[i] + key[i%keylen]) % 256;
swap(&State[i], &State[j]);
}
How can i modify the code or should i just convert the numbers to string.
Strings and numbers are both bytes. Here is a working RC4 code that accepts a key of unsigned chars:
#include<stdio.h>
#include<string.h>
#define SIZE 256
unsigned char SBox[SIZE];
int i;
int j;
void initRC4(unsigned char Key[]);
unsigned char getByte(void);
void initRC4(unsigned char Key[])
{
unsigned char tmp;
unsigned char KBox[SIZE];
for(i=0;i<SIZE;i++)
SBox[i]=i;
for(i=0;i<SIZE;i++)
KBox[i]=Key[i % strnlen(Key,SIZE)];
for(j=0,i=0;i<SIZE;i++)
{
j=(j+SBox[i]+KBox[i]) % SIZE;
tmp=SBox[i];
SBox[i]=SBox[j];
SBox[j]=tmp;
}
}
unsigned char getByte(void)
{
unsigned char tmp;
i=(i+1)%SIZE;
j=(j+SBox[i])%SIZE;
tmp=SBox[i];
SBox[i]=SBox[j];
SBox[j]=tmp;
return SBox[(SBox[i]+SBox[j])%SIZE];
}
First, you initialize the RC4 stream:
initRC4(key);
Then you do:
getByte()
...which always returns 1 byte from the RC4 stream you've set up.
One thing to remember though - a letter in string is not always equal to 1 byte. Same goes for the integers and number symbols in strings. Really, you must read an introduction to computer programming before you mess with ciphers.
Here is a demonstration of how bytes differ in strings in integers:
#include <string>
int main(int argc, char **argv) {
const int n=67898;
const std::string str = "67898";
const int arrayLength = sizeof(int);
const int stringArrayLength = str.size();
unsigned char *bytePtr=(unsigned char*)&n;
printf("Bytes for integer: ");
for(int i=0;i<arrayLength;i++)
{
printf("%X ", bytePtr[i]);
}
printf("\n");
printf("Bytes for string: ");
for(int i=0;i<stringArrayLength;i++)
{
printf("%X ", str.at(i));
}
printf("\n");
return 0;
}
Output:
Bytes for integer: 3A 9 1 0
Bytes for string: 36 37 38 39 38
There will usually be a terminating byte at the end of a string, so you could add +1 byte to string size.