This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 4 years ago.
#include <stdio.h>
#include <string.h>
char* longestConsec(char* strarr[], int n, int k)
{
char* longest_arr[k];
unsigned int longest_len = 0;
if (n == 0 || k > n || k <= 0)
return "";
for (int i = 0; i < (n - (k - 1)); i++)
{
/*
if(( strlen(strarr[i]) + strlen(strarr[i + 1]) ) > longest_len)
{
longest_len = strlen(strarr[i]) + strlen(strarr[i + 1]);
memmove(longest_arr1, strarr[i], 10);
memmove(longest_arr2, strarr[i + 1], 10);
}
*/
unsigned int cmp_len = 0;
// get the length of every k consecutive string in a list and add them up to cmp_len
for (int j = 0; j < k; j++)
cmp_len += strlen( strarr[i + j] );
// compare if cmp_len is greater than longest_len then add that string into longest_arr overlap the previous one
if (cmp_len > longest_len)
{
for (int m = 0; m < k; m++)
memmove(longest_arr[m], strarr[i + m], strlen(strarr[i + m]) + 1); // the first suspect
longest_len = cmp_len;
}
}
// if there is more than 1 consecutive string then the output is combine of k consecutive string in the list
if (k > 1)
{
for (int l = k - 1; l >= 0; l--)
strcat(longest_arr[l - 1], longest_arr[l]); // the second suspect
}
// return the longest_arr[0] the string that have been combine
return longest_arr[0];
}
int main(void)
{
// test subject
char* a1[] = {"zone", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"};
char* newstring = longestConsec(a1, 8, 2);
printf("%s\n", newstring);
return 0;
}
when i try to run it got Segmentation fault. I suspect it is the memcpy and strcpy function but don't know how to fix it.
The code is suppose to do get in a list of string and then check k consecutive string in that list, and print out the concatenation of those string.
The problem is here
char* longest_arr[k];
for (int m = 0; m < k; m++)
memmove(longest_arr[m], strarr[i + m], strlen(strarr[i + m]) + 1); /* there is no memory allocated for longest_arr[m] */
Since longest_arr is array of k character, you should allocate memory for each longest_arr[m]. for e.g
for (int m = 0; m < k; m++) {
longest_arr[m] = malloc(SIZE); /* Allocate memory here, define the SIZE */
memmove(longest_arr[m], strarr[i + m], strlen(strarr[i + m]) + 1);
}
And don't forget to free the dynamically allocated memory by calling free() function to avoid memory leakage.
Related
I have a variable string, that I need to slice into smaller strings, the main string should be treated as a bidimensional array with a certain width and height MxM, and the smaller strings should be cut in blocks of NxN size. So for example, if I have the following string, char source[17] = "ABCDEFGHIJKLMNS0" and his bidimensional size is 4x4, and the size of the smaller blocks are 2x2, the smaller blocks should be ABEF, CDGH, IJMN, KLSO.
In other words, the string should be seeing as
ABCD
EFGH
IJKL
MNSO
and NxN should be cut from it, like:
AB
EF
Always with the constraint that these blocks should be linear arrays as the main string.
I have tried with 3 nested for, with the following code, but I didn't know how to calc the index of the main array in order to cut the blocks that way
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char pixelsSource[17] = "ABCDEFGHIJKLMNS0";
char pixelsTarget[4][5];
int Y = 0;
int X = 0;
for (int block = 0; block < 4; block++)
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
pixelsTarget[block][(i * 2) + j] = pixelsSource[(i * 2) + j];
printf("[%d][%d] = [%d] \n", block, (i * 2) + j, (i * 2));
}
}
}
for (int block = 0; block < 4; block++)
{
printf("%s\n", pixelsTarget[block]);
}
}
I broke this down into a more piece-by-piece way and generalized it for M & N. Here's the code, with inline comments:
#include <stdio.h>
#define M 4
#define N 2
int main(void)
{
// source data is an M * M string(plus null terminator)
char pixelsSource[M * M + 1] = "ABCDEFGHIJKLMNSO";
// destination is an array of N*N strings; there are M*M/N*N of them
char pixelsTarget[(M*M)/(N*N)][N*N + 1];
// iterate over the source array; blockX and blockY are the coordinate of the top-left corner
// of the sub-block to be extracted
for (int blockX = 0; blockX < M; blockX += N)
{
for (int blockY = 0; blockY < M; blockY += N)
{
int dstWord = blockX/N + blockY;
// for each letter in the sub-block, copy that letter over to the destination array
for (int y = 0; y < N; y++)
{
for (int x = 0; x < N; x++)
{
int dstIndex = y*N + x;
int srcIndex = (blockY + y)*M + blockX + x;
printf("[%d][%d] = [%d]\n", dstWord, dstIndex, srcIndex);
pixelsTarget[dstWord][dstIndex] = pixelsSource[srcIndex];
}
}
// null-terminate destination word
pixelsTarget[dstWord][N*N] = '\0';
}
}
// output
for (int block = 0; block < (M * M) / (N * N); block++)
{
printf("%s\n", pixelsTarget[block]);
}
}
i want to rotate the string one place at a time and print all the rotations
Input : S = "abc"
Output : abc
bca
cab
im trying to concatenate the string and then printing it, but the problem is input string can be of size 10^5 so my array would require to be of 10^10 size.
but im unable to declare that size array, so i wanted a to know if there is a better way to do it
void printRotatedString(char str[])
{
int n = strlen(str);
// Concatenate str with itself
char temp[2*n + 1];
strcpy(temp, str);
strcat(temp, str);
// Print all substrings of size n.
for (int i = 0; i < n; i++)
{
for (int j=0; j != n; j++)
printf("%c",temp[i + j]);
printf("\n");
}
}
i expect it to work even for 10^5 sized strings
You can do it, even without concatenation. But why do you need it? It will be better if you provide an actual problem source.
void printRotatedString(char str[]) {
int n = strlen(str);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%c", str[(i + j) % n]);
printf("\n");
}
}
We can come up with another solution using prefix sums. Let's calculate array c where c[i] = the number of letters in our string which are even(or another boolean function) from the beginning. We can calculate it easily if we know c[i - 1], c[i] would be c[i - 1] + 1 if i-th letter is even, c[i] = c[i - 1] otherwise.
So let's use the same idea, let's concatenate our string on its own. And then try to check every substring length of our input string. Having prefix sums, we can easily check if the left-hand side has more even elements than the right-hand side.
Here is the solution code:
int c[100500];
int isEven(char c) {
return c % 2 == 0;
}
int solve(char str[]) {
int n = strlen(str);
char temp[2*n + 1];
strcpy(temp, str);
strcat(temp, str);
for (int i = 0; i < n + n; i++) {
c[i + 1] = c[i] + isEven(temp[i]);
}
int counter = 0;
for (int i = 1; i + n <= n + n; ++i) {
int l = i, r = i + n - 1;
int mid = i + n / 2;
int leftSide = c[mid - 1] - c[l - 1];
int rightSide = c[r] - c[mid - 1];
if (leftSide > rightSide) {
++counter;
}
}
return counter;
}
I have the following code:
void sortStrings(char strings[5][32])
{
int i = 0, j = 0, wall = 0;
int min = i;
for (int i = wall; i < 5; i++){
min = i;
for (j = wall; j < 5; j++){
if (strcmp(strings[j], strings[min]) < 0){
min = j;
}
}
swapStrings(strings[min], strings[wall]);
wall++;
}
}
What this code does is sorts a 2d array of strings by alphabetical order, I have tested it and it works correctly, now my question is how could I implement this code WITHOUT using array operations (aka using pointers and pointer operations only).
This is what I have so far and it is crashing when I try to run it so what am I doing wrong?
{
int i = 0, j = 0, wall = 0;
char *p = strings;
int min;
for (i = wall; i < 5; i++){
min = i;
for (j = wall; j < 5; j++){
if (*(p + j) < *(p + min)){
min = j;
}
}
swapStrings(*(p + j),*(p + wall));
wall++;
}
}
Here is the swapStrings method I am using for reference:
void swapStrings(char string1[], char string2[])
{
char temp[32];
strcpy(temp, string1);
strcpy(string1, string2);
strcpy(string2, temp);
}
The expected output is: if I were to enter in 5 strings, lets say they are:
hello
goodbye
how
are
you
It should return:
are
goodbye
hello
how
you
Thank you.
You have two things wrong:
p have to be char** and not char*
Comparing yourself between strings need a loop such:
int t = 0;
while (*(*(p + j)+t) && (*(*(p + j) + t) == *(*(p + min) + t)))
t++;
if (*(*(p + j) + t) < *(*(p + min) + t)) {
min = j;
}
Maybe you want to write your function for compare.
I have a function that returns all the combinations of letters possible in the alphabet with repetition in a word of length LENTH_MAX. The function returns these combinations in a 2D array call 'arr'.
Since calculating the total number of arrays is a pain because you need to calculate factorial numbers [ (n + r - 1)!/r!(n - 1)! ] I decided to increasingly reallocate memory for the arrays in 'arr' as needed.
I set a variable called capacity that determinetes the initial size of 'arr' and a constant called CAP_INCR that specifies the number of arrays for which memory will be reallocated in addition to the memory already assigned. The program compiles ok by if I set CAP_INCR to 1, so that each time a new combination is found new memory is allocated for that array, the program crushes with a Segmentation fault: 11 message, if I set CAP_INCR to 100 if finishes correctly but the output is wrong, the first combination 'a a a' is repeated twice and the last combination 'z z z' is mission.
I'd really appreciate some help. I'm a decent programer in other languages but I'm just starting with C.
The code is:
#include <stdio.h>
#include <stdlib.h>
const unsigned short LENGTH_MAX = 3;
const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
#define CAP_INCR 1 /* memory increases */
unsigned char* combinations(unsigned char n, unsigned char r)
{
// n length of alphabet
// r length of figures
unsigned int set_counter = 0; //counting generated sequences
unsigned char *vector = NULL; //where the current figure is stored
unsigned char *arrTemp = NULL; // Temporary pointer store
unsigned int capacity = 100; // count current size of arr
unsigned char *arr = (unsigned char *)malloc(capacity * r * sizeof(unsigned char)); // multidimentional array
vector = (unsigned char *)malloc(sizeof(unsigned char) * r);
if(vector == NULL || arr == NULL)
{
fprintf(stderr, "error: insufficient memory\n");
exit(EXIT_FAILURE);
}
//initialize: vector[0, ..., r - 1] are 0, ..., r - 1
for(int l = 0; l < r; l++) //for(int l = 0; l < r; l++) // no repetition
vector[l] = 0;
//generate all successors
while(1)
{
set_counter++;
// check is arr current capacity is enough
if(set_counter > capacity)
{ // We need more memory
capacity += CAP_INCR;
arrTemp = (unsigned char *)realloc(arr, capacity * r * sizeof(unsigned char));
if(!arrTemp)
{
printf("Unfortunately memory reallocation failed.\n");
free(arr);
arr = NULL;
exit(0);
}
arr = arrTemp;
}
for(int x = 0; x < r; x++) { // assign a new combination to arr
//printf("%c ", alphabet[vector[x]]);
*(arr + set_counter*r + x) = vector[x];
}
//printf("(%u)\n", set_counter);
int j; //index
//easy case, increase rightmost element
if(vector[r - 1] < n - 1)
{
vector[r - 1]++;
continue;
}
//find rightmost element to increase
for(j = r - 2; j >= 0; j--) {
if(vector[j] != n - 1) {
break;
}
}
//terminate if vector[0] == n - r
if(j < 0)
break;
//increase
vector[j]++;
//set right-hand elements
for(j += 1; j < r; j++)
vector[j] = vector[j - 1];
}
return arr;
}
int main() {
unsigned char* arr = combinations(sizeof(alphabet)-1, LENGTH_MAX);
int c=0;
for (int i = 0; i < 3276; i++) // 3276 is the total number of combinations
{
for (int j = 0; j < 3; j++)
{
printf("%c ", alphabet[*(arr + i*3 + j)]);
}
printf("count: %d\n",++c);
}
return 0;
}
I got this error in my rc4 algorithm, it works well, but i got this error every time when the message is too big, like 1000kB, here is the code:
char* rc4(const int* key, int key_size, char* buff, int buff_size){
int i, j, k;
int s[255], rk[255]; //rk = random_key
char* encrypted = alloc_char_buffer(buff_size);
for (i = 0; i < 255; i++){
s[i] = i;
rk[i] = key[i%key_size];
}
j = 0;
for (i = 0; i < 255; i++){
j = (j + s[j] + rk[i]) % 256;
SWITCH(s + i, s + j);
}
i = 0;
j = 0;
for (k = 0; k < buff_size; k++){
i = (i + 1) % 256;
j = (j + s[i]) % 256;
SWITCH(s + i, s + j);
//try{
//}
//catch ()
encrypted[k] = (char)(s[(s[i] + s[j]) % 256] ^ (int)buff[k]);
}
encrypted[buff_size] = 0;
return encrypted;
}
at the end o the last loop i got this error, i think this is some type of buffer overflow error, the only variable able to do that is the 'encrypted' but at the end of the loop, the value of the variable 'k' have the exactly same value of 'buff_size' that is used to alloc memory for 'encrypted', if someone can help i'll thank you
the 'encrypted' is "non-null terminated", so if the string have 10 bytes i will allocate only 10 bytes, not 11 for the '\0'
if you need, here is the code for alloc_char_buffer(unsigned int)
char* alloc_char_buffer(unsigned int size){
char* buff = NULL;
buff = (char*)calloc(size+1, sizeof(char));
if (!buff)
_error("program fail to alloc memory.");
return buff;
}
SWITCH:
//inversão de valores
void SWITCH(int *a, int *b){
*(a) = *(a) ^ *(b); //a random number
*(b) = *(a) ^ *(b); //get a
*(a) = *(a) ^ *(b); //get b
}
char* encrypted = alloc_char_buffer(buff_size);
/* ... */
encrypted[buff_size] = 10;
Here is the problem. You allocate buff_size elements. Thus, the last valid index is buff_size-1, not buff_size.
Another issue:
j = (j + s[j] + rk[i]) % 256;
Thus the range of j is [0, 255], but the legal index of s is only [0, 254]. You should either declare s as a 256-element array or review the algorithm implementation.
Your following line is creating the problem as you are trying to access beyond your allocated memory.
encrypted[buff_size] = 10;
Additionally, you should avoid use calloc instead of writing your own function alloc_char_buffer. It would allocate memory and initialize with 0.
calloc(buff_size, sizeof(char));