Why this C programming can not run crrectly? - c

It's just a sample test that I want to unite the list Lb and La without repeat element. It didn't work, and returned -1073741510, I think maybe the array overflow, but I can't find where the problem is
This is my code:
#include <stdio.h>
void Union(char *La, char *Lb);
int ListLength(char *L);
void GetElem(char *L, int i, char *e);
int LocateElem(char *L, char *e, int (*comp)(char a, char b));
int compare(char a, char b);
void ListInsert(char *, int, char *);
int main(){
char *La;
char *Lb;
int i;
for(i = 0; i <= 10; ++i){
La[i] = i;
Lb[i] = i + 5;
}
La[i] = '\0';
Lb[i] = '\0';
Union(La, Lb);
for(i = 0; La[i] != '\0'; ++i){
printf("%c\n", La[i]);
}
return 0;
}
//unite La and Lb without repeat elements
void Union(char *La, char *Lb){
int La_length = ListLength(La);
int Lb_length = ListLength(Lb);
int i = 0;
char *e;
for(i; i<= Lb_length; ++i){
GetElem(Lb, i, e);
if(!LocateElem(La, e, compare))
ListInsert(La, ++La_length, e);
}
}
//caculate the length of L
int ListLength(char *L){
int i;
for(i = 0; *(L + i) != '\0'; ++i);
return i;
}
void GetElem(char *L, int i, char *e){
*e = *(L + i);
}
//search the element e in L, if exist return the location, else return 0
int LocateElem(char *L, char *e, int (*comp)(char a, char b)){
int i;
for(i = 0; *(L + i) != '\0'; ++i){
if(comp(*(L + i), *e)) return i + 1;
}
return 0;
}
//compare the element a and b
int compare(char a, char b){
if(a == b) return 1;
return 0;
}
//if e doesn't exit in L, insert the e in L
void ListInsert(char *L, int i, char *e){
int j;
for(j = ListLength(L) - 1; j >= i; --j){
*(L + j + 1) = *(L + j);
}
L[ListLength(L)] = '\0';
*(L + i - 2) = *e;
}

First, this is wrong:
char *La;
char *Lb;
int i;
for(i = 0; i <= 10; ++i){
La[i] = i;
Lb[i] = i + 5;
}
You need to reserve memory for La and Lb, for instance, by declaring them as:
char La[12];
char Lb[12];
An then this:
char *e;
for(i; i<= Lb_length; ++i){
GetElem(Lb, i, e);
should read:
char e;
for(; i<= Lb_length; ++i){
GetElem(Lb, i, &e); /* better yet: e=Lb[i] */
Finally, you're most likely looping one time too many by using <= instead of < as the for exit condition.

You have several issues. I think you need to read more about what are raw pointers, fixed length arrays, variable length arras and dynamic arrays. If you need your array to grow you can make it dynamic with malloc and realloc. Alternatively you can use a "big" array you know never will overflow.
int La[12]; // 0 to 10, plus '\0'
But this is fixed and cannt grow. You could use
int La[1000]; // if it solve yours problems
But in general you will need dynamic arrays.
Also, you need to deside if your array can hold 0 or it is used as terminator. '\0' and 0, in the form you use it are equal. Many of your for cycle dont run because the first elemnt is 0.

Related

Converting Static 2D Array to Dynamic Array in C

We were asked to convert 2D static array to dynamic array. So I will need to create an array of pointers in which every pointer points to a different row. I have written this code but my code breaks when i=1 on line *(dynamicStr[i] + v) = rowStr[v]; Additionally, if I enable free(ptr); section my debugger gets stuck there for 6 or 7 times and then contiunes.
EDIT: In the end, I solved the problem with appying the answers #dodooft and #Viktor Terziev gave.
#include <stdio.h>
#include <stdlib.h>
void toDynamic(int x,int y, char toDyna[x][y]);
void toDynamic2(int x,int y, char toDyna[x][y]);
int main()
{
char toDyna[7][12] = {
"JOHN",
"MARK",
"PIERCEPIERCE",
"20",
"ROSIE",
"ALEX",
"MARLYN"
};
int x = 7;
int y = 12;
toDynamic2(x, y, toDyna);
return 0;
}
void toDynamic2(int x,int y, char toDyna[x][y]){
char *dynamicStr[x];
int rowToCheck = 0;
int size;
char *ptr;
int c;
for(int i = 0; i < x; i++){
printf("i: %d\n",i);
c = 0;
size = strlen(toDyna[rowToCheck]);
ptr = (char*) malloc(size * sizeof(char));
for(int j = 0; j < y; j++){
if(toDyna[i][j] != '\0'){
*(ptr+c) = toDyna[i][j];
c++;
} else{
break;
}
}
*(ptr+size) = '\0';
printf(" ");
char rowStr[size];
for(int v = 0; v < size; v++){
rowStr[v] = *(ptr+v);
printf("Added Char: %c\n", rowStr[v]);
*(dynamicStr[i] + v) = rowStr[v];
}
//free(ptr);
//printf("\n%s\n", rowStr);
//dynamicStr[i] = &rowStr;
rowToCheck++;
}
for(int i = 0; i < x; i++){
printf("%s\n", dynamicStr[i]);
}
}
EDIT: This is the working verion of the code:
#include <stdio.h>
#include <stdlib.h>
char** toDynamic(int x,int y, char toDyna[x][y]);
void free2DArray(int x, char **dynamicStr);
int main()
{
char toDyna[7][12] = {
"JOHN",
"MARK",
"PIERCEPIERCE",
"20",
"ROSIE",
"ALEX",
"MARLYN"
};
int x = 7;
int y = 12;
char **dynamicArr;
dynamicArr = toDynamic(x, y, toDyna);
free2DArray(x, dynamicArr);
return 0;
}
char** toDynamic(int x,int y, char toDyna[x][y]){
printf("Q2\n");
char **dynamicStr;
int rowToCheck = 0;
int size;
int c;
dynamicStr = (char*)malloc(x * sizeof(char*));
for(int i = 0; i < x; i++){
dynamicStr[i] = (char*)malloc(y * sizeof(char));
c = 0;
size = strlen(toDyna[rowToCheck]);
char *ptr = (char*) malloc((size + 1) * sizeof(char));
for(int j = 0; j < y; j++){
if(toDyna[i][j] != '\0'){
*(ptr+c) = toDyna[i][j];
c++;
} else{
break;
}
}
*(ptr+size) = '\0';
dynamicStr[i] = ptr;
rowToCheck++;
}
for(int i = 0; i < x; i++){
printf("%s\n", dynamicStr[i]);
}
printf("----------------------------\n");
return dynamicStr;
}
void free2DArray(int x, char **dynamicStr){
printf("Q3\n");
for(int i = 0; i < x; i++){
free(dynamicStr[i]);
printf("dynamicStr %d freed\n", i);
}
free(dynamicStr);
printf("dynamicStr array freed\n");
printf("----------------------------\n");
}
You define dynamicStr as an array of char pointers, when you are trying to assign a value to it with *(dynamicStr[i] + v) = rowStr[v]; you are basically copying the value of rowStr[v] to the address that is pointed by dynamicStr[i] + v. That address is not defined in your code, so you got a segfault.
If you are trying to fill dynamicStr with pointers to new arrays with dynamic memory, you should try something like
dynamicStr[i] = ptr;
where ptr is the pointer returned by the malloc call to the i-th row. Also, as you are working with strings you can use strcpy to copy the data from the static array to the dynamic one.
Its much easier than you think, please refer to strcpy documentation and strlen documentation, and (if you use my code) don't forget to free your memory.
char * * toDynamic2(size_t n, size_t m, char strings[n][m])
{
char * * arr = malloc(n * sizeof(char*));
for(size_t i = 0; i < n; ++i)
{
size_t size = strlen(strings[i]);
arr[i] = malloc((size + 1) * sizeof(char));
strcpy(arr[i], strings[i]);
}
for(size_t i = 0; i < n; ++i)
{
printf("%s\n", arr[i]);
}
return arr;
}

How can I pass Pointer Matrix to Function in C?

I tried what is described in these links:
How can I pass character pointer reference to function and get affected value back?
Passing pointers (matrix) to a function in c
Passing an array as an argument to a function in C
but I can't. Dimension of my array is 3 and I initialized it like this:
char* trips[N][2] = {{"ANKARA", "10:00"}, {"BURSA", "11:00"}, {"IZMIR", "12:00"}, {"ISTANBUL", "13:00"}, {"ANTALYA", "14:00"}}
so how can I pass this matrix into function?
My code is here and it doesn't sort or effect my array.
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef enum {
SortByCity,
SortByHour
}SortType;
void merge(char**, int, int, int, SortType);
void mergeSort(char**, int, int, SortType);
void mergeSortByHour(char**, int, int, SortType);
int main(int argc, char *argv[]) {
int i;
char* trips[N][2] = {{"ANKARA", "10:00"}, {"BURSA", "11:00"}, {"IZMIR", "12:00"}, {"ISTANBUL", "13:00"}, {"ANTALYA", "14:00"}, {"ANKARA", "11:00"}, {"ISTANBUL", "13:00"}, {"ANKARA", "11:30"}, {"BURSA", "21:00"} , {"BURSA", "13:00"}};
mergeSort(**trips, 0, N-1, SortByCity);
for(i = 0; i < N; i++){
printf("%-10s %s\n", trips[i][0], trips[i][1]);
}
return 0;
}
void merge(char** T, int L, int M, int H, SortType S){
int i, j, k;
int N1 = M - L + 1;
int N2 = H - M;
char* LA[N1][2], RA[N2][2];
for (i = 0; i < N1; i++){
LA[i][S] = T[L+i][S];
LA[i][1-S] = T[L+i][1-S];
}
for (j = 0; j < N2; j++){
RA[j][S] = T[L+j][S];
RA[j][1-S] = T[L+j][1-S];
}
i = 0;
j = 0;
k = L;
while (i < N1 && j < N2)
{
if (strcmp(LA[i][S], RA[j][S]))
{
T[k][S] = RA[j][S];
T[k][1-S] = RA[j][1-S];
j++;
}
else
{
T[k][S] = LA[i][S];
T[k][1-S] = LA[i][1-S];
i++;
}
k++;
}
}
void mergeSort(char** T, int L, int H, SortType S){
if(L < H)
return;
int M = (L + H) / 2;
mergeSort(T, L, M, S);
mergeSort(T, M+1, H, S);
merge(T, L, M, H, S);
}
Please dont mark my question as duplicate because I dont understand the solutions explained in the site and can't solve my problem.

Merge sort of characters in string C

I have this working merge-sort algorithm in C. But it works only for integers. When I tried to change int to char, i'm getting segfault.
Can you please help me, what should I change in this code, so I could use MergeSort like this:
char*str = "test_string";
MergeSort(str, 0, strlen(str)-1);
void Merge(int *array, int left, int mid, int right){
int tempArray[right-left+1];
int pos=0,lpos = left,rpos = mid + 1;
while(lpos <= mid && rpos <= right){
if(array[lpos] <= array[rpos]){
tempArray[pos++] = array[lpos++];
}
else{
tempArray[pos++] = array[rpos++];
}
}
while(lpos <= mid) tempArray[pos++] = array[lpos++];
while(rpos <= right)tempArray[pos++] = array[rpos++];
int iter;
for(iter = 0;iter < pos; iter++){
array[iter+left] = tempArray[iter];
}
return;
}
void MergeSort(int *array, int left, int right){
int mid = (left+right)/2;
if(left<right){
MergeSort(array,left,mid);
MergeSort(array,mid+1,right);
Merge(array,left,mid,right);
}
return;
}
I'm lost. Thanks!
Change your declaration of array from int * to char * in both functions. Make tempArray a char[] instead of an int[]. You are trying to read memory that is 4x (or 8x) out of bounds at the end of the array, hence the seg-fault. Put another way, char is 1 byte (usually) while int is 4 or 8, so you are looking at items of a different size stacked next to each other. Also, do not pass in a const * for your string. Declaring a string as char*str = "test_string"; implies read-only memory on some systems. Use char str[] = "test_string"; instead. If you are not using strictly C, you can use C++ templates to make a function that works for int and char: http://www.codeproject.com/Articles/257589/An-Idiots-Guide-to-Cplusplus-Templates-Part-1
#include <stdio.h>
#include<ctype.h>
#include<string.h>
int Run_count=-1;
int main ( int argc , char *argv[] )
{
/* if you dont want to use argv, put the elements in A yourself,
size being the number of string*/
/*L --> left side, R --> right side*/
int i = 0;
int size = argc-1;
char *A[argc-1];
for(i=1;i<=argc;i++){*(A+i-1) = argv[i];}
Caller(A,size);
for(i=0;i<size;i++){
printf("%s\n", A[i]);
}
printf("%d",Run_count);
}
int Caller(char* A[] , int n){
Run_count++;
int sizeL, sizeR ,i;
char *L[n/2+1] , *R[n-n/2+1];
if (n < 2){return 1;}
sizeL = n/2;
sizeR = n - sizeL;
for(i=0;i<sizeL;i++) {L[i] = *(A+i);}
for(i=0;i<n - n/2;i++) {R[i] = *(A+i+n/2);}
Caller( L, sizeL);
Caller( R, sizeR);
merger( L,sizeL, R,sizeR, A);
}
void merger(char* L[], int lengthL , char* R[] , int lengthR , char *A[]){
int i, j, k ,t =0 ;
for(k = 0 , j = 0; k < lengthL && j < lengthR ;t++){
if(compare(*(L+k),*(R+j))){
*(A+t) = *(L+k);
k++;}
else{*(A+t) = *(R+j);j++;}
}
while(k < lengthL ){
*(A+t) = *(L+k);
k++;t++;
}
while(j < lengthR ){
*(A+t) = *(R+j);
j++;t++;}
}
int compare(char *line1 , char *line2 )
{
int i;
for(i = 0;*(line1 + i) != '\0' && *(line2 + i) != '\0' ;){
if(isdigit(*(line1+i)) && isalpha(*(line2+i))){return 0;}
else if(isdigit(*(line2+i)) && isalpha(*(line1+i))){return 1;}
else if(*(line1 + i) > *(line2 + i)){return 0;}
else if(*(line1 + i) == *(line2 + i)){i++;}
else{return 1;}
}
}

K&R valid input for arrays & pointers in the swap function

I'm having trouble with the things I am and am not allowed to do with arrays and pointers in the following code:
#include <stdio.h>
#define MAX 1000
void swap (char *v[], int i, int j);
main() {
int i = 1, j = 2;
int count;
char *a = "Bill ", *b = "went ", *c = "to the ", *d = "grocery store.";
char *v[MAX];
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
printf("String before swapping elements at index %d and %d: \n",i,j);
for(count = 0; count < 4; ++count)
printf("%s",v[count]);
printf("\n");
swap(v,i,j);
printf("String after swapping elements at index %d and %d: \n",i,j);
for(count = 0; count < 4; ++count)
printf("%s",v[count]);
printf("\n");
system("Pause");
return 0;
}
void swap (char *v[], int i, int j)
{
char *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
Two things come to mind:
Why can't I write v[] = {a,b,c,d} after declaring *v[MAX]? In fact, I did a quick test and even this isn't allowed:
char v[MAX];
v[] = {'w','o','r','d','s'};
whereas char v[] = {'w','o','r','d','s'}; is accepted. Why is that?
Second thing, how can I re-write the for loop without having to use a magic number (in this case 4)? I tried using strlen in various ways but I got an error each time. The best I could come up with is a somewhat clumsy solution of declaring char *k; and changing the loop condition to
for(count = 0, k = v; *(k-1); ++count, ++k)
printf("%s",v[count]);
Surely there must be a more elegant way to loop through the v array?
how can I re-write the for loop without having to use a magic number
(in this case 4)?
One way of doing this, is to add a special terminator value ( usually NULL) in the array that you are iterating, e.g.
char *v[] = { a, b, c, d, NULL };
for(count = 0; v[count] != NULL; ++count)
printf("%s",v[count]);
char *v[] = { a, b, c, d};
int size = sizeof(v)/sizeof(*v);//4

Bubble Sort Trouble

gcc compiles the following code without error. I'm creating a bubble sort function that can be used with arrays of any data type (hence the function pointer).
It sorts the array of character strings (arr2) without a problem, however, I can't figure out why it won't properly sort the array of integers (arr). I added a printf statement in the compare_long function to see what is going on. It doesn't look like the integers are being passed to it properly. Any help will be greatly appreciated.
#include <stdio.h>
#include <string.h>
#define MAX_BUF 256
long arr[10] = { 3,6,1,2,3,8,4,1,7,2};
char arr2[5][20] = { "Mickey Mouse",
"Donald Duck",
"Minnie Mouse",
"Goofy",
"Pluto" };
void bubble(void *p, int width, int N, int(*fptr)(const void *, const void *));
int compare_string(const void *m, const void *n);
int compare_long(const void *m, const void *n);
int main(void) {
int i;
puts("\nBefore Sorting:\n");
for(i = 0; i < 10; i++) { /* show the long ints */
printf("%ld ",arr[i]);
}
puts("\n");
for(i = 0; i < 5; i++) { /* show the strings */
printf("%s\n", arr2[i]);
}
bubble(arr, 4, 10, compare_long); /* sort the longs */
bubble(arr2, 20, 5, compare_string); /* sort the strings */
puts("\n\nAfter Sorting:\n");
for(i = 0; i < 10; i++) { /* show the sorted longs */
printf("%d ",arr[i]);
}
puts("\n");
for(i = 0; i < 5; i++) { /* show the sorted strings */
printf("%s\n", arr2[i]);
}
return 0;
}
void bubble(void *p, int width, int N, int(*fptr)(const void *, const void *)) {
int i, j, k;
unsigned char buf[MAX_BUF];
unsigned char *bp = p;
for(i = N - 1; i >= 0; i--) {
for(j = 1; j <= i; j++) {
k = fptr((void *)(bp + width*(j-1)), (void *)(bp + j*width));
if(k > 0) {
memcpy(buf, bp + width*(j-1), width);
memcpy(bp + width*(j-1), bp + j*width , width);
memcpy(bp + j*width, buf, width);
}
}
}
}
int compare_string(const void *m, const void *n) {
char *m1 = (char *)m;
char *n1 = (char *)n;
return (strcmp(m1,n1));
}
int compare_long(const void *m, const void *n) {
long *m1, *n1;
m1 = (long *)m;
n1 = (long *)n;
printf("m1 = %l and n1 = %l\n", *m1, *n1);
return (*m1 > *n1);
}
The ANSI C spec defines long as a MINIMUM of 4 bytes (32 bits) but GCC is defining long as 8 bytes in your case. It is architecture-specific so you need to use sizeof(long) or one of the C99 types like uint32_t or int32_t if you want a specific size.

Resources