I need help with the following program:
Print all sorted strings from the input array of strings.
Assume that strings are sorted if characters are in lexicographic order (also assume that the only characters in strings are letters).
Example:
INPUT:
n=2
1. string: stack
2. string: exchange
OUTPUT:
No sorted strings
I am having a problem with accessing some variables in the following program:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 30
char** read(int *pn);
int isSorted(char *str);
char** sortedArr(char **str,int pn);
char** read(int *pn)
{
do
{
printf("n = ");
scanf("%d",pn);
}
while(*pn < 1);
char **arr;
arr=(char **)malloc(*pn * sizeof(char *));
int i;
for(i=0; i<*pn;i++)
arr[i]=(char *)malloc(MAX+1);
for(i=0; i<*pn; i++)
{
printf("%d. word: ",i+1);
scanf("%s",arr[i]);
}
return arr;
}
int isSorted(char *str)
{
int i,j;
for(i=0; i<strlen(str)-1;i++)
for(j=i+1; j<strlen(str); j++)
if(strcmp(str+i,str+j) > 0)
return 1;
return 0;
}
char** sortedArr(char **str,int pn)
{
char **sortArr;
sortArr=(char **)malloc(pn * sizeof(char *));
int i;
for(i=0; i<pn; i++)
{
if(isSorted(sortArr[i]))
sortArr[i]=(char *)malloc(MAX+1);
}
for(i=0; i<pn; i++)
{
if(isSorted(sortArr[i]))
printf("%d. word: %s",sortArr+i);
}
return sortArr;
}
int main()
{
char **arr;
char **sortArr;
int pn;
arr=read(&pn);
sortArr=sortedArr(arr,pn);
int i;
for(i=0; i<pn; i++)
free(arr[i]);
free(arr);
return 0;
}
The problem is how to access the variable pn in function sortedArr()?
Your program has several issues, I'll try to address the most part of them.
Let's start from the isSorted function, if your goal is to check if a word has all the character sorted, you don't need to use strcmp or a nested loop. All what you need is something like this:
// check if all the character in the string are sorted
int isSorted( char *str )
{
int i, length = strlen(str) - 1;
for ( i=0; i < length; i++ )
if ( str[i] > str[i+1] )
return 0;
return 1;
}
I'll separate the printing function from the input one and copy ones, so to have:
void print( char **str, int n )
{
int i;
for ( i = 0; i < n; i++ ) {
printf("word %d: %s\n", i + 1, str[i]);
}
}
There are several methods to read some words from stdin and some are presented in other answers. I'll use this, but you should check all the pointers returned from malloc:
char** read(int *pn)
{
char buffer[BUFSIZE];
printf("Please, enter number of words: ");
while ( *pn < 1 && fgets(buffer, BUFSIZE, stdin) ) {
sscanf(buffer, "%d", pn);
}
int i = 0, length;
printf("\nPlease, enter the words: \n");
char **arr = malloc(*pn * sizeof(char *));
while ( i < *pn ) {
// read words one line at a time
if ( !fgets(buffer, BUFSIZE, stdin) )
break;
length = strlen(buffer);
// ignore empty lines
if ( length < 2 )
continue;
arr[i] = malloc(length);
memcpy(arr[i],buffer,length);
// add the null terminator
arr[i][length - 1] = '\0';
++i;
}
*pn = i;
return arr;
}
Then, I'm not really sure if you want only to print the words that are "sorted" or you actually need to copy them (and print later). I'll show you the latter:
// return an array of string containing only the sorted ones
char** sortedArr( char **str, int n, int *m)
{
char **sortArr = NULL;
char *sorted = calloc(n,1);
int i;
*m = 0;
// first find (and count) the sorted strings
for ( i = 0; i < n; i++ ) {
if ( isSorted(str[i]) ) {
// maybe you need only to print str[i] now...
sorted[i] = 1;
++(*m);
}
}
// then copy the sorted. I'm not sure if you need this
int j = 0, length = 0;
if ( *m ) {
sortArr = malloc(*m * sizeof(char *));
for ( i = 0; i < n; i++ ) {
if ( !sorted[i] )
continue;
length = strlen(str[i]) + 1;
sortArr[j] = malloc(length);
memcpy(sortArr[j],str[i],length);
}
}
free(sorted);
return sortArr;
}
Finally the main function (and the one to free allocated memory):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BUFSIZE 128
char** read( int *pn );
int isSorted( char *str );
char** sortedArr( char **str, int n, int *m );
void print( char **str, int n );
void freeArr( char **str, int n );
void freeArr( char **str, int n )
{
if ( !str ) return;
int i;
for ( i = 0; i < n; i++ ) {
free(str[i]);
}
free(str);
}
int main()
{
char **arr = NULL;
char **sortArr = NULL;
int n = 0, m = 0;
arr = read(&n);
print(arr, n);
printf("\nSorted: \n");
sortArr = sortedArr(arr,n,&m);
print(sortArr, m);
freeArr(sortArr, m);
freeArr(arr, n);
return 0;
}
Hope it helped. Tell me if there is something wrong or I have misunderstood your task.
Change the sortedArr function, so that it takes pn as an argument:
char** sortedArr(char **str, int pn)...
Then, in your main(), change the sortArr=sortedArr(arr) to sortArr=sortedArr(arr, pn), to pass the value to the function. Then you can use the pn value inside the sortedArr function.
One head-scratcher is:
for(i=0; i<*pn;i++)
arr[i]=(char *)malloc(strlen(arr+i)+1);
for(i=0; i<*pn; i++)
{
printf("%d. word: ",i+1);
scanf("%s",arr[i]);
}
You should combine both because you cannot allocate properly until you know the length of word. Allocating some strlen(arr+i)+1 for who knows what is at arr+i is meaningless (and unless arr+i just happens to be a nul-terminated string, undefined behavior). When you are taking input, you can/should use a temprory buffer to hold the input until you can validate it is what you want it to be. At minimum, test the return to scanf to insure you actually had a sucessful conversion to the type of input you are expecting. For instance:
for (i = 0; i < *pn; i++)
{
char buf[64] = ""; /* however long is sufficient for word */
printf ("%d. word: ",i+1);
if (scanf ("%63[^\n']%*c",buf) == 1)
arr[i] = strdup (buf); /* allocates/copies buf for arr[i] */
else {
fprintf (stderr, "error: invalid input for word[%d].\n", i);
}
}
(note: you have similar allocation issues in sortedArr)
For your sort, you need to pass pn as a parameter to sortedArr so you at least know how many strings you are dealing with. Rather than looping and attempting to compare adjacent elements, why not have your sortedArr function simply call qsort and sort the array you create in read. If you want to preserve both the original and sorted arrays, then have sortedArr call memcpy and create a copy of arr and then call qsort on the copy. All you need to do is create a string comparison compare function for qsort to compare arr or the copy, e.g.:
/* comparison function for qsort (char **) */
int cmp_str (const void *a, const void *b)
{
/* The actual arguments to this function are "pointers to
pointers to char", but strcmp(3) arguments are "pointers
to char", hence the following cast plus dereference
note: to reverse sort order, swap a and b, below */
return strcmp (* (char * const *) a, * (char * const *) b);
}
Which you can then use to sort your arr (or copy) with
qsort (arr, pn, sizeof *arr, cmp_str);
Much less error-prone then a one-off loop and index attempt. Give it a try and let me know if you have questions.
Related
I managed to sort it alphabetically but I need to sort it by the most frequent characters first after that. Since I'm new to C programming Im not sure if this alphabetical sort is needed. Also I thought about using a struct but not sure how to do the whole process with it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmpfunc(const void *a, const void *b) {
return *(char*)a - *(char*)b;
}
void AlphabetOrder(char str[]) {
qsort(str, (size_t) strlen(str), (size_t) sizeof(char), cmpfunc);
printf("%s\n", str);
}
void Max_Occurring(char *str)
{
int i;
int max = 0;
int freq[256] = {0};
for(i = 0; str[i] != '\0'; i++)
{
freq[str[i]] = freq[str[i]] + 1;
}
for(i = 0; i < 256; i++)
{
if(freq[i] > freq[max])
{
max = i;
}
}
printf("Character '%c' appears %d times", max, freq[max], str);
}
int main() {
char str1[20];
printf("Enter a string: ");
scanf("%s", &str1);
AlphabetOrder(str1);
Max_Occurring(str1);
return 0;
}
I wrote you a frequency sorter using the idea that #WeatherVane mentioned:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct cfreq {
unsigned char c;
int freq;
};
int freqcmp(const void *a, const void *b) {
struct cfreq *a2 = (struct cfreq *) a;
struct cfreq *b2 = (struct cfreq *) b;
if(a2->freq < b2->freq) return -1;
if(a2->freq == b2->freq) return 0;
return 1;
}
int freqcmpdesc(const void *a, const void *b) {
return -freqcmp(a, b);
}
void FrequencyOrder(const char str[]) {
struct cfreq cfreqs[256];
for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
cfreqs[i].c = i;
cfreqs[i].freq = 0;
}
for(int i = 0; str[i]; i++) cfreqs[str[i]].freq++;
qsort(cfreqs, sizeof(cfreqs) / sizeof(*cfreqs), sizeof(*cfreqs), freqcmpdesc);
for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
if(cfreqs[i].freq) printf("%c", cfreqs[i].c);
}
printf("\n");
}
int main() {
char str1[20];
printf("Enter a string: ");
scanf("%s", &str1);
FrequencyOrder(str1);
return 0;
}
and here is a sample session (note: output is not deterministic for letters with same frequency):
Enter a string: buzz
zbu
If you want duplicate letters in the output then replace the print with a loop along these lines:
while(cfreqs[i].freq--) printf("%c", cfreqs[i].c);
Im not sure if this alphabetical sort is needed.
It is not needed, yet if done, Max_Occurring() can take advantage of a sorted string.
Since the string is sorted before calling Max_Occurring(), compute the max occurring via a count of adjacent repetitions of each char.
// Untested illustrative code.
// str points to a sorted string.
void Max_Occurring(const char *str) {
char max_ch = '\0';
size_t max_occurence = 0;
char previous = '\0';
size_t occurrence = 0;
while (*str) {
if (*str == previous) {
occurrence++;
} else {
occurrence = 1;
}
if (occurrence > max_occurence) {
max_occurence = occurrence;
max_ch = *str;
}
previous = *str;
str++;
}
printf("Character '%c' appears %zu times", max_ch, max_occurence);
}
In the case of multiple characters with the same max occurrence, this code only reports one max.
Avoid buffer overflow
Do not use scanf("%s"... without a width limit.
Tip: enable all warnings to save time and see the problem of using &str1 when str1 should be used.
char str1[20];
...
// scanf("%s", &str1);
scanf("%19s", str1);
Avoid a negative index
If still wanting to for a frequency table, watch out for the case when char is signed and code use str[i] < 0 to index an array.
Instead:
const unsigned char *ustr = (const unsigned char *) str;
size_t freq[UCHAR_MAX + 1] = {0};
for(size_t i = 0; ustr[i] != '\0'; i++) {
freq[ustr[i]]++;
}
Here's another alternative that may be simpler.
void freqOrder( char *p ) {
#define ASCIIcnt 128 // 7bit ASCII
// to count occurences of each character
int occur[ ASCIIcnt ];
memset( occur, 0, sizeof occur );
int maxCnt = 0; // remember the highest count
// do the counting
for( ; *p; p++ )
if( ++occur[ *p ] > maxCnt )
maxCnt = occur[ *p ];
// output most frequent to least frequen
for( ; maxCnt; maxCnt-- )
for( int i = 0; i < ASCIIcnt; i++ )
if( occur[i] == maxCnt )
while( occur[i]-- )
putchar( i );
putchar( '\n' );
}
int main( void ) {
freqOrder( "The quick brown fox jumps over the lazy dog" );
return 0;
}
Output
' ooooeeehhrruuTabcdfgijklmnpqstvwxyz'
This code scans number then he create array with malloc, then i scan strings, i put then inside the array with another malloc, then i sort the strings and print them. I build this code with mallocs and i put array inside array,i have leaks in this code, where i need to put free() function and how i put free()? I tried many times to solve this leaks but its not working.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sort(char** names, int length);
void print_array(char** names, int length);
int main()
{
int num_of_friends = 0;
int i = 0;
char name[50] = { 0 };
char** names = NULL;
printf("Enter number of friends: ");
scanf("%d", &num_of_friends);
getchar();
names = malloc(sizeof(char) * num_of_friends);
for ( i = 0; i < num_of_friends; i++)
{
printf("Enter name of friend %d: ", i + 1);
fgets(name, 50, stdin);
name[strcspn(name, "\n")] = 0;
names[i] = malloc(sizeof(char) * strlen(name));
strcpy(names[i], name);
}
sort(names, num_of_friends);
print_array(names, num_of_friends);
getchar();
return 0;
}
void sort(char** names, int length)
{
char temp[50] = { 0 };
int i = 0;
int j_min = 0;
int j = 0;
for ( i = 0; i < length - 1; i++)
{
j_min = i;
for ( j = i+1; j < length; j++)
{
if (strcmp(names[j], names[j_min]) < 0)
{
j_min = j;
}
}
if (j_min != i)
{
strcpy(temp, names[i]);
strcpy(names[i], names[j_min]);
strcpy(names[j_min], temp);
}
}
}
void print_array(char** names, int length)
{
int i = 0;
for (i = 0; i < length; i++)
{
printf("Friend %d: %s \n", i + 1, names[i]);
}
}
For names, you are allocating sizeof (char) times the user provided number of bytes. This is needs to be sizeof (char *), giving you enough room for each pointer value.
names = malloc(sizeof (char *) * num_of_friends);
You need to allocate one additional byte for the null terminating character ('\0'). sizeof (char) is guaranteed to be 1, making that statement redundant.
names[i] = malloc(strlen(name) + 1);
Before the end of main, you need to free each element of names, and then names itself.
sort(names, num_of_friends);
print_array(names, num_of_friends);
getchar();
for (i = 0; i < num_of_friends; i++)
free(names[i]);
free(names);
return 0;
Your sort function may attempt to copy strings between buffers of differing size. You need to swap pointers instead.
Example:
void swap(char **a, char **b) {
char *c = *a;
*a = *b;
*b = c;
}
void sort(char **names, size_t length) {
for (size_t i = 0; i < length - 1; i++)
for (size_t j = i + 1; j < length; j++)
if (strcmp(names[i], names[j]) > 0)
swap(names + i, names + j);
}
I just have a function here in C language, Can you please tell me what does str[ ][20] meaning and why do we need it
void printlist(char str[][20], int n) {
int i;
printf("\t*******************************\n");
printf("\tNo.\t\t\tName");
printf("\n\t*****************************\n");
for (i = 0; i < n; i++) {
printf("\t%d \t\t\t%s\n", i + 1, str[i]);
}
}
Thanks in advance
char str[][20], means that you have an unknown number of char arrays of size 20.
The parameter n to the function printlist specifies, how many rows there are in the specified array str.
Example:
int main()
{
char str[][20] = { "Hello", "World" };
printlist(str, sizeof str / 20); // <-- printlist(str, 2);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
void print(int **array,int row,int col){
int i,j;
for(i=0;i<row;++i){
for(j=0;j<col;++j){
printf("%d ",array[i][j]);
}
printf("\n");
}
}
int **take(int *row,int *col){
int i; int **array;
printf("Enter the row number for array \n");
scanf("%d",row);
printf("Enter the column number for the array \n");
scanf("%d",col);
array=(int**)malloc(sizeof(int*)*(*row));
for(i=0;i<(*row);++i){
array[i]=(int*)malloc(sizeof(int)*(*col));
}
return array;
}
void assign(int **array,int row,int col){
int i,j;
srand(time(NULL));
for(i=0;i<row;++i){
for(j=0;j<col;++j){
array[i][j]=rand()%50;
}
}
}
int **increase(int **array,int *row,int *col){
int **temp;int trow=*row;int tcol=*col;
temp=take(row,col);
memcpy(temp,array,sizeof(int)*trow*tcol);
free(array);
return temp;
}
int main(){
int **array=NULL; int row,col;
array=take(&row,&col);
assign(array,row,col);
print(array,row,col);
array=increase(array,&row,&col);
array[2][0] = 1;
free(array);
return 0;
}
First ı am making 2 by 3 matrix and print it then increase it 3 by 4 and when trying to reach array[2][0], I am taking segmentation fault
What is the problem.I checked it many times but I could not find anything
memcpy(temp,array,sizeof(int)*trow*tcol); is wrong.
array isn't continuous int.
array is as like follows.
[int*][int*][int*]...
| |
| +-→[int][int][int]...
|
+-→[int][int][int]...
fix like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void print(int **array, int row, int col){
int i, j;
for(i = 0; i < row; ++i){
for(j = 0; j < col; ++j){
printf("%2d ", array[i][j]);
}
printf("\n");
}
}
int **take(int *row,int *col){
int **array, i;
printf("Enter the row number for array \n");
scanf("%d", row);
printf("Enter the column number for the array \n");
scanf("%d", col);
array = malloc(sizeof(int*) * (*row));
for(i = 0; i < (*row); ++i){
array[i] = calloc(*col, sizeof(int));
}
return array;
}
void assign(int **array,int row,int col){
int i,j;
srand(time(NULL));
for(i=0;i<row;++i){
for(j=0;j<col;++j){
array[i][j]=rand()%50;
}
}
}
int **increase(int **array, int *row, int *col){
int **temp, trow = *row, tcol = *col;
temp=take(row, col);
if(*row < trow || *col < tcol){
printf("Was decreased.\n");
for(int i = 0; i < *row; ++i)
free(temp[i]);
free(temp);
*row = trow; *col = tcol;
return array;//not change
}
for(int i = 0; i < trow; ++i){
memcpy(temp[i], array[i], sizeof(int) * tcol);
free(array[i]);
}
free(array);
return temp;
}
int main(void){
int **array = NULL;
int row, col;
array=take(&row, &col);
assign(array, row, col);
print(array, row, col);
array = increase(array, &row, &col);
//test: 2, 3 --> 3, 4
array[2][0] = 1;
print(array, row, col);
for(int i = 0; i < row; ++i)
free(array[i]);
free(array);
return 0;
}
Your two dimensional matrix is represented by pointers that point to one dimensional int arrays.
The array is not a contiguous two dimensional array. Using memcpy to copy the old array to the new one, in the function increase, won't work.
You will have to iterate through each pointer and then through the array the pointer is pointing to. Basically use two nested loops, just like you do when you print the arrays.
In the function increase the code doesn't free arrays the pointer array is pointing to:
free(array);
Only the arrays of pointers is freed, when it should also free each element of the array of pointers. This is obvious if you look at how the array is allocated:
array=(int**)malloc(sizeof(int*)*(*row));
for(i=0;i<(*row);++i){
array[i]=(int*)malloc(sizeof(int)*(*col));
}
Rather than memcpy, realloc could be used to increase the size of array. Check the return of realloc and malloc as they can fail.
The return of scanf should also be checked as it can fail as well.
Instead of scanf, this uses fgets for input and parses the input with strtol in the get_int_range function.
Using realloc allows the take and increase functions to be combined. Since the take function now has knowledge of the old and new sizes, the operation of the assign function can also be included.
takeaway handles freeing the allocated memory.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <limits.h>
//inputs
// char *line : pointer to text to be parsed
// char **next : pointer to pointer to allow modification of caller's pointer
// char *delim : pointer to characters to be considered terminators
// int *value : pointer to int to allow modification of caller's int
// int min : minimum value of range
// int max : maximum value of range
// returns : 0 failure or 1 success
int get_int_range ( char *line, char **next, char *delim, int *value, int min, int max)
{
long int input = 0;
char *end = NULL;//will point to end of parsed value
if ( line == NULL) {
return 0;
}
errno = 0;
input = strtol ( line, &end, 10);//get the integer from the line. end will point to the end of the parsed value
if ( ( errno == ERANGE && ( input == LONG_MAX || input == LONG_MIN))
|| ( errno != 0 && input == 0)){// parsing error from strtol
perror ( "input");
return 0;
}
if ( end == line) {// nothing was parsed. no digits
line[strcspn ( line, "\n")] = '\0';//remove newline
printf ( "input [%s] MUST be a number\n", line);
return 0;// return failure
}
// *end is the character that end points to
if ( *end != '\0' && !( delim && strchr ( delim, *end))) {// is *end '\0' or is *end in the set of term characters
line[strcspn ( line, "\n")] = '\0';//remove newline
printf ( "problem with input: [%s] \n", line);
return 0;
}
if ( input < min || input > max) {// parsed value is outside of range
printf ( "input out of range %d to %d\n", min, max);
return 0;
}
if ( next != NULL) {// if next is NULL, caller did not want pointer to end of parsed value
*next = end;// *next allows modification to caller's pointer
}
if ( value == NULL) {
return 0;
}
*value = input;// *value allows modification to callers int
return 1;// success
}
void print(int **array,int row,int col){
int i,j;
for(i=0;i<row;++i){
for(j=0;j<col;++j){
printf("%d ",array[i][j]);
}
printf("\n");
}
}
int **take(int **array, int *row, int *col){
char line[256] = "";
int i;
int each = 0;
int newrow = 0;
int newcol = 0;
int valid = 0;
int **temp = 0;
int *temprow = 0;
do {
printf("Enter the row number for array \n");
fgets ( line, sizeof ( line), stdin);//read a line
valid = get_int_range ( line, NULL, "\n", &newrow, (*row) + 1, INT_MAX);// call to parse a value
} while ( !valid);
do {
printf("Enter the column number for the array \n");
fgets ( line, sizeof ( line), stdin);//read a line
valid = get_int_range ( line, NULL, "\n", &newcol, (*col) + 1, INT_MAX);// call to parse a value
} while ( !valid);
if ( ( temp = realloc ( array, sizeof( int*) * ( newrow))) == NULL) {
fprintf ( stderr, "problem reallocating\n");
return array;
}
array = temp;
for(i=0;i<(*row);++i){//realloc existing rows
if ( ( temprow = realloc ( array[i], sizeof ( int) * ( newcol))) == NULL) {
fprintf ( stderr, "problem reallocating row \n");
return array;
}
array[i] = temprow;
for ( each = *col; each < newcol; each++) {
array[i][each] = rand ( ) % 50;
}
}
for(i=(*row);i<newrow;++i){// malloc new rows
if ( ( array[i] = malloc ( sizeof ( int) * ( newcol))) == NULL) {
fprintf ( stderr, "problem allocating row \n");
return array;
}
for ( each = 0; each < newcol; each++) {
array[i][each] = rand ( ) % 50;
}
}
*row = newrow;
*col = newcol;
return array;
}
int **takeaway ( int **array, int *row, int *col) {//free allocated memory
*col = 0;
while ( *row){
*row -= 1;
free ( array[*row]);
}
free ( array);
return NULL;
}
int main(){
int **array=NULL;//so realloc will work on the first call
int row = 0;
int col = 0;
srand(time(NULL));//call srand once early in the program
array=take(array,&row,&col);
print(array,row,col);
array=take(array,&row,&col);
array[2][0] = 1;
print(array,row,col);
array = takeaway ( array, &row, &col);
return 0;
}
here is my code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define STRING_LENGTH 20
#define MAX 30
int read_string(char string[], int n);
int compare(const void*a, const void*b);
int main(){
int i;
char* word_list[30];
char word[STRING_LENGTH + 1];
for (i = 0; ; i++){
printf("\nEnter a word.\n");
read_string(word, STRING_LENGTH);
if (word[0] == '\0')
break;
word_list[i] = (char *)malloc(STRING_LENGTH + 1);
//free(word_list);
strcpy(word_list[i], word);
}
int length = sizeof(word_list)/sizeof(char*);
int j;
qsort(word,length, sizeof(char*), compare);
for (j = 0; word_list[j] != '\0'; j++)
printf("%s\n", word_list[j]);
return 0;
}
int compare(const void*element1, const void *element2){
const char *string1 = *(const char**)element1;
const char *string2 = *(const char**)element2;
return strcmp(string1,string2);
}
int read_string(char string[], int n){
int ch, i = 0;
while ((ch = getchar()) != '\n')
if (i < n)
string[i++] = ch;
string[i] = '\0';
return i;
}
My program is supposed to read in strings via the read_string function and then strcpy is used to place them as elements of an array of pointers, then the names are sorted alphabetically. It compiles and reads i my input but it crashes once it gets to qsort(). I know qsort() is causing the problem but I don't know why. Any help would be very appreciated.
There are a number of issues as pointed out in the comments. The primary being you are calling qsort with the incorrect pointer, and incorrect number of members (30) instead of the number of strings read. A correction would be:
qsort (word_list, i, sizeof (char *), compare);
While you can use a sentinel to stop the print after qsort completes, why? You already know how many strings you read in i. So simply:
for (j = 0; j < i; j++)
printf ("%s\n", word_list[j]);
As an aside, it would be useful to be able to stop input after any number of strings in read_string. Allowing for an keyboard generated EOF to signal end of input by ctrl+d (ctrl+z on windows) will work. E.g.:
while ((ch = getchar ()) != '\n' && ch != EOF)
Notice that it is word_list and not word you would like to sort.
int main() {
int i;
char* word_list[30];
char word[STRING_LENGTH + 1];
for(i = 0; ; i++) {
printf("\nEnter a word.\n");
read_string(word, STRING_LENGTH);
if(word[0] == '\0')
break;
word_list[i] = (char *)malloc(STRING_LENGTH + 1);
strcpy(word_list[i], word);
}
// call qsort with the number of items in the wordlist
qsort(word_list, i, sizeof(char*), compare);
}
int compare(const void*element1, const void *element2){
const char **string1 = (const char**)element1;
const char **string2 = (const char**)element2;
return strcmp(*string1,*string2);
}
You should also call set length to the number of items in word_list before calling qsort() not to the number of characters in a word.
For instance if you have read in two words from stdin then you call qsort() like this qsort(word_list, 2, sizeof(char*), compare);
Perhaps I also need to mention that you should free the memory allocated by malloc() when you have finished using the word list.