2

Full disclosure, this is an assignment for a class I have to do. We have a program that checks if two words are anagrams. We are supposed to modify it so that we can enter the words as command lines in a program. For instance: (./a.out hello elloh: is an anagram... ./a.out hello world: Not an anagram).

Here is the original program:

#include <stdio.h>
#define N 26

int main()
{


    char ch;
    int letter_counts[N]= {0};
    int i;
    int count =0;

    printf("enter a word: ");

    while((ch=getchar())!= '\n')

    {
        letter_counts[ch - 'a']++;

    }

    for(i =0;i<N;i++)
        printf("%d", letter_counts[i]);


    printf("enter the second word: ");
    while((ch=getchar())!= '\n')

    {
        letter_counts[ch - 'a']--;

    }

    for(i =0;i<N;i++)
        printf("%d", letter_counts[i]);

    for(i =0;i<N;i++)
        if(letter_counts[i]==0)
            count++;


    if(count == N)
        printf("The words are anagrams.\n");
    else

        printf("The words are NOT anagrams.\n");


    return 0;
}       

Now here is what I have so far:

#include <stdio.h>
#define N 26

/*
  This program is a modified version of anagram.c so that the words run as command-line arguments.   
*/
int main(int argc, char *argv[])
{
  if(argc != 3)
  {
    printf("Incorrect number of arguments");
    return 0;

  }
  char ch;
    int letter_counts[N]= {0};
    int i;
    int count =0;
  //int k;
  //for (k = 1; i < argc; i++) 
  //{
    while((ch=getchar())!= '\n')
      {
          letter_counts[ch - 'a']++;
    }

      for(i =0;i<N;i++)
          printf("%d", letter_counts[i]);

      while((ch=getchar())!= '\n')  
      {
          letter_counts[ch - 'a']--;
      }

      //for(i =0;i<N;i++)
        //printf("%d", letter_counts[i]);

      for(i =0;i<N;i++)
          if(letter_counts[i]==0)
              count++;

    int k;
    int j;
    for (k = 1; i < argc; i++)
    {
      for (j = 0; j < N; j++)
      {
        if (count == N) 
        {
          printf("%s and %s are anagrams\n", argv[k], argv[k + 1]);
          break;
        } 
        else
          printf("The words are NOT anagrams. \n");
      }
    }

    if(count == N)
          printf("The words are anagrams.\n");
     else
        printf("The words are NOT anagrams.\n");
  //}




    return 0;
}       

The output (if the number of arguments is correct) is always :

0000000000000000000000000
0000000000000000000000000
These are anagrams

What am I doing wrong here and what is the best way to go about this?

Thank you for any help I really appreciate it.

cr0wn
  • 41
  • 4

3 Answers3

0

You are using getchar() which reads from STDIN, which isn't what you want to do if you're getting your words from command-line arguments. Instead you want to look at argv:

for (char *c = argv[1]; *c != NULL; c++) {
    letter_counts[*c - 'a']++;
}

and

for (char *c = argv[2]; *c != NULL; c++) {
    letter_counts[*c - 'a']--;
}

More about argc and argv: http://crasseux.com/books/ctutorial/argc-and-argv.html

Nikolas Stevenson-Molnar
  • 4,235
  • 1
  • 22
  • 31
0

To not solve your homework for you I'll show you how to use argc and argv on a different program that just checks if the first parameter reversed equals the second:

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

int main(int argc, char **argv)
{
    if (argc != 3) {
        printf("Usage: %s first_word second_word\n\n", argv[0]);
        return EXIT_SUCCESS;
    }

    char const *first = argv[1];
    char const *second = argv[2];

    size_t first_length = strlen(first);
    size_t second_length = strlen(second);

    if (first_length != second_length) {
        puts("The words are NOT semordnilaps.\n");
        return EXIT_SUCCESS;
    }

    for (size_t first_index = first_length, second_index = 0; first_index; --first_index, ++second_index) {
        if (first[first_index - 1] != second[second_index]) {
            puts("The words are NOT semordnilaps.\n");
            return EXIT_SUCCESS;
        }
    }

    puts("The words are semordnilaps.\n");
}
Swordfish
  • 12,971
  • 3
  • 21
  • 43
  • Search for "anagram vs semordnilap" to understand why I downvote ;) – grek40 Feb 25 '19 at 06:58
  • @grek40 Gaaaah. Edited. – Swordfish Feb 25 '19 at 07:00
  • If you add a nice hint that you intentionally solved a different problem in order to show commandline usage without revealing the homework solution, my rage will be calmed completely – grek40 Feb 25 '19 at 07:02
  • @grek40 Haha, took me quite a while to get that one. Thought in the OPs sample call `./a.out hello elloh: is an anagram` was a typo ... hello olleh vs. hello elloh, haha – Swordfish Feb 25 '19 at 11:53
-1

Modified program torun from command line argumement. Below is working code snippet for you. Here we pass two command line arguments with program name. while ((ch = argv[1][len]) != '\0') retrieve the char by char from first arguments and while ((ch = argv[2][len]) != '\0') retrieve the same from the second and rest of the logic remains same.

#include <stdio.h>
#define N 26

int main(int argc, char *argv[])
{
    if( argc != 3)
    {
        printf("Incorrect argumemts\n");
        return 0;
    }
    char ch;
    int letter_counts[N]= {0};
    int i;
    int count =0;

    int len=0;
    while ((ch = argv[1][len]) != '\0')
    {
        letter_counts[ch - 'a']++;
        len++; /* moving index */
    }

    for(i =0;i<N;i++)
        printf("%d", letter_counts[i]);

    len=0;
    while ((ch = argv[2][len]) != '\0')
    {
        letter_counts[ch - 'a']--;
        len++; /* moving index */
    }

    for(i =0;i<N;i++)
        printf("%d", letter_counts[i]);

    for(i =0;i<N;i++)
        if(letter_counts[i]==0)
            count++;

    if(count == N)
        printf("The words are anagrams.\n");
    else

        printf("The words are NOT anagrams.\n");


    return 0;
}
Practice
  • 1
  • 2
  • 2
    Hi, a good answer should contain why it is now working ... not only the code. Please add some description to your answer. – YesThatIsMyName Feb 25 '19 at 08:08
  • *`letter_counts[ch - 'a']`* – You rely on the user only giving you lowercase characters. If the user "misbehaves" (or isn't aware of the limitation) you access the array out of bounds. Never trust user input. This can also lead to a buffer overflow attack if exploited intentionally. Also your two `while`-loops cry desperatly wanting to be `for`-loops. – Swordfish Feb 25 '19 at 10:44
  • @Swordfish: This is just sample program and modification to existing one not a production code to ship with product. There are so may extra checks and precautions we can add to any computer program. – Practice Feb 25 '19 at 11:03
  • @Pavan What's the problem in adding a check for `isalpha()` and a `tolower()` + a short explanation?? – Swordfish Feb 25 '19 at 11:51
  • When we view the exercise as "rework the existing program with minimal behavior change", we wouldn't want undefined behavior on "@Swordfish" input to disappear due to some clever user input handling. I know, I should stop trolling and start answering some questions. *Out* – grek40 Feb 25 '19 at 18:53