Getting Segmentation Fault on simple loops - c

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);
}
}
}
}
}

Related

dynamic allocation string C

I want the user to enter 3 names, and right after the program prints these 3 names
can someone tell me why is not printing anything???
I tried everything
if someone could explain it.....
there is no error, it simply exits after inserting the strings
#include <stdio.h>
#include <stdlib.h>
int main(){
int i, a, componentes;
char *nome;
componentes = 3;
nome = (char*) malloc(sizeof(char)*100);
printf("\n");
for(i = 0; i < componentes; i++){
// printf("String %d: ", i+1);
scanf("%s", &nome[i]);
}
printf("\n");
for(a = 0; a < componentes; a++){
printf("%s\n", nome[i]);
}
return 0;
}
I fixed the issues raised (plus free'ing the memory):
#include <stdio.h>
#include <stdlib.h>
#define N 3
#define LEN 100
int main() {
char *components[N];
for(int i = 0; i < N; i++) {
components[i] = malloc(LEN);
fgets(components[i], LEN, stdin);
}
for(int i = 0; i < N; i++) {
printf("%s", components[i]);
free(components[i]);
}
return 0;
}
You could also allocate the 300 bytes for the 3 strings via local variable on the stack, either with char components[N][LEN]; or as a single string that you index just to show you a different way:
#include <stdio.h>
#include <stdlib.h>
#define N 3
#define LEN 100
int main() {
char components[N * LEN];
for(int i = 0; i < N; i++) {
fgets(components + i * LEN, LEN, stdin);
}
for(int i = 0; i < N; i++) {
printf("%s", components + i * LEN);
}
return 0;
}

Why is there a segmentation fault in 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("", "");
}

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;
}

C How to turn strings passed by command into array

I'm trying to turn strings into arrays. However, when I try to print the values to test it, it won't print anything.
Command
a.c BTC IOT NEO ETH XRP
Expected Output
BTC.csv
IOT.csv
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct
{
char m[9];
}moeda;
int main(int argc, char *argv[]){
FILE *csv;
int n = argc-1;
moeda *m;
m = (moeda*)malloc(n*sizeof(moeda));
for(int z=1; z<=n; z++)
{
int i = 0;
sprintf(m[i].m, "%s.csv", argv[z]);
i++;
}
printf("%s\n", m[0].m);
printf("%s\n", m[1].m);
return 0;
}
You declare i inside the loop, meaning it gets set to 0 for each iteration. Try
int i = 0;
for(int z=1; z<=n; z++)
{
sprintf(m[i].m, "%s.csv", argv[z]);
i++;
}
Or just
for(int z=1; z<=n; z++)
{
sprintf(m[z - 1].m, "%s.csv", argv[z]);
}

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;
}

Resources