Why is there a segmentation fault in C? - c

I am trying to solve this:
https://www.reddit.com/r/dailyprogrammer/comments/ffxabb/20200309_challenge_383_easy_necklace_matching/
where you check if words can be rearranged by moving the last letter of one to the front(can be done multiple times) and I keep getting a segmentation fault on line 37. Does anyone know why?
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
void shift(string, int);
bool same_necklace(string a, string b)
{
if(strlen(a) != strlen(b))
{
printf("false\n");
return false;
}
int n = strlen(a);
for(int i = 0; i < n; i++)
{
shift(a, n);
if(strcmp(a, b) == 0)
{
printf("true\n");
return true;
}
}
printf("false\n");
return false;
}
void shift(string a, int n)
{
char output[n];
for(int i = 0; i < n; i++)
{
output[i] = a[(i+1) % n];
}
for(int i = 0; i < n; i++)
{
a[i] = output[i];
}
}
int main(void)
{
same_necklace("nicole", "icolen");
same_necklace("nicole", "lenico");
same_necklace("nicole", "coneli");
same_necklace("aabaaaaabaab", "aabaabaabaaa");
same_necklace("abc", "cba");
same_necklace("xxyyy", "xxxyy");
same_necklace("xyxxz", "xxyxz");
same_necklace("x", "x");
same_necklace("x", "xx");
same_necklace("x", "");
same_necklace("", "");
}

You're trying to store values to a string literal, which is read-only memory on modern OSes.
To fix it make a copy of the string you're going to shift before-hand. Remember to make room for the null-terminator and free your memory after you're done:
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
void shift(string, int);
bool same_necklace(string a, string b)
{
int n = strlen(a);
a = memcpy(malloc(n + 1), a, n + 1);
if(strlen(a) != strlen(b))
{
printf("false\n");
return false;
}
for(int i = 0; i < n; i++)
{
shift(a, n);
if(strcmp(a, b) == 0)
{
printf("true\n");
return true;
}
}
printf("false\n");
free(a);
return false;
}
void shift(string a, int n)
{
char output[n];
for(int i = 0; i < n; i++)
{
output[i] = a[(i+1) % n];
}
for(int i = 0; i < n; i++)
{
a[i] = output[i];
}
}
int main(void)
{
same_necklace("nicole", "icolen");
same_necklace("nicole", "lenico");
same_necklace("nicole", "coneli");
same_necklace("aabaaaaabaab", "aabaabaabaaa");
same_necklace("abc", "cba");
same_necklace("xxyyy", "xxxyy");
same_necklace("xyxxz", "xxyxz");
same_necklace("x", "x");
same_necklace("x", "xx");
same_necklace("x", "");
same_necklace("", "");
}

Related

Return the strings that are smaller (lexicographically) from a given string

Given array of strings, its size and another 1 string, I need to return an array of strings, which these strings are < (lexicographically) from the given string. Also: return the length of the returned array using given pointer size_res.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** LowerSTR(char* arr[], int size_arr, char* str, int* size_res) {
size_t i, j;
char** barr = malloc(size_arr);
*size_res = 0;
------> printf("TEST"); <-----
for(i=0; i<size_arr; i++) {
for(j=0; j<strlen(str); j++) {
if (arr[i][j] == '\0' || (int)(arr[i][j]) < (int)(str[j])) {
barr[(*size_res)++] = arr[i];
break;
}
else if ((int)(arr[i][j]) == (int)(str[j])) {
continue;
}
else {
break;
}
}
}
if (*size_res == 0) return NULL;
return barr;
}
I tried to test my code with this main:
int main() {
int* len;
char* arr[] = {"hello", "hola"};
char** ans = LowerSTR(arr, 2, "bonjour", len);
printf("%d", *len);
return 0;
}
But the line above the test printf(highlighted with ----> <---- in the function) causes error: segmentation fault - I cannot understand why..
code with strcmp:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** LowerSTR(char* arr[], int size_arr, char* str, int* size_res) {
size_t i;
char** barr = malloc(size_arr);
*size_res = 0;
for(i=0; i<size_arr; i++) {
if (strcmp(arr[i], str) <= 0)
barr[(*size_res)++] = arr[i];
}
if (*size_res == 0) return NULL;
return barr;
}

Creating list of ip addresses over a specific range in C

I am writing a tool to scan all the nodes on a network but I have ran in to a problem. I'm writing the tool in C but I'm new to the language so I'm not sure how the iterate through the address range.
The user will give the argument 192.168.*.* and it will create every IP address in that range, e.g. 192.168.1.1, 192.168.1.2, 192.168.1.3 and then eventually 192.168.2.1, 192.168.2.2, 192.168.2.3 etc.
My previous code was:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void scanner(int s)
{
char addr[20];
for (int i = 0; i < 255; ++i)
{
sprintf(addr, "192.168.%d.%d", s, i);
printf("%s\n", addr);
}
}
int main()
{
for (int i = 0; i < 255; ++i)
{
scanner(i);
}
return 0;
}
But I don't know how to run this from the user input.
You can take the inputs from the user using the scanf function. I have updated your code to use the same -
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int addr_byte_0;
int addr_byte_1;
void scanner(int s)
{
char addr[200];
int i;
for (i = 0; i < 255; ++i)
{
sprintf(addr, "%d.%d.%d.%d", addr_byte_0, addr_byte_1, s, i);
printf("%s\n", addr);
}
}
int main()
{
int i;
//printf("Enter the first byte of the address: ");
scanf ("%d", &addr_byte_0);
//printf("Enter the second byte of the address: ");
scanf ("%d", &addr_byte_1);
for (i = 0; i < 255; ++i)
{
scanner(i);
}
return 0;
}
Also, as per C standards you cannot declare a variable inside the for loop. Hence I have moved the declaration out of the for loop. Hope this helps!
Inspired by (e.g. python-) generators, my solution doesn't perform dynamic memory allocation and and has constant memory consumption. I don't like that I currently rely on a do while loop. Also the explicit check for ig->num_wildcards == 0 is ugly. Anyways:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define IP_OCTETS 4
#define MAX_UCHAR 255
typedef struct {
int wildcard_pos[IP_OCTETS];
int num_wildcards;
int counter[IP_OCTETS];
int octet[IP_OCTETS];
} ip_generator;
char* mystrsep(char** stringp, const char* delim)
{
char* start = *stringp;
char* p;
p = (start != NULL) ? strpbrk(start, delim) : NULL;
if (p == NULL)
{
*stringp = NULL;
}
else
{
*p = '\0';
*stringp = p + 1;
}
return start;
}
void init_ip_gen(ip_generator *ig, char* ip_mask)
{
char *token, *string;
char* ip_mask_ptr = ip_mask;
const char delimiters[] = ".";
int i = 0;
while ((token = mystrsep(&ip_mask_ptr, delimiters)) != NULL)
{
ig->wildcard_pos[i] = -1;
if (strcmp(token, "*") == 0)
{
ig->wildcard_pos[ig->num_wildcards] = i;
ig->counter[ig->num_wildcards] = 1;
ig->num_wildcards++;
}
else
{
ig->octet[i] = atoi(token);
}
i++;
}
}
int ig_next(ip_generator *ig)
{
int i;
int carry = 1;
if (ig->num_wildcards == 0)
{
return 0;
}
for (i = ig->num_wildcards - 1; i >= 0; i--)
{
if (carry == 1)
{
if (ig->counter[i] == MAX_UCHAR)
{
ig->counter[i] = 1;
}
else
{
ig->counter[i]++;
carry = 0;
}
}
if (carry == 0)
{
break;
}
if (i == 0 && carry == 1)
{
return 0;
}
}
return 1;
}
void generate_ip(ip_generator *ig, char *ip)
{
int i;
int j = 0;
int oct[IP_OCTETS];
for (i = 0; i < IP_OCTETS; i++)
{
if (i == ig->wildcard_pos[j])
{
oct[i] = ig->counter[j];
j++;
}
else
{
oct[i] = ig->octet[i];
}
}
sprintf(ip, "%d.%d.%d.%d", oct[0], oct[1], oct[2], oct[3]);
}
int main()
{
char ip_mask[] = "192.*.10.*";
//char ip_mask[] = "192.1.10.123";
ip_generator ig;
memset(&ig, 0, sizeof(ig));
init_ip_gen(&ig, ip_mask);
char ip[32];
memset(ip, 0, sizeof(ip));
do
{
generate_ip(&ig, ip);
printf("%s\n", ip);
} while (ig_next(&ig));
return 0;
}

Getting Segmentation Fault on simple loops

I'm trying to execute this code (yes, with that two lines commented out), but every time I get a Segmentation Fault.
I can't understand why.
(linux, gcc)
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *current;
while(strcmp("99999999zz", current) != 0)
{
for(int i = 0; i < pow(10, 10); i++)
{
sprintf(current, "%010d", i);
printf("%s\n", current);
for(int a = 97; a <= 122; a++)
{
for(int j = 0; j < 10; j++)
{
//current[j] = (char)a;
//printf("%s\n", current);
}
}
}
}
}
This code, instead, runs without problems:
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *current;
while(strcmp("99999999zz", current) != 0)
{
for(int i = 0; i < pow(10, 10); i++)
{
sprintf(current, "%010d", i);
printf("%s\n", current);
}
}
}
You invoked undefined behavior in both programs by using value of uninitialized variable having automatic storage duration, which is indeterminate.
You should declare an array instead of a pointer and initialize it.
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(int argc, char *argv[])
{
double limit = pow(10, 10); /* calculating this every time in the loop may cause loss of performance */
char current[128] = ""; /* allocate enough memory and initialize */
while(strcmp("99999999zz", current) != 0)
{
for(int i = 0; i < limit; i++)
{
sprintf(current, "%010d", i);
printf("%s\n", current);
for(int a = 97; a <= 122; a++)
{
for(int j = 0; j < 10; j++)
{
//current[j] = (char)a;
//printf("%s\n", current);
}
}
}
}
}

How to make an Array equal another array in C

I am having trouble making an array equal another array in c.
in the main method it will not let me assign inputInt1 to the returned value of converTwosComp.
#include <stdio.h>
#include <stdlib.h>
int validChecker(char *input_StringIn);
int* convertTwosComp(char *inputStringIn, int *inputIntIn);
int main(void) {
char inputString1[11];
char inputString2[11];
int inputInt1[11];
int inputInt2[11];
printf(" is ");
inputInt1 = convertTwosComp(inputString1, inputInt1);
for(i = 0; inputString1[i]; i++){
printf("%d", inputInt1[i]);
}
int * convertTwosComp(char *inputStringIn, int *inputIntIn){
int digit;
int i;
if((inputStringIn[0] == '+') ||(inputStringIn[0]) == '0'){
inputStringIn[0] = 0;
}
if(inputStringIn[0] == '-'){
inputStringIn[0] = 1;
}
for(i = 0; inputStringIn[i]; i++){
digit = inputStringIn[i] - '0';
inputStringIn[i] = digit;
}
for(i = 0; inputIntIn[i]; i++){
if(inputIntIn[i] == 0){
inputIntIn[i] = 1;
}
if(inputIntIn[i] == 1){
inputIntIn[i] = 0;
}
}
return inputIntIn;
}
in the main method it will not let me assign inputInt1 to the returned value of converTwosComp.
This is what you probably need:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char array1[] = "Michi";
size_t len = strlen(array1);
char *array2 = malloc(len+1);
memcpy(array2, array1, len+1);
printf("Array2 = %s\n",array2);
free(array2);
return 0;
}
Output:
Array2 = Michi
You can always use a for loop to copy a string, in case you do not want to use memcpy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char one[30];
char two[30];
while(fgets(one,sizeof(one),stdin))
{
int len = strlen(one);
for(int i = 0; i < (len + 1); i++)
{
two[i] = one[i];
}
printf("%s", two);
break;
}
return EXIT_SUCCESS;
}

Caesar Cipher not returning correct key

So my decrypter program seems to not be able to find the key and implement it by itself. I noticed that if I changed the key to equal -5 which is the correct key it would print out the decrypted text correctly. However I am unable to figure out how to make the program figure it out by itself without having me to put it in manually. Any help would be greatly appreciated! Thank you!
rotUtils.h
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "rotUtils.h"
int rotate(int c, int n){
if (n == 0) return c;
int nRot = abs(n) % (RANGECHAR + 1);
if(n > 0)
return rotatePlus(c + nRot);
else
return rotateMinus(c - nRot);
}
int rotatePlus(int sum){
int diff = sum - MAXCHAR;
if (sum > MAXCHAR) sum = MINCHAR + diff - 1;
return sum;
}
int rotateMinus(int sum){
int diff = MINCHAR - sum;
if (sum < MINCHAR) sum = MAXCHAR - diff + 1;
return sum;
}
decrypt.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "rotUtils.h"
bool solved( char decodearr[], char dictarr[][30], int size1, int size2){
char* compared;
bool result = false;
for(int j = 0; j < size2; j++){
compared = strstr( decodearr, dictarr[j]);
}
if( compared != '\0'){
result = true;
}
return result;
}
int decode( char codearr[], char dictarr[][30], int size1, int size2)
{
bool solution = false;
int key = -50; This is where I had to change it to -5 to solve
char decodearr[10000];
while(solution == false && key < 51)
{
for( int i = 0; i < size1; i++)
{
if(!isspace(codearr[i]))
{
decodearr[i] = rotate(codearr[i], key);
}
else
decodearr[i] = codearr[i];
}
solution = solved( decodearr, dictarr, size1, size2);
if( solution == false)
{
key++;
}
}
for( int j = 0; j < size1; j++)
{
codearr[j] = decodearr[j];
}
return key;
}
int main( int argc, char* argv[])
{
char* file = argv[1];
char* dictionary = argv[2];
char code[10000];
char dict[30000][30];
FILE* codeFile;
codeFile = fopen(file, "r");
int i = 0;
int j = 0;
int key;
FILE* dictFile;
dictFile = fopen(dictionary, "r");
while(!feof(codeFile))
{
code[i] = fgetc(codeFile);
i++;
}
code[ i ]= '\0';
fclose(codeFile);
while(!feof(dictFile))
{
fscanf(dictFile, "%s", dict[j]);
j++;
}
key = decode(code, dict, i, j);
fclose(dictFile);
for(int k = 0; k < i; k++)
{
printf("%c", code[k]);
}
printf( "\nThe key is: %d\n", key);
return 0;
}
Solved() will only return true if there is a match on the last dictionary word currently, you have to move that check inside. You could print to screen whenever you find a key that has a match on your dictionary and/or keep a list of possible keys then print after you are done with them all, right now you would exit as soon as you find any match even if it was just luck.

Resources