0

I created this program to read a string from the user and to sort it's word alphabetically, finally I tried to add a funtion for helping me running this program as much as the user wants, but never works. I used do...while, but every time the program stops before reading the string.

char *words[L];
char *word;
char sentence[100];
int i = 0, nrCuvinte = 0;
    int j, k, ok, n, lung;


for(j=0;j<L;++j)
{
    words[j] = (char*)malloc(L*sizeof(char));
}
printf("Enter any sentence you want: \n");

fgets(sentence,99,stdin);
lung = strlen(sentence);

if(sentence[lung-1] == '\n')
{
    sentence[lung-1] = '\0';
}
printf("\n");

word = strtok(sentence, " .,-;/?!");
for(j=0;j<(strlen(word)+1);j++)
{
    word[j] = tolower((unsigned char) word[j]);
}
while(word != NULL)
{
    for(j=0;j<(strlen(word)+1);j++)
    {
        word[j] = tolower((unsigned char) word[j]);
    }
    strcpy(words[i],word);
    word = strtok(NULL, " .,-;/?!");
    ++i;
    ++nrCuvinte;

}

n = nrCuvinte-1;
do{
    ok =1;
    for(k=0;k<n;++k)
    {
        if(strcmp(words[k],words[k+1])>0)
        {
            char *aux;
            aux = words[k];
            words[k] = words[k+1];
            words[k+1]= aux;
            ok = 0;
        }
    }
    --n;
}while(n>0&&(ok==0));

for(j=0;j<nrCuvinte;++j)
{
    puts(words[j]);
}
for(j=0;j<L;++j)
{
    free(words[j]);
    words[j]=0;
}
  • 2
    `sizeof(char)` is always 1 by definition, so you don't need to multiply by it. Also, without knowing what `L` is, allocating each element of `*words[L]` as also having length `L` seems weird. You might want something like `*words[MAX_WORDS]` and then allocate them as `words[j] = malloc(MAX_WORD_LENGTH + 1);` (Also, don't cast the return value of `malloc`.) – Arkku Dec 26 '18 at 22:41
  • I've run your program here and it appears to work (e.g. It parses the sentence, sorts the words, and prints the words in sorted order). What issues are you having? As a side note, your program can be cleaned up a bit. (e.g.) I would `realloc` the `words` array on a dynamic basis as the line is parsed rather than relying on a fixed allocation – Craig Estey Dec 26 '18 at 23:05
  • The first loop that converts `word` to lower case is unnecessary, since the first iteration of the `while (word != NULL)` loop will do it again. – Barmar Dec 26 '18 at 23:05
  • You say the problem is with a function that calls this function in a loop. You need to post *that* function. – Barmar Dec 26 '18 at 23:06
  • And this code isn't even inside a function definition. Show that as well. – Barmar Dec 26 '18 at 23:07
  • @Barmar To get the missing pieces, I just wrapped the code inside a `main`, added (e.g.) `#define L 1000` and added the requisite `#include` and it seemed to work for me. – Craig Estey Dec 26 '18 at 23:10
  • Is this the `main` function or is this an auxiliary function you call inside `main` in a loop? If it is the latter, you should post the contents of `main` also. If it is the former, you should put everything inside a giant loop. Notice the input portion of the code isn't inside a loop, so how could it be repeated without `goto`s? – Yuri J Dec 26 '18 at 23:10
  • @CraigEstey He said he's trying to use it in a loop. How did you add that missing piece? Anyway, we need to see how the OP did it, since he obviously did it wrong. – Barmar Dec 26 '18 at 23:14

1 Answers1

0

I added the #includes, a #define for L, wrapped everything inside a main function and placed a while(1) loop inside the main function. At the start of the while(1) loop I added nrCuvinte = 0; and i = 0; in order to reset those variables. I also added the ability to break out of the while(1) loop by typing in 'yes' when asked to do so.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define L 500

int main(){

  char user_input[4];
  char *words[L];
  char *word;
  char sentence[100];
  int i = 0, nrCuvinte = 0;
  int j, k, ok, n, lung;

  while(1){
    i = 0;
    nrCuvinte = 0;
    for(j=0;j<L;++j){
      words[j] = (char*)malloc(L*sizeof(char));
    }
    printf("Enter any sentence you want: \n");

    fgets(sentence,99,stdin);
    lung = strlen(sentence);

    if(sentence[lung-1] == '\n'){
      sentence[lung-1] = '\0';
    }
    printf("\n");

    word = strtok(sentence, " .,-;/?!");
    for(j=0;j<(strlen(word)+1);j++){
      word[j] = tolower((unsigned char) word[j]);
    }
    while(word != NULL)
    {
      for(j=0;j<(strlen(word)+1);j++){
        word[j] = tolower((unsigned char) word[j]);
      }
      strcpy(words[i],word);
      word = strtok(NULL, " .,-;/?!");
      ++i;
      ++nrCuvinte;
    }

    n = nrCuvinte-1;
    do{
      ok =1;
      for(k=0;k<n;++k){
        if(strcmp(words[k],words[k+1])>0)
        {
          char *aux;
          aux = words[k];
          words[k] = words[k+1];
          words[k+1]= aux;
          ok = 0;
        }
      }
      --n;
    }while(n>0&&(ok==0));

    for(j=0;j<nrCuvinte;++j){
      puts(words[j]);
    }
    for(j=0;j<L;++j){
      free(words[j]);
    }
    printf("If you want to exit type 'yes', else press enter.\n");
    fgets(user_input,4,stdin);
    if(strcmp(user_input, "yes") == 0)
      break;
  }
}

I also wrote another version, this time wrapping your code inside a function and calling this function from the main function inside a while(1) loop:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define L 500

void sort_sentence(){
  char *words[L];
  char *word;
  char sentence[100];
  int i = 0, nrCuvinte = 0;
  int j, k, ok, n, lung;

  for(j=0;j<L;++j)
  {
    words[j] = (char*)malloc(L*sizeof(char));
  }
  printf("Enter any sentence you want: \n");

  fgets(sentence,99,stdin);
  lung = strlen(sentence);

  if(sentence[lung-1] == '\n'){
    sentence[lung-1] = '\0';
  }
  printf("\n");

  word = strtok(sentence, " .,-;/?!");
  for(j=0;j<(strlen(word)+1);j++){
    word[j] = tolower((unsigned char) word[j]);
  }
  while(word != NULL){
    for(j=0;j<(strlen(word)+1);j++){
      word[j] = tolower((unsigned char) word[j]);
    }
    strcpy(words[i],word);
    word = strtok(NULL, " .,-;/?!");
    ++i;
    ++nrCuvinte;

  }

  n = nrCuvinte-1;
  do{
    ok =1;
    for(k=0;k<n;++k){
      if(strcmp(words[k],words[k+1])>0){
        char *aux;
        aux = words[k];
        words[k] = words[k+1];
        words[k+1]= aux;
        ok = 0;
      }
    }
    --n;
  }while(n>0&&(ok==0));

  for(j=0;j<nrCuvinte;++j){
    puts(words[j]);
  }
  for(j=0;j<L;++j){
    free(words[j]);
  }

}

int clean_stdin()
{
  while (getchar()!='\n');
  return 1;
}

int main(){

  int user_input;
  char c;

  while(1){
    sort_sentence();
    do{
      printf("If you want to exit type '2', if you want to continue type '1'.\n");
    }while(((scanf("%d%c", &user_input, &c) != 2 || c!='\n') && clean_stdin()) ||( user_input != 2 && user_input != 1));
    if(user_input == 2)
      return 0;
  }
}

Edit: Now in the second code example the user will be prompted with a message telling her/him to enter 1 or 2 until he/she inputs 1 or 2, every other input results in getting prompted with the same message again. If 1 is entered the next sort_sentence() function call is executed, if 2 is read the program terminates. Credits go to MOHAMED for his elegant solution on the community wiki. I used his idea here.

  • Thank you very much!!! The explanation with include, define and main were not that relevant because i did that, but I posted just the body of the main. I appreciate you help. Moreover, I would be very grateful if you could give me an example on the same problem, but using values(ex: 1 to repeat or 2 to exit). – Andrei - Alexandru Harpa Dec 27 '18 at 00:51
  • @Andrei-AlexandruHarpa you are welcome! If I understand you correctly you mean an example which awaits user input **1** or **2** and if **1** is read the loop should be repeated and if **2** is read the program should exit? –  Dec 27 '18 at 01:04