0

First I apologize for any mistype, for I am Brazilian and English is not my native language.

I am a freshman at my college and I got this algorithm to solve, from my teacher:

Make a program that creates a vector of n words, n being a size entered by the user (maximum 100). Your program should remove all duplicate words from the input vector and sort the words. Print the final vector without repeated and ordered words.

E.g. with 7 words to sort:

Input: 7 [enter]

hand ear leg hand hand leg foot

Output: ear foot hand leg

Note: Comment the program prints so that the output of the program is as shown in the example above (the numbers are separated by a spacebar, without space after last digit).

Note2: In case of invalid entry the program should print: "invalid entry" (all lower case).

Ok, I got it working but the I got confused with the notes and I can't find a way to fix the possible bugs, here is my code:

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

int main()
{
  char word[100][100], aux[100];
  int i, j, num;

  printf("Type how many words you want to order: ");
  do
  {
  scanf("%d", &num);
  }while (num>100 || num<=0);

  for(i=0; i<num; i++)
    scanf("%s",&word[i]);

  for (i = 0; i < num; i++) //loop to sort alphabetically
  {
    for (j = i+1; j < num; j++)
    {
      if ((strcasecmp(word[i], word[j]) > 0))  //swapping words
      {
        strcpy(aux, word[j]);
        strcpy(word[j], word[i]);
        strcpy(word[i], aux);
      }
    }
  }

  for (i = 0; i < num; i++) //loop to remove duplicates
  {
    if ((strcasecmp(word[i], word[i+1]) == 0))  //finding the duplicates
    {
      for (j = i+1; j < num; j++) //loop to delete it
        strcpy(word[j], word[j+1]);

      num--;
      i--;
    }
  }

  printf("\nWords sorted and without duplicates:\n");
  for(i=0; i<num-1; i++)
    printf("%s ", word[i]); //output with spacebar

  printf("%s", word[num-1]); //last output without spacebar

  return 0;
}

When I type a word with more than 100 characters, the Code::Blocks closes with an error, else it works fine. What do you think I should change?

The teacher uses a Online Judge (Sharif Judge) to evaluate if the code is right, and I got error in 3 of the tests (that are not specified), all of them were "Time Limit Exceeded". Maybe it has do to with the size of the matrix, or the problem with words >100.

Thanks in advance, Vinicius.

Community
  • 1
  • 1
Vinicius
  • 55
  • 9
  • What is the error you receive? – J.N. May 09 '17 at 01:32
  • [this](http://imgur.com/a/xYdjK). – Vinicius May 09 '17 at 01:56
  • Sometimes it closes automatically. – Vinicius May 09 '17 at 01:57
  • What about the "Code::Blocks" error? – J.N. May 09 '17 at 01:58
  • I don't know what I did to get the error now, but it was like `Process terminated with status -1073741510 (0 minute(s), 1 second(s))` – Vinicius May 09 '17 at 02:00
  • I got it now, I don't know how, but the program just [stopped working](http://imgur.com/a/cYUWb). – Vinicius May 09 '17 at 02:04
  • If the words can be 100 characters max, you have a problem if you expect to use null-terminated strings, because that requires storage of 101 characters. Use `strncpy` and/or enlarge your arrays. Regarding time limit exceeded, you have an issue where you loop trying to read an integer. This will continue looping even if the stream closes. You seem to also be outputting extraneous messages that are not defined in the problem statement. Or possibly it's because your sorting algorithm has N-squared time complexity. – paddy May 09 '17 at 02:23
  • @paddy , where do you suggest me to add the `strncpy`? I need to separate the words by **enter** or **spacebar**, this way wouldn't it kill the **spacebar**? – Vinicius May 09 '17 at 02:35

4 Answers4

0

of course you will get an error if you use woerds more than 100 length casue you have this line: char word[100][50], aux[100];

that means that you word length limit is set to 50. use word[100][100];

also you may not delete duplicates, just skip them in output

lol of course if youre using judge , you should not output any symbols except the answer, this means you should delete all lines, like :

printf("Type how many words you want to order: ");

and check the input format, and check limitations, i mean max word length , max amounts of words


try smth like this:

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

#define max_word_length = 101;
#define max_amount_of_words = 101;

int main() {
    char word[max_amount_of_words][max_word_length] = {};
    char aux[max_word_length];
    int i, j, num;

    scanf("%d", &num);

    if (num < 0 || num > 100) {
        printf("invalid entry");
        return 0;
    }

    for (i = 0; i < num; i++) {
        scanf("%s", word[i]);
    }

    for (i = 0; i < num; i++) {//loop to sort alphabetically    
        for (j = i + 1; j < num; j++) {
            if ((strcasecmp(word[i], word[j]) > 0)) {  //swapping words         
                strcpy(aux, word[j]);
                strcpy(word[j], word[i]);
                strcpy(word[i], aux);
            }
        }
    }

    bool is_joint = false;
    for (i = 0; i < num; i++) { //loop to skip duplicates   
        if ((strcasecmp(word[i], word[i + 1]) != 0)) { //if there is a duplicate , we willnot output it
            if(is_joint) printf(" ");
            printf("%s ", word[i]);
            is_joint = true;
        }
    }

    return 0;
}
bobra
  • 615
  • 3
  • 18
  • I had the `[100]` before, the Judge got me the same error – Vinicius May 09 '17 at 01:53
  • If n is always< 100. Definitely your sorting is not causing any time limit exceeded. Make sure ur input numbers are taken properly. If the input is > 100 print ' invalid entry'. Try the combination of always putting'\0' at 100 index also. – arunk2 May 09 '17 at 02:47
  • @ArunKumar , after the **fgets**, inside the **for** loop? something like `if (sizeof (word[i])>100) printf("invalid entry");` – Vinicius May 09 '17 at 02:57
  • @Vinicius if you check your task with judge, there is a guaranteed correct input, but there should be strinct input format and limits. you should remove any lines like while (num>100 || num<=0); if (sizeof (word[i])>100) printf("invalid entry"); – bobra May 09 '17 at 03:01
  • @bobra What do you mean "skip"? I don't know a way to skip them, can you tell me? – Vinicius May 09 '17 at 03:02
  • @bobra I submitted the latest code, the 3 errors with "Time Limit Exceeded" are now "Wrong". – Vinicius May 09 '17 at 03:12
  • @Vinicius make sure about last 'space' symbol in the output, maybe you can link your task in judge ? – bobra May 09 '17 at 03:14
  • @bobra I tried to run your code, i got [this](http://i.imgur.com/O67G8WV.png) error – Vinicius May 09 '17 at 03:18
  • @bobra I can't give the Judge, is from the college and need to use their proxy settings + my account – Vinicius May 09 '17 at 03:19
  • @Vinicius change for ( int i = 0; i < num; i++) to for ( i = 0; i < num; i++), and declare int i above, also with j . change max_amount_of_words = 100 to 101, and char word[max_amount_of_words + 1][max_word_length] = {}; to char word[max_amount_of_words][max_word_length] = {}; we have different compilers – bobra May 09 '17 at 03:22
  • @bobra ,still doesn't work, the **for** did work, but the char word didn't, can't I change to `word[101][101]`? – Vinicius May 09 '17 at 03:32
  • @bobra and what is the use for the `= {};`? – Vinicius May 09 '17 at 03:33
  • @Vinicius i dont know, waht a bad compiler are you using, but according to standart ={} sets all array elements to zero value in your case '\0'; – bobra May 09 '17 at 03:35
  • @Vinicius if there is a big problem , just swap 8 and 9 lines, (char word will be a global variable), and remove ={} , this should set it to '\0' – bobra May 09 '17 at 03:38
  • @bobra I'm using GNU GCC on Code::Blocks – Vinicius May 09 '17 at 03:39
  • @bobra do you have any social media? We need to keep discussing, if you don't mind, I need to sleep and I'll only be able to answer and keep active for like 10h from now – Vinicius May 09 '17 at 03:47
  • @bobra It didn't, the output it gave me was [wrong](http://i.imgur.com/W1smALk.png) – Vinicius May 09 '17 at 03:49
  • @Vinicius notice, i fixed before if ((strcasecmp(word[i], word[i + 1]) != 0)) there was == , change it to != – bobra May 09 '17 at 03:50
  • This won't resolve the problem when the number of input characters exceed 100. It is most likely going to get seg fault error. The requirement says either a space or newline char delimeters need to be considered for separation of words. Moreover, the program has to check whether non alphabet was inserted. So the difficult piece of this project is getting the input stored properly into array of strings. – Nguai al May 09 '17 at 04:17
0

I guess you input sanity check is causing the issue.

As mentioned in the comment section. If n is always < 100. Definitely your sorting is not causing any time limit exceeded. Looks like the n is given something greater than 100 and your scanf is waiting and causing the issue. Also, make sure your input numbers are taken properly. If the input is > 100 print 'invalid entry'. Something like below should work.

scanf("%d", &num);
if (num > 100)
    printf("invalid entry");

for (i = 0; i < num; i++) {
    scanf("%s", word[i]);
    if (strlen(word[i])>100)
            printf("invalid entry");
}

Hope it helps!

arunk2
  • 2,246
  • 3
  • 23
  • 35
  • Thank you, it really helped! But still facing problems with Judge, haha – Vinicius May 09 '17 at 04:15
  • Still haven't, but the thing is, the code is right, but the Judge tests shows Wrong, and I don't know what is wrong haha – Vinicius May 09 '17 at 04:51
  • Check for spaces and formatting in your printf(). Any additional space or upper case special characters could be culprit. – arunk2 May 09 '17 at 04:53
0

I got 100% on Judge, I fixed the code and looks like this:

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

int main(){
  char word[101][101],aux[101]; //a number higher than the limit to comparisons
  int i,j,num;

  scanf("%d",&num);
  if(num<=0||num>100){ // if words < 0 or >100
    printf("invalid input");
    return 0;
  }

  for(i=0;i<num;i++){
    scanf("%s",&word[i]); //read n words
    if(strlen(word[i])>100){ //if word >100 caracters
      printf("invalid input");
      return 0;
    }
    for(j=0;j<strlen(word[i]);j++){
      if (word[i][j]>=65&&word[i][j]<=90){
        word[i][j]= word[i][j]+32; // if word is uppercase, make them lowcase
      }
      else if (word[i][j]>122||word[i][j]<97){// if word is different from alphabet lowercase
      printf("invalid input");
      return 0;
      }
    }
  }

  for(i=0;i<num;i++){
    for(j=i+1;j<num;j++){
      if((strcmp(word[i],word[j])>0)){ //loop to sort words
        strcpy(aux,word[j]);
        strcpy(word[j],word[i]);
        strcpy(word[i],aux);
      }
    }
  }


  for(i=0;i<num-1;i++){
    if((strcmp(word[i],word[i+1])!=0)){ // output words with spacebar, without the last one
      printf("%s ",word[i]);
    }
  }
  printf("%s",word[num-1]); // last word without spacebar

  return 0;
}

Thank you everyone who tried to help, I've learned a lot with your suggestions!

Vinicius
  • 55
  • 9
-1

This project is actually pretty tough assignment for a programmer who just started in C.

Run this program in your computer. Before running against the Judge, make sure you run many times with your manual inputs. Once you are happy with the tests, try against the Judge.

Like I said, the hardest part is storing the user's inputs according to spec (accepting space or newline characters in multiple lines).

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

int
main(void)
{

   int iNumW, iIndex;
   int iWCnt = 0;
   int iC;
   char caTemp[100];
   char caWords[100][100];
   char *cpDelimeter = " \n";
   char *cpToken;
   char *cp;
   short sIsWord = 1;
   char caGarbage[100];

   scanf("%d", &iNumW );
   fgets(caGarbage, sizeof caGarbage, stdin);  //Remove newline char

   //Get word inputs
   while( iWCnt < iNumW )
   {
       fgets(caTemp, sizeof caTemp, stdin );
       for( cpToken = strtok( caTemp, cpDelimeter );   cpToken != NULL;  cpToken = strtok( NULL, cpDelimeter)){

          cp = cpToken;
          while( *cp ){
              sIsWord = 1;

              //Check if alphabet
              if( !isalpha(*cp) ){
                  sIsWord = 0;
                  break;
              }
              cp++;
          }
          if( sIsWord ){
              strcpy( caWords[iWCnt], cpToken );
             //printf( "%s\n", caWords[iWCnt]);
              iWCnt++;
              if( iWCnt >= iNumW ) break;
          } else {
              printf("invalid entry.\n");
        }
        //printf("%d\n", iWCnt);
      } 
   }
   int i,j ;
   for (i = 0; i < iWCnt; i++) {//loop to sort alphabetically    
      for (j = i + 1; j < iWCnt; j++) {
        if ((strcasecmp(caWords[i], caWords[j]) > 0)) {  //swapping words         
            strcpy(caTemp, caWords[j]);
            strcpy(caWords[j], caWords[i]);
            strcpy(caWords[i], caTemp);
          }
      }
  }

   for (i = 0; i < iWCnt; i++) { //loop to skip duplicates   
       if ((strcasecmp(caWords[i], caWords[i + 1]) != 0)) { //if there is a duplicate , we willnot output it
        printf("%s ", caWords[i]);
       }
   }

   return 0;
} 
Nguai al
  • 958
  • 5
  • 15
  • I typed a word with more than 100 char and then it didn't let me type the following words (E.g: 4 as the number of words), and the words can be separated by **enter** or **spacebar** – Vinicius May 09 '17 at 02:24
  • The Judge pointed as wrong, I think using **fgets** is not possible, since the teacher didn't teach about it yet, only **gets**. – Vinicius May 09 '17 at 02:31
  • fgets() will only capture all characters including white space until a newline char is recognized or up to the number of characters allowed. In this case 100. So if you typed `sdfgfg fdfda ererer fadfaf`, fgets() will recognize this as one word. So what you need is the following: after fgets(), need to parse this string into words if there are any space or white characters. You still need fgets() cause it will prevent you from exceeding 100 characters. – Nguai al May 09 '17 at 02:33
  • Here is the difference between gets() and fgets() [link](http://stackoverflow.com/questions/28400020/difference-between-fgets-and-gets) – Nguai al May 09 '17 at 02:36
  • What do you think about `fgets( word[i], sizeof(word[i]), stdin ); if (word[i]==' ' || word[i]=='\0'); i+=1;` – Vinicius May 09 '17 at 02:43
  • @Vinicius: Note that you should [Never, ever use `gets()` because it is not safe!](http://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used) — and teachers who teach the use of `gets()` should be treated as 'propagators of bad practices'. Everything they teach must be treated with caution because teaching `gets()` is really that bad! Never use `gets()` again after you finish this course — or after you've been taught `fgets()`, or `getline()` from POSIX. – Jonathan Leffler May 09 '17 at 04:41
  • @JonathanLeffler Thank you for your advice, this teacher must have some problems, the Judge tests shows wrong for ever, it's driving me nuts – Vinicius May 09 '17 at 04:52
  • @Nguaial the judge gave this a 0? Idk why haha – Vinicius May 09 '17 at 05:52
  • @vinicius - Did you manually run it yourself? I don't know what `Judge` is doing. But can you duplicate what Judge is doing manually and let me know which test case fails. – Nguai al May 09 '17 at 05:57
  • @Nguaial I can't duplicate what judge is doing, the teacher didn't say what the judge tests do, we have to figure out by ourselves. – Vinicius May 09 '17 at 09:36
  • @viinicius - We need to know which test case from `Judge` failed this code. – Nguai al May 09 '17 at 14:14