Passing argument from main to function in C - c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Compile this program with:
// cc -std=c99 -Wall -Werror -pedantic -o rot rot.c
#define ROT 3
// The rotate function returns the character ROT positions further along the
// alphabetic character sequence from c, or c if c is not lower-case
char rotate(char c)
{
// Check if c is lower-case or not
if (islower(c))
{
// The ciphered character is ROT positions beyond c,
// allowing for wrap-around
return ('a' + (c - 'a' + ROT) % 26);
}
else
{
return ('A' + (c - 'A' + ROT) % 26);;
}
}
// Execution of the whole program begins at the main function
int main(int argc, char *argv[])
{
for (int j = 2; j < argc; j++){
// Calculate the length of the second argument
int length = strlen(argv[j]);
// Loop for every character in the text
for (int i = 0; i< length; i++)
{
// Determine and print the ciphered character
printf("%c" ,rotate(argv[j][i]));
printf("%c" ,rotate(argv[j][i])-ROT);
printf("%d",i+1);
printf("\n");
}
// Print one final new-line character
printf("\n");
}
// Exit indicating success
exit(EXIT_SUCCESS);
return 0;
}
I am struggling with a program that rotates the given characters by the amount user type in as the first argument of argv.
Now I need to modify the program to achieve this. The question says I can use àtoi` function to do that.
My confusion is that How can my argv[1] value in Main be passed into function rotate (Variable ROT)?
The ideal output would be (using terminal in MAC)
./rot 1 ABC
AB1
BC2
CD3

ROT is a macro. You can't change it at runtime. Use a variable instead.
(You need to error check strtol() and ensure there are as many argv[] passed before using them -- strtol() is better than atoi as helps detect errors).
int rot = (int)strtol(argv[1], 0, 0);
printf("%c" ,rotate(rot, argv[j][i]));
printf("%c" ,rotate(rot, argv[j][i])-ROT);
and change it to:
char rotate(int rot, char c) {
...
}
and use rot instead of ROT.

Related

Null pointer passed as argument 1

In line int d = atoi(argv[2]); there seems to be something wrong. "null pointer passed as argument 1..."
What can I do?
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, string argv[])
{
int num;
int i = 1;
int j = 1;
int board [i][j];
// 2nd CL argument is size of grid.
if (argc != 2)
{
return false;
}
int d = atoi(argv[2]);
if (d <= 0)
{
return false;
}
// setting up board.
// number of tiles needed.
num = d * d - 1;
// iterating over columns and rows
for (i = 0; i <= d; i++)
{
for (j = 0; j <= d; j++)
{
// set values.
board[i][j] = num;
num --;
}
printf ("%d", board[i][j]); // TESTING.
printf ("\n");
}
// if even swap 1 & 2. Don't display 1.
}
argv[0] holds the name of the command used to start your program. If you expect two command line arguments, check argc == 3 and read the command line arguments from argv[1] and argv[2].
You have a multiple issues with your program
1) string is not a standard type in C.
2) false is not a standard constant in C98.
Standard C (since C99) provides a boolean type, called _Bool. By including the header stdbool.h one can use the more intuitive name bool and the constants true and false.
3) Your board has a fixed size 1x1 board[1][1]:
int i = 1;
int j = 1;
int board [i][j];
Fix this otherwise your program will smash memory.
4) You need 2 arguments for your board. Arguments start on position argv[1] and argv[2] in argv[] Since first argv[0] is name of the program you need argc = 3.

segmentation fault in c while coding Vigenère’s cipher

I am really new to coding and I have been teaching myself how to code by using EDX.org. This week I have been studying about Cryptography and I have to create a Vigenère’s cipher. I wrote the code and for the most part, it's correct. However when I compiled the program, it's showing a segmentation error. I have been trying to figure our why this is happening and I am totally stuck. Could you take a look at my code and tell me whats wrong?
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int index(int k, int c);
int main (int argc, string argv[1])
{
//check for correct criteria
if (argc = 2, isalpha(argv[1]))
{
string text = GetString();
string key = argv[1]; //store key word
int Totalshift = strlen(key); //number of shift for keyword
int shift = 0;
//loops over the whole text
for (int i = 0, n = strlen(text); i <n; i++ )
{
char p= text[i];
char k = toupper(key[shift]); //Upper case for each character
if (isupper(p))
{
//convert to 0 index
p = p - 65;
k = k - 65;
int crypt= index (k , p);
printf("%c", crypt+65);
shift= (shift+1) %Totalshift;
}
else if (islower(p))
{
p = p - 97;
k = k - 65;
int crypt= index (k , p);
printf("%c", crypt+97);
shift= (shift+1) %Totalshift;
}
else
{
printf("%c", p);
}
}
printf("\n");
}
//error message
else
{
printf("ERROR!\n");
return 1;
}
}
//index function
int index(int k, int p)
{
return (k+p)% 26;
}
string
No. Never, ever hide pointers.
int main(int argc, char ** argv)
Then:
//check for correct criteria
if (argc = 2, isalpha(argv[1]))
Here, you assign to the variable (parameters behave like local variables in that respect) the value 2, thus destroying the previous value (which holds the number of arguments given to the program). The result is the value which was assigned, thus 2. Then, there's the comma operator: You discard that 2, and then call isalpha(argv[1]), which clearly shows why you should always turn on warnings and never, ever hide pointers:
argv[1] is of type char *, thus a pointer to a character array (or, as we know in this case, a character array terminated with '\0', which is called a C string). Since isalpha takes an int as parameter the value of the pointer ("the memory address") is implicitly converted to (a probably very large) int value. Quoting from above link, emphasis mine:
The c argument is an int, the value of which the application shall ensure is representable as an unsigned char or equal to the value of the macro EOF. If the argument has any other value, the behavior is undefined.
Which is possibly the source of the segmentation fault.
Finally, that GetString really looks fishy to me. Assuming that it allocates some memory (for the string that it presumably reads from the user) ... where do you free that memory? Is it really allocating memory, or possibly returning a pointer to an array with automatic storage duration (a local variable, so to say)?

Function to encrypt a string using pointers

I need to write a function that gets a string and a number N, the function will return in the same pointer the encrypted string. The function will encrypt a string by the following rules:
Reverse the string, e.g: if the string is "Amnon" the result would be "nonmA".
After the reverse, each letter needs to be replaced by the value of N, e.g: if N=3 then instead of "nonmA" the result would be "qrqpD".
I had no problem doing the reverse part but I'm struggling with switching each letter. Here is the code I wrote so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void StRreverse(char* mystr, int N);
void StRreverse(char* mystr, int N)
{
int c, length, n;
char *begin, *end, temp;
length = strlen(mystr);
begin = mystr;
end = mystr;
for (c = 0; c < length - 1; c++)
{
end++;
}
for (c = 0; c < length / 2; c++)
{
temp = *end;
*end = *begin;
*begin = temp;
begin++;
end--;
}
}
void main()
{
char string[100];
printf("Enter some text\n");
gets(string);
StRreverse(string);
printf("Reverse of entered string is \"%s\".\n", string);
system("pause");
}
First, identify 'letters' in a portable way:
#include <ctype.h>
Then you can use isalpha(mystr[c]) to generally identify letters, and specifically islower and isupper. Then, on each letter, add your constant modulo 26. That is, if a becomes b, then y becomes z and z would be a again.
This operation is encoding-dependent as not all encodings have "a" to "z" and "A" to "Z" defined consecutively. Fortunately, it's unlikely you have such a system :) (although it is an interesting exercise to work out a way where this would not be an issue!).
The trick is to 'wrap around' with an offset of either A or a, so capitals and lowercase need a separate line of code:
if (isupper(mystr[c]))
mystr[c] = 'A' + ((mystr[c]-'A' + N + 26) % 26);
if (islower(mystr[c]))
mystr[c] = 'a' + ((mystr[c]-'a' + N + 26) % 26);
where N can be as low as -25, or as high as you want. That lower limit (and the addition of 26 in the statements) is because in some implementations of C, taking the modulus of a negative number returns a negative number as well.
To decode this text -- properly called the Caesar Cypher --, you can apply the same formula with -N.
The most simple way to do switching is by adding the number to that character. For example
`char str[n] = {'a','b','c','d'};
for(int i=0; i less than n; i++)
str[i] = str[i] +3; // we are adding 3 to switch
`
I dont remeber the ascii number for small 'a'. But if its 36 the above code will make it 39 which will be 'd'. Hope it works for u

Counting substrings in a string

I have the task to make a little program with pointers and I am facing a problem with const char*s. The program is meant to count the number of times that a sub-string appears in a main-string. Also, the different positions, where the sub-strings start, should be saved in a char** ptr. This is my little testing code:
#include <stdio.h>
#include <string.h>
main()
{
int i=-1;
int k=0;
char** ptr;
char* str="cucumber";
char* substr="cu";
while(strstr(str, substr)!=NULL)
{
i++;
ptr[i]=strstr(str, substr);
str = strpbrk(str, substr)+1;
k++;
}
printf("%i",k);
}
It should print 2, since the sub-string 'cu' appears 2 times in 'cucumber' - yet, my compiler tells me that I am using chars, when I should use constant ones. Except, I don't know how to do that.
The strstr() function requires them. What should I change?
// note:
// 1) correction to declaration of main()
// 2) addition of return statement
// 3) 'substr' is a poor name choice for a variable, as
// a) it looks like a C lib function (it is a ACL library function)
// b) it does not clearly convey what the variable contains
// 4) clutter in the 'while' loop removed
// 5) 'while' loop is replaced by a 'for' loop so more can be accomplished with less code
// 6) unneeded variables are eliminated
// 7) the 'for' loop stops when there is no possibility of further testStr occurrences
// 8) the printf() clearly indicates what is being printed
#include <stdio.h>
#include <string.h>
int main()
{
char* testStr="cucumber";
char* findStr="cu";
int k = 0;
for( int i=0; strlen(&testStr[i]) >= strlen(findStr); i++)
{
if( strstr(&testStr[i], findStr) != NULL)
{
k++;
}
}
printf("\nnumber of occurrences of %s in %s is %d\n", findStr, testStr, k);
return(0);
}
Allocate memory for storing the pointer values
#include <stdio.h>
#include <string.h>
#define MAX_SUB_STR 10
int main()
{
int i;
int k;
char* ptr[MAX_SUB_STR];
char* str="cucumber";
char* temp;
char* substr="cu";
i = 0;
k = 0;
temp = str;
while(strstr(temp, substr)!=NULL && k < MAX_SUB_STR)
{
ptr[k]=strstr(temp, substr);
temp = ptr[k] + strlen(substr);
k++;
}
printf("%i\n",k);
for (i = 0; i < k; i++)
printf("%p\n",ptr[i]);
return 0;
}

Get C XOR return value

In the for loop, it prints the correct value 11100001 in each loop, but the main call print char_str is blank.
I hope it can return 11100001 as char.
//xor
char * xorencrypt(char * a, char * b) {
size_t alen = strlen(a);
size_t blen = strlen(b);
char * encrypted = malloc(alen + 1);
int i;
for (i = 0; i < 8; i++) {
encrypted[i] = a[i] ^ b[i];
printf("%s\n", encrypted[i]);
}
encrypted[alen] = '\0';
return encrypted;
}
main {
char * char_str = xorencrypt("11011000", "00111001");
printf("%s\n", char_str);
}
Your code needs a bit of refactoring.
1) You need to include some headers
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2) the 'main' function should return an int
int main() {
/* code here */
return 0;
}
3) You should make sure the call to malloc succeeds
char * encrypted = malloc(alen + 1);
assert(encrypted != (char*)0); /* requires #include <assert.h>
4) You should be careful when xor'ing ones and zeros. You are handling chars like integers
you are xoring zeros (value 48 in ascii) with ones (value 49 in ascii)
encrypted[i] = a[i] ^ b[i];
you want something like this instead
int a_i = a[i] - '0';
int b_i = b[i] - '0';
encrypted[i] = (a_i ^ b_i) + '0';
A reworked version of the code that assumes you are dealing exclusively with strings of the binary digits '0' and '1'. If you are dealing with more general strings, you will need a different solution.
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static
char *xorencrypt(char *a, char *b)
{
size_t alen = strlen(a);
char *encrypted = malloc(alen + 1);
assert(alen == strlen(b));
assert(encrypted != NULL);
for (size_t i = 0; i < alen; i++)
{
assert(a[i] == '0' || a[i] == '1');
assert(b[i] == '0' || b[i] == '1');
encrypted[i] = (a[i] ^ b[i]) + '0';
putchar(encrypted[i]);
}
encrypted[alen] = '\0';
putchar('\n');
return encrypted;
}
int main(void)
{
char *char_str = xorencrypt("11011000", "00111001");
printf("%s\n", char_str);
free(char_str);
return 0;
}
Amongst the changes:
Error check the memory assignment. Using assert() is a bad way to do it in production code, but it does ensure that you check that the memory is allocated.
Check that the strings are the same length.
Remove unused variable blen.
The static is optional; it means the code compiles cleanly under the stringent options I use (which require a prototype declaration of every non-static function before it is defined or used).
The loop index i is of the same type size_t as alen to avoid warnings about comparing signed and unsigned values. I'm using the C99 style 'declare a variable in a for loop' notation.
The upper bound of the loop is based on the measured length of the strings, not a fixed constant.
The original version of the XOR operation either generated a null '\0' or a control-A '\1' for each character.
The revised version of the crucial XOR operation ensures that the result is a printable digit.
The printf("%s\n", encrypted[i]); in the original passed a character to be printed as a string. If your compiler wasn't warning you, turn on the warning options or get a better compiler.
If you'd written printf("%s\n", &encrypted[i]); you would have had problems, potentially, with a string that is not guaranteed to be null terminated inside the loop (though you did null terminate the string after the loop, which was good).
The code in main() frees the allocated memory. It is good practice to ensure there is a free() for every malloc().
I prefer to explicitly return 0 from main(), even though C99 says you don't have to.
This answer was started while the question was active. Then life got in the way.

Resources