I was writing a program in C for lexicographically sorting the strings entered by user , but whenever i am entering a string with string length greater than 3 my code shows some garbage values and i am not able to understand why ?
My line of Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void lexiiographic_sort(char** , int );
int main(void)
{
int n;
scanf_s("%d", &n);
char** arr;
arr = (char**)malloc(n * sizeof(char*));
for (int i = 0; i < n; i++)
{
if ((*(arr + i) = (char*)malloc(1024 * sizeof(char))) == NULL) { exit(1); }
scanf_s("%s", *(arr + i),sizeof(*(arr + i)));
if ((*(arr + i) = (char*)realloc(*(arr + i), strlen(*(arr + i)) + 1)) == NULL) { exit(1); }
printf("%s\n", *(arr + i));
}
lexiiographic_sort(arr, n);
for (int i = 0; i < n; i++)
{
printf("%s\n", *(arr + i));
}
}
void lexiiographic_sort(char** string, int size)
{
char* temp;
for (int i = 1; i < size; i++)
{
for (int j = 1; j < size; j++)
{
if ((int)(*(*(string + j - 1))) > (int)(*(*(string + j))))
{
if ((temp = (char*)malloc(strlen(*(string + i - 1)) * sizeof(char) + 1)) == NULL) { exit(1); }
temp = *(string + j - 1);
if((temp = ((char*)realloc(temp, strlen(*(string + j)) * sizeof(char) + 1))) == NULL){exit(1); }
*(string + j - 1) = *(string + j);
*(string + j) = temp;
}
}
}
}
}
You cannot get size of dynamically allocated buffer via sizeof. sizeof(*(arr + i)) is the size of a pointer char*. It seems it is 4 in your environment and it is the reason of the 3-character limit (one is left for terminating null-character).
You used the hard-coded number 1024 as the buffer size, so use that instead.
scanf_s("%s", *(arr + i),1024);
Defining a macro for buffer size and using them will improve your code more.
Related
I am working on a project in which I need to check neighboring cells of a specific cell in a dynamically allocated 2D char array. Basically, If certain neighboring cells are 'X' for example, then the current cell you are on becomes '-'. To allocate the 2D array, I used a single malloc call:
char *array = (char *)malloc(numRows * numCols * sizeof(char));
To access an element while using a double for loop, I use this:
for (int i = 0; i <= getNumRows(); i++)
{
for (int j = 0; j < getNumCols(); j++)
{
printf("%c ", **(array + i * getNumCols() + j));
}
printf("\n");
}
How would I access and view the neighboring cells of the current element?
The code posted to display the matrix has problems:
the outer loop should stop when i == getNumRows() and
the printf argument should use a single * dereferencing operator
Here is a modified version:
for (int i = 0; i < getNumRows(); i++) {
for (int j = 0; j < getNumCols(); j++) {
printf("%c ", *(array + i * getNumCols() + j));
}
printf("\n");
}
Which can also be rewritten to avoid recomputing the matrix sizes repeatedly:
for (int i = 0, row = getNumRows(), cols = getNumCols(); i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%c ", array[i * cols + j]);
}
printf("\n");
}
Accessing the neighbouring cells of cell r,c depends on how you deal with boundaries:
if boundaries should not be crossed, you must test if r and/or c are on a boundary to produce between 3 and 8 neighbours.
if boundaries wrap as a torus, you can just compute r+/-1 % rows and c+/-1 % cols to always produce 8 neighbours.
To simplify the first case, you can allocate the matrix with 2 extra columns and rows, with char *array = malloc(sizeof(char) * (numRows + 1) * (numCols + 2)); and use the inner space (active area) this way:
for (int i = 1; i <= getNumRows(); i++) {
for (int j = 1; j <= getNumCols(); j++) {
printf("%c ", *(array + i * getNumCols() + j));
}
printf("\n");
}
If you initalize the boundary rows and columns in the matrix as ' ', you can always access the 8 cells at r+/-1, c+/-1 and check for 'X' without special casing the boundary rows of the active part.
Accessing these neighbouring cells can be done according to the implementation choices:
int rows = getNumRows(), cols = getNumCols();
char *cellp = array + r * cols + c;
// using extra rows and columns
char top_1 = cellp[-cols - 1];
char top_2 = cellp[-cols];
char top_3 = cellp[-cols + 1];
char mid_1 = cellp[-1];
char mid_2 = cellp[+1];
char bot_1 = cellp[+cols - 1];
char bot_2 = cellp[+cols];
char bot_3 = cellp[+cols + 1];
// using torus-like wrapping
char top_1 = array[(r + rows - 1) % rows * cols + (c + cols - 1) % cols];
char top_2 = array[(r + rows - 1) % rows * cols + c];
char top_3 = array[(r + rows - 1) % rows * cols + (c + 1) % cols];
char mid_1 = array[r * cols + (c + cols - 1) % cols];
char mid_2 = array[r * cols + (c + 1)];
char bot_1 = array[(r + 1) % rows * cols + (c + cols - 1) % cols];
char bot_2 = array[(r + 1) % rows * cols + c];
char bot_3 = array[(r + 1) % rows * cols + (c + 1) % cols];
// using tests
char top_1 = (r == 0 || c == 0 ) ? 0 : cellp[-cols - 1];
char top_2 = (r == 0 ) ? 0 : cellp[-cols];
char top_3 = (r == 0 || c == cols - 1) ? 0 : cellp[-cols + 1];
char mid_1 = ( c == 0 ) ? 0 : cellp[-1];
char mid_2 = ( c == cols - 1) ? 0 : cellp[+1];
char bot_1 = (r == rows - 1 || c == 0 ) ? 0 : cellp[+cols - 1];
char bot_2 = (r == rows - 1 ) ? 0 : cellp[+cols];
char bot_3 = (r == rows - 1 || c == cols - 1) ? 0 : cellp[+cols + 1];
I would use a pointer to the array. It makes array indexing much easier. Example prints neighbouring cells.
void print_n(void *arr, size_t nrows, size_t ncols, size_t col, size_t row)
{
int (*array)[nrows][ncols] = arr;
if(col) printf("Left: %d\n", (*array)[row][col - 1]);
if(col < ncols - 1) printf("Right: %d\n", (*array)[row][col + 1]);
if(row) printf("Top: %d\n", (*array)[row - 1][col]);
if(row < nrows - 1) printf("Right: %d\n", (*array)[row + 1][col]);
}
int main(void)
{
size_t ncols = 10, nrows = 20;
int (*array)[nrows][ncols] = malloc(sizeof(*array));
for(size_t row = 0; row < nrows; row++)
for(size_t col = 0; col < ncols; col++)
(*array)[row][col] = row * 100 + col;
print_n(array, nrows, ncols, 6, 7);
free(array);
}
https://godbolt.org/z/7Yoff5
so I was writing this code for the game of life using C on linux but i got this warning! what does this warning mean and how can i fix it ?. The code i wrote is :
#include <stdio.h>
#include <string.h>
#include <omp.h>
#include <stdlib.h>
#include <assert.h>
#define MAX_N 2000
int plate[2][(MAX_N + 2) * (MAX_N + 2)];
int which = 0;
int n;
int live(int index){
return (plate[which][index - n - 3]
+ plate[which][index - n - 2]
+ plate[which][index - n - 1]
+ plate[which][index - 1]
+ plate[which][index + 1]
+ plate[which][index + n + 1]
+ plate[which][index + n + 2]
+ plate[which][index + n + 3]);
}
void iteration(){
#pragma omp parallel for schedule(static)
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
int index = i * (n + 2) + j;
int num = live(index);
if(plate[which][index]){
plate[!which][index] = (num == 2 || num == 3) ?
1 : 0;
}else{
plate[!which][index] = (num == 3);
}
}
}
which = !which;
}
void print_plate(){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
printf("%d", plate[which][i * (n + 2) + j]);
}
printf("\n");
}
printf("\0");
}
int main(){
int M;
char line[MAX_N];
memset(plate[0], 0, sizeof(int) * (n + 2) * (n + 2));
memset(plate[1], 0, sizeof(int) * (n + 2) * (n + 2));
if(scanf("%d %d", &n, &M) == 2){
for(int i = 1; i <= n; i++){
scanf("%s", &line);
for(int j = 0; j < n; j++){
plate[0][i * (n + 2) + j + 1] = line[j] - '0';
}
}
for(int i = 0; i < M; i++){
iteration();
}
print_plate();
}
return 0;
}
it would be so much appreciated if you could help me fix cause i think this should have work fine.
You have this:
scanf("%s", &line);
line is of type char[2000] (MAX_N). By taking the address-of operator of it, you are getting a type of char(*)[2000]. Get rid of the & and instead you will have type char[2000] which will decay to the char* you need.
There are a few errors in the code:
You're trying to scan a variable line by addressing it in the scanf() function. This could be solved if you remove the ampersand & sign from there.
Explained answer is though already provided in the first answer of this question.
Using the statement:
printf("\0"); // format contains a (null)
is totally meaningless. You're trying to print something which doesn't exists - a null.
The pragma:
#pragma omp parallel for schedule(static)
will be ignored as per of -Wunknown-pragmas flag.
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.
sir i am a new programmer.So i am facing some new problems which I really need to solve. Like I write a code
#include<stdio.h>
main(){
int ara[] ={10,20,30,40,50,60,70,80,90,100},i,temp,j;
for(i=0,j=9;i<10;i++,j--){
ara[i]=ara[j];
printf("%d\n",ara[i]); }
}
I thought the result would be 100,90,80,70,60,50,40,30,20,10 but the result is not like this...Would anyone please tell me why the result shows 100,90,80,70,60,60,70,80,90,100
After printing value 60, i.e. half of the array when you try to access elements further, actually you will access those elements which are of the locations after mid of the array. because you are assigning them using ara[i] = ara[j]..so you will end up with repetition after half of array.
As:-
ara[0] = ara[9]
ara[1] = ara[8]
ara[2] = ara[7]
ara[3] = ara[6]
ara[4] = ara[5]
ara[5] = ara[4]
The simplest solution may be creating a temporary array:-
#include<stdio.h>
main(){
int ara[] ={10,20,30,40,50,60,70,80,90,100},i,temp[10],j;
for(i = 9, j = 0; i >= 0; i--, j++){
temp[j]=ara[i];
}
for(i = 0; i < 10; i++){
printf("%d\n", temp[i]);
}
}
What you are doing in this code?
reversing an array
Why are you printing 100,90,80,70,60,50,60,70,...
because when you reach the 6th one (ara[4]), you've already swapped it with 4th one (ara[6])
You need to save in the temporary variable the value which is written first
Some examples
char *reverse(char *str)
{
char tmp;
int len;
if (str != NULL)
{
len = strlen(str);
for (int i = 0; i < len / 2; i++)
{
tmp = *(str + i);
*(str + i) = *(str + len - i - 1);
*(str + len - i - 1) = tmp;
}
}
return str;
}
int *reverseints(int *data, size_t size)
{
int tmp;
if (data != NULL)
{
for (int i = 0; i < size / 2; i++)
{
tmp = *(data + i);
*(data + i) = *(data + size - i - 1);
*(data + size - i - 1) = tmp;
}
}
return data;
}
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.