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)?
Related
int count(char letter, int* array, int number)
{
int sum= 0;
int i;
for(i = 0; i < number; ++i)
{
if(array[i] == letter)
++sum;
}
return sum;
}
int main(){
char array[] = { 'A','B','B','C'};
int number= sizeof(array) / sizeof(char);
count("A", array, number);
return 0;
}
I am attempting to count an occurrence of a particular character in an array and get nothing. The problem is certainly in the way I pass the character argument, but I struggle to find a similar example online.
I did a bit of tweaking of your code so that the parameters in your function align with the parameters passed when your function is called. Following is an example of what your code might look like in order to count characters.
#include <stdio.h>
#include <stdlib.h>
int count(char letter, char* array, int number) /* Made second parameter a character array in lieu of an integer array */
{
int sum= 0;
int i;
for(i = 0; i < number; ++i)
{
if(array[i] == letter)
++sum;
}
return sum;
}
int main()
{
char array[] = { 'A','B','B','C'};
int number= sizeof(array) / sizeof(char) ;
printf("Count: %d\n",count('A', array, number)); /* Changed from string constant "A" to character 'A' */
return 0;
}
First off, you appear to want to send a character as your first parameter to your function. In your original code you were actually sending a string constant as "A" was enclosed in double quotes and not single quotes. The second parameter is a character array (aka, a string). Therefore, in your function definition the second parameter there needs to be a character array and not an integer array. Characters take up one or two bytes of memory depending upon the system, and integers "usually" take up four bytes of memory. So there would be a mismatch in attempting to check out array values.
Using your revised function to produce output for a "printf" call, I received the following output on my terminal.
Count: 1
So probably the biggest takeaway from this is that characters (e.g. 'A') are different from string constants (e.g. "A"), and characters, even though they equate to an integer value, utilize a smaller chunk of memory than do integers.
Hope that helps.
Regards.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 3 years ago.
I initially wrote a perfectly working C code for converting a positive integer (say 12345) to a string (i.e. "12345") and print it. The logic is simple: extracting the digits of the integer one-by-one by taking modulo 10 and reducing the integer by a factor of 10 each time (this occurs in the itos() function). The final string needs to hold the extracted digits in reverse order so as to match the original integer (cf. reverse() function).
#include <stdio.h>
#include <string.h>
char *reverse (char *s);
char *itos (int n);
int
main ()
{
int n = 12345;
char *s = itos (n);
printf ("%s", s);
return 1;
}
char *
itos (int n)
{
int d = 0;
char s[100];
int i = 0;
do
{
d = n % 10;
s[i] = (d + '0');
n = n / 10;
i++;
} while (n != 0);
s[i] = '\0';
return reverse(s);
}
char *
reverse (char *s)
{
int i = 0;
int j = strlen (s) - 1;
char temp;
while (i < j)
{
temp = s[i];
s[i] = s[j];
s[j] = temp;
i++;
j--;
}
return s;
}
You may compile it here. This works perfectly fine, but something strange happens if I return s instead of reverse(s) from the char* itos() function. That is:
#include <stdio.h>
#include <string.h>
char *itos (int n);
int
main ()
{
int n = 12345;
char *s = itos (n);
printf ("%s", s);
return 1;
}
char *
itos (int n)
{
int d = 0;
char s[100];
int i = 0;
do
{
d = n % 10;
s[i] = (d + '0');
n = n / 10;
i++;
} while (n != 0);
s[i] = '\0';
return s;
}
I'd have expected it to simply print the string "54321" instead of "12345". However, in the output screen, I simply get a (null). There might be a logical error in the char* itos() function, as in I might have done some illegal pointer operation, but I can't really locate the source of error.
I did try debugging by inserting print statements in several parts of the code. What I noticed is if I print the string s within the itos() function just before the return statement then it works fine and prints the string "54321". However, the print statement in the main() function still outputs a (null), which probably implies that there is some mismanagement of memory when the itos() function returns a character pointer to the main() function. Could someone please clarify?
Inside function itos you declared the variable s which is an array of 100 chars. This array is allocated somewhere after the start of the function and deallocated just before the function returns to its caller.
So when you put a printf inside itos, the variable s will still be a valid storage and this is why it worked as you intended. However as soon as itos returns, the memory reserved to the variable s should be considered deallocated thus can not be expected to still contain the data it had when itos was executing, creating undefined behavior if you rely on that.
Probably once deallocated, the memory pointed by s had its values modified, causing your function to not being able to proper convert the string back to a number.
char s[100] is only valid within itos. When the function returns, the memory becomes invalid, and accessing it through the pointer you returned is undefined behavior. You could instead allocate the memory dynamically, like this:
char* s = malloc(100);
When you do it this way, you need to free it when you're done with it (such as after the printf in main), like this:
free(s);
So, would defining a global character array be the way to go?
This would also work. Generally, it has its advantages and disadvantages over dynamically allocating the memory. For instance, it would occupy the memory at all times even if your function isn't using it. But to make up for it, the function runs faster because it doesn't have to dynamically allocate/delete the memory every time the function runs. But on the other hand it increases the startup time because it will zero-initialize the array. And of course you couldn't run it multiple times in parallel with one global array. But for this small program, none of those matter much.
I am trying to print every fourth character of a string using pointers.
I was able to achieve it using the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[]){
char* string = "WhatTheeHell";
char* p = string;
while(*p != '\0'){
printf("%c\n", *p);
p += 4;
}
return 0;
}
This correctly gives the output to me as:
W
T
H
Now, I tried another way to do it, which according to my knowledge of pointer arithmetic, should have worked, since the size of int on my machine is 4 bytes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[]){
char* string = "WhatTheeHell";
int* p = (int*)string;
while(*p != '\0'){
printf("%c\n", *p);
p += 1;
}
return 0;
}
When I print the output for this, it gives me WTH followed by four newlines.
My question, why are the four newlines being printed? Shouldn't it be that after the H is printed, the *p gives a NULL character present at the end of the string literal and the loop gets terminated?
For starters the first program is invalid. If a string has the number of characters that is not divisible by 4 you will have undefined behavior because the pointer can point to beyond the string using the pointer arithmetic
p += 4;
A valid approach can look the following way as it is shown in the demonstrative program
#include <stdio.h>
int main( void )
{
const char *s = "WhatTheeHell";
const size_t STEP = 4;
if ( *s )
{
const char *p = s;
do
{
printf( "%c\n", *p );
for ( size_t i = 0; i < STEP && *p; ++i, ++p );
} while ( *p );
}
}
Its output is
W
T
H
The second your program is also invalid. For starters it is not necessary thet a string literal is aligned by sizeof( int ) (moreover in general the sizeof( int ) can be greater or less than 4). So the program already has undefined behavior.
In this condition
*p != '\0'
there are compared sizeof( int ) bytes (not a single byte ) with the integer constant '\0'. So the comparison will be always true when the pointer points inside the string (and even beyond the string if there are no zero bytes).
By the way also pay attention to that in C sizeof( '\0' ) is equal to sizeof( int ).
When you compare *p to \0, *p is not a single char but a (presumably) four-byte value (the char is promoted to integer before comparison).
Nothing guaranties that after the \0 of your string there are other zero bytes: this is undefined behaviour.
Thus your loop continues until it reaches by chance a zero integer.
When printing with "%c\n", only the lower byte of the integer is considered; if its value is zero (nothing is guaranteed) it does not print anything visible, just the following \n
I got a homework question. I'm so close to complete program. I'm having trouble about one thing. This is the question:
Write a C program that generates and displays a character array of size 10 consisting of
random English lower-case letters. The program then asks the user how many times the array
will be right-shifted and displays the right shifted array at each right-shifting step. A sample
program execution output is given below. ( Hint: Use the ASCII codes of the English lower-case
letters which are 97, 98, ... 122 for a, b, ..., z, respectively, to generate the character array).
This is my code:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
void print_string (char *string){
int i;
for (i=0 ; i < 10 ; i ++){
printf("%c ", string[i]);
if (i == 9)
printf("\n");
}
}
void random_string(char *string, unsigned length)
{
/* Seed number for rand() */
srand((unsigned int) time(0) + getpid());
/* ASCII characters 97 to 122 */
int i;
for (i = 0; i < length; ++i)
{
string[i] = (rand() % 26)+ 97;
}
string[i] = '\0';
}
void reverse_string(char* str, int left, int right) {
char* p1 = str + left;
char* p2 = str + right;
while (p1 < p2) {
char temp = *p1;
*p1 = *p2;
*p2 = temp;
p1++;
p2--;
}
}
void rotate(char* str, int k, int n) {
reverse_string(str, 0, n-1);
reverse_string(str, 0, k-1);
reverse_string(str, k, n-1);
}
int main(void)
{
char s[11];
int i,shiftNum;
random_string(s, 11);
printf("Randomly constructed array is :\n");
print_string(s);
printf("Enter how many times array will be shifted: ");
scanf("%d",&shiftNum);
rotate(s,shiftNum,11);
print_string(s);
}
What's wrong with this code? When I execute it with 1, I couldn't get the first reverse correctly and I want to display all shifting steps.
For a start, it is atrocious that your lecturer/professor is telling you to use 97..122. C does not require that ASCII be the character set on every system, so this code is entirely non-portable, yet if you look at the history as far as Unix is concerned C is supposed to be a portable programming language. If you want to write this in a portable way, you need to store the characters in an array and select from that array:
char lowercase[] = "abcdefghijklmnopqrstuvwxyz";
string[i] = lowercase[rand() % (sizeof lowercase - 1)];
Now that we've covered that pedantic detail, Cool Guy indicated in a comment that this line of code is erroneous: string[i] = '\0';. He's correct about that.
This should also performed within main, not within random_string: srand((unsigned int) time(0) + getpid());. The reason is that calling random_string multiple times in the same second would result in the same "random string", which is very uncool.
scanf("%d",&shiftNum); can't guarantee success (that the user will input numeric data), and so can't guarantee that shiftNum will contain a sane value. You need to check the return value. For example:
if (scanf("%d", &shiftNum) != 1) {
puts("Invalid shift count!\n");
exit(0);
}
You should probably also consider using an unsigned type for shiftNum (and this will cause the corresponding format spec %d to change to something else, such as %u for unsigned int).
One more important task before I finish this task: You need to modify rotate to handle an input of 0 correctly, since some users might want to rotate/shift 0 times (as an alternative to not rotating/shifting at all). I'm confident that this should be an easy task for you.
int main()
{
unsigned char a[3];
unsigned char (*p)[3]=NULL;
unsigned char *q=NULL;
int i = 0;
a[0]=0;
a[1]=1;
a[2]=2;
p=&a;
for(i=0;i<3;i++){
if((*p)[3] == a[3]){
printf("*p[%d]:%d a[%d]:%d",i,(*p)[3],i,a[3]);
}
}
}
o/p:
*p[0]:0 a[0]:0*p[1]:0 a[1]:0*p[2]:0 a[2]:0
Exited: ExitFailure 14
I want to copy an array of size 3 to a pointer and to do a comparision. I have written a sample program. But i'm getting an error value.
I ran this using an online c compiler . (codepad.org)
Please help me in identifying my mistakes.
Your variable p is an array, not a pointer. You can't re-assign an array to point somewhere else, so the line
p = &a;
is not valid.
Also, C indexes from 0 as you seem to know, so comparisons using index [3] for arrays of size 3 are not valid.
Further, in your comparison loop you're not actually using i to index, but instead always comparing using the invalid constant index [3].
It's not very clear from your code (q is not used, for instance), but it sounds as if you want to do something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned char a[3];
unsigned char *p;
p = malloc(sizeof a);
if(p != NULL) /* If allocation succeeded, p is valid. */
{
int i;
memcpy(p, a, sizeof a);
for(i = 0; i < sizeof a; ++i)
{
if(p[i] == a[i])
printf("p[%d]:%d a[%d]:%d\n", i, p[i], i, a[i]);
}
free(p);
}
Of course, this will always print all the numbers, since memcpy() will never fail to copy the memory. :)
Here You have declared the return type of main function as int, but you are not returning anything from it.
So return any integer value (like 1) or make the main function's return type void.