sorting strings while using malloc - c

how can i sort the string without breaking the program? the string input had to be done without the use of gets(fgets , getsc etc.)
int main ()
{
char **pointsarr;
char temp;
printf("insert strings: \n");
scanf("%d",&a);
printf("declare the size of the strings: \n");
pointsarr = malloc(a * sizeof(char*));
for (i=0; i<a; i++)
{
pointsarr[i]= malloc(b* sizeof(char));
}
printf("input strings: \n");
for (i=0; i<a; i++)
{
scanf("%s", pointsarr[i]);
}
printf("the strings on the 2d board: \n");
for (int i=0; i<a; i++)
printf("%s\n",pointsarr[i]);
/* int n= strlen(pointsarr);
for (i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
if (pointsarr[i]>pointsarr[j])
{
temp=pointsarr[i];
temp=pointsarr[i]; // whats going wrong on this point?
pointsarr[i]=pointsarr[j];
pointsarr[j]=temp;
}
}
}
*/
free(pointsarr);
}
in this if whats going wrong and it dosent return the sorted string?

The easiest way to sort your array is to use the library function qsort().
Sample code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int comparefunc (const void* p1, const void* p2)
{
return strcmp (* (const char **) p1, * (const char **) p2);
}
int main ()
{
int i, a = 4, b = 20;
char **pointsarr = (char **) malloc(a * sizeof(char*));
for (i=0; i<a; i++)
pointsarr[i]= (char *) malloc(b* sizeof(char));
strcpy (pointsarr [0], "qwerty");
strcpy (pointsarr [1], "uiop");
strcpy (pointsarr [2], "asdf");
strcpy (pointsarr [3], "ghjkl");
for (i=0; i<a; i++)
printf("%s\n",pointsarr[i]);
printf("-----\n");
qsort (pointsarr, a, sizeof (char **), comparefunc);
for (i=0; i<a; i++)
printf("%s\n",pointsarr[i]);
}
Output:
qwerty
uiop
asdf
ghjkl
-----
asdf
ghjkl
qwerty
uiop
Live demo

Problem 1: the line int n= strlen(pointsarr); is certainly wrong, as pointsarray is a pointer to an array of strings, not a pointer to a string.
It is also unnecessary, as you already have the length of the array: it's a.
Problem 2: see the comment by #xing

Related

Creating a 1-D array of strings from user input in C

I was attempting to create an array from user input in C. My code was as follows
#include <stdio.h>
#include <stdlib.h>
char** create_array(int num);
int main(){
char** my_array;
int i;
printf("%s", "Input the size of the array: ");
scanf("%d", &i);
my_array = create_array(i);
for (int m = 0; m < i; m++){
printf("%s\n", (char*)my_array[m]);
}
}
char ** create_array(int num){
char** array = malloc(num * sizeof(char*));
for (int i = 0; i < num; i++) {
char temp[32];
printf("Input element %d of the array: ", i);
scanf("%s", temp);
array[i] = temp;
}
for (int m = 0; m < num; m++){
printf("%s\n", array[m]);
}
printf("end of func\n");
return array;
}
I was having (possibly unrelated?) issues with segmentation faults until I replaced the declaration of temp from char *temp; to char temp[32];. I am not sure of why declaring temp as a char pointer creates the segmentation fault, if that is a simple related answer let me know, if not I will ask in another question.
However, when I run this code, upon inputting
Input the size of the array: 2
Input element 0 of the array: value0
Input element 1 of the array: value1
I get
value1
value1
end of func
Segmentation fault (core dumped)
So to me it seems like temp somehow isn't changing when the for loop executes next iteration. I'm not sure why or how that would ever happen though. I also tried changing
printf("%s\n", my_array[m]);
to
printf("%s\n", (char*)my_array[m]);
but that didn't seem to help either.
Any ideas?
Thanks
I believe this is what you're looking for. The trick is allocate the memory for the strings on the heap. Saving pointers to char temp[32]; is dangerous because it's in automatic storage. As #Spikatrix said in a comment, that memory is not guaranteed to be in a valid state between each iteration of the loop. With the data on the heap, there's a well-defined region of memory set aside and identified by the pointer returned from malloc.
There's also a lot of good reason to not use scanf. As is, your code does not do any bounds checks and can easily overwrite the 32-byte array allocated for each string.
#include <stdio.h>
#include <stdlib.h>
char** create_array(int num);
int main(){
int num_strings;
printf("Input the size of the array: ");
scanf("%d", &num_strings);
printf("\n");
char** my_array = create_array(num_strings);
for (int i = 0; i < num_strings; i++){
printf("%s\n", my_array[i]);
}
for (int i = 0; i < num_strings; i++) {
free(my_array[i]);
}
free(my_array);
}
char** create_array(int num) {
char** array = malloc(num * sizeof(char*));
for (int i = 0; i < num; i++) {
array[i] = malloc(32);
printf("Input element %d of the array: ", i);
scanf("%s", array[i]);
printf("\n");
}
printf("end of func\n");
return array;
}

free() the reserved data with malloc

Hi I have written this Program which create a list of books which is given by the User and i can't free the my_value at the end of program and get a lot of errors . This is my Code
#include <stdio.h>
#include <stdlib.h>
int main(){
int n;
printf("Please Enter the Number of Books:\n");
scanf("%d",&n);
char **array=(char *) malloc((n+1)*sizeof(char *));
for(int i=0;i<n;i++){
array[i] = (char *)malloc(sizeof(char *));
}
for(int i=0;i<n;i++){
char *my_value=(char *) malloc(sizeof(char)*100);
printf("Please Enter the Name of the %dth Book:\n",i+1);
scanf("%s",my_value);
*(array+i)=my_value;
free(my_value);
}
for(int i=0;i<n;i++){
printf("\n The Book Nr.%d is %s \n",i+1,*(array+i));
}
for(int i=0;i<n;i++){
free(array[i]);
}
free(array);
return 0 ;
}
First, in
char **array=(char *) malloc((n+1)*sizeof(char *));
you don't need n+1 pointers since you use only n.
Then, this loop
for(int i=0;i<n;i++){
array[i] = (char *)malloc(sizeof(char *));
}
is unnecessary (and wrong). array[i] is to be overwritten just after.
In the next loop
*(array+i)=my_value; // is array[i] = my_value
free(my_value); // <=== why? remove that line!
you free what you just allocated -- array[i] cannot be used anymore from that point! Lead to undefined behavior.

Why doesn't qsort() work when I use it to sort an array of strings?

I'm trying to sort this list of strings: ["a", "z", "b"]. So the answer should be ["a", "b", "z"]. However, when I try to use C's qsort(), nothing moves! What am I doing wrong?
MWE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int sortcmpfunc (const void *a, const void *b)
{ return strcmp((const char*)a, (const char*)b); }
int main(){
const char** list = (const char**)malloc(50*sizeof(const char*));
for(int i = 0; i < 50; i++){
list[i] = (char*)malloc(50*sizeof(char));
}
list[0] ="a";
list[1] = "z";
list[2] = "b";
for (int i=0; i<3; i++){ printf("%s ", list[i]); } printf("\n");
qsort(list, 3, sizeof(const char*), sortcmpfunc);
for (int i=0; i<3; i++){ printf("%s ", list[i]); } printf("\n");
return 0;
}
Output with gcc test-qsort.c && ./a.out:
a z b
a z b
Simply
strcmp(*(char **) a, *(char **) b);
note that a pointer to each element is passed to the comparison function, hence you need to cast to the correct type and dereference.
And please avoid
for (int i=0; i<3; i++){ printf("%s\n", list[i]); }
and instead write
for (int i = 0; i < 3; i++) {
printf("%s\n", list[i]);
}
it's horrible
And also use
gcc -Wall -Werror test-qsort.c && ./a.out

A wordsearch c program assignment

EDIT: My new question is how can i put words in a random location on the grid, ive tried like below but just get a single random letter in the same spot. And also have i done the functions correctly as i feel that that may be the issue.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
char **createArray(); //function prototype
void printArray(char** array);
void insertHorizontally(char*word, char** array);
#define WIDTH 16
#define HEIGHT 16
char** myArray; //global array
void main()
{
char words[4] = {'f','r','e','e'};
myArray = createArray();
insertHorizontally(words,myArray);
printArray(myArray);
}
//Creates a 2D array of WIDTH * HEIGHT and returns a pointer to it
char **createArray()
{
int i,j;
char **array = (char **) malloc(sizeof(char *) * WIDTH);
for(i=0; i<WIDTH; i++)
{
array[i] = (char *) malloc(sizeof(char) * HEIGHT);
}
for(i=0; i<WIDTH; i++)
{
for(j=0; j<HEIGHT; j++)
{
//words[i][j] = 65 + rand() % 25;
array[i][j] = '_';
}
}
return array;
}
void printArray(char** array)
{
int i,j;
array =myArray;
for(i=0; i<WIDTH; i++)
{
for(j=0; j<HEIGHT; j++)
{
printf(" %c ", array[i][j]);
}
printf("\n");
}
}
void insertHorizontally(char*word, char** array)
{
array=&myArray;
array=&rand();
word = (char *) malloc(sizeof(char) * HEIGHT);
int i,j,a;
for(j = 0; j<HEIGHT; j++)
{
for(a=0;a<sizeof(word);a++)
{
array[i][j] = *word;
}
}
}
array=&myArray;//overwrite
array=&rand();//overwrite?, `&rand()` invalid
word = (char *) malloc(sizeof(char) * HEIGHT);//overwrite
sizeof(word)//pointer size, change to `char words[] = "free";...strlen(word)
write in a horizontal direction at random positions:
void insertHorizontally(char*word, char** array)
{
int word_len = 4;
int i = rand() % (HEIGHT-word_len+1);
int j = rand() % WIDTH;
int k;
for(k=0;k < word_len;k++) {
array[j][i+k] = word[k];
}
}

functions with malloc syntax error?

I am new to working with pointers and I have no idea why this does not work. If I print inside the scan function it works, but it has to be in a separate function.
#include <stdio.h>
#include <stdlib.h>
int scan(int n, int *buffer)
{
int i;
printf("nr of elements:\n");
scanf("%d", &n);
//int *buffer, i=0;
// *buffer=(int*)malloc((*n) * sizeof(int));
buffer = malloc((n + 1) * sizeof(*buffer));
for(i=0; i<n; i++){
buffer[i]=i+1;
printf ("%d ", buffer[i]);}
printf ("\n-------------\n");
}
void print(int *n,int *buffer){
int i;
for(i=0; i<n; i++){
printf ("%d ", buffer[i]);}
}
int main()
{
int n,i, *buffer;
scan(&n, &buffer);
print(n, *buffer);
printf("i quit\n");
for(i=0; i<n; i++){
printf ("%d ", buffer[i]);
}
return 0;
}
It can help to use (slightly) more descriptive variable names to make it abundantly clear that 'n' in scan is not the same as 'n' in print:
#include <stdio.h>
#include <stdlib.h>
void scan(int *np, int **bufferp)
{
int i;
printf("nr of elements:\n");
scanf("%d", np);
*bufferp = (int*)malloc(*np * sizeof(**bufferp));
for(i=0; i < *np; i++){
(*bufferp)[i] = i + 1;
printf ("%d ", (*bufferp)[i]);
}
printf ("\n-------------\n");
}
void print(int n, int *buffer){
int i;
for(i=0; i<n; i++){
printf ("%d ", buffer[i]);
}
printf("\n");
}
int main()
{
int n, i, *buffer;
/* pass references to n and buffer for scan to modify */
scan(&n, &buffer);
print(n, buffer);
return 0;
}
There are two ways of changing parameters of function (change data outside function):
1) use references (in my example - the first argument of scan function)
2) use pointers (in my example - the second argument of scan... THIS ARGUMENT IS OF TYPE int*)
Try this (my comments show the changes):
#include <stdio.h>
#include <stdlib.h>
void scan(int &n, int ** buffer) // pointer to pointer for bufer, void instead of int for function, and &int for n
{
int i;
printf("nr of elements:\n");
scanf("%d", &n);
*buffer = (int*) malloc( n * sizeof(**buffer)); // (int*) should be, and *buffer
for(i=0; i<n; i++){
(*buffer)[i]=i+1; // *buffer
printf ("%d ", (*buffer)[i]); // *buffer
}
printf ("\n-------------\n");
}
void print(int n, int *buffer) // type of n changed from int* to int
{
int i;
for(i=0; i<n; i++){
printf ("%d ", buffer[i]);
}
}
int main()
{
int n,i, *buffer = NULL;
scan(n, &buffer);
print(n, buffer); // buffer is pointer, no need to use *
printf("i quit\n");
for(i=0; i<n; i++){
printf ("%d ", buffer[i]);
}
return 0;
}
Note: if you whant to change data you can use
void changeArgument(int * data)
{
(*data)++;
}
but to change addres of data, you should use
void changeArgument(int ** pointer)
{
(*pointer) = (int*)malloc(sizeof(int));
}
Either declare the scan() with void return type and display the data their itself.
OR if you want the function to return int then instead of printing it in the function return the value and display it in main(). It should work fine then.

Resources