Modifying a program to run as command line arguments in C - c

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.

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

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");
}

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;
}

Related

Why does i never get past 1?

I am trying to create a program to solve a wordsearch from a 2D array using only pointers. In my primary function for doing the actual search for the words I have a while loop that is supposed to keep going as long as i doesn't exceed the length of the word and as long as the letters from the word correspond to the letters on the grid. After finding the word it should make the letters on the grid lowercase and print out that it found the word. Here is my entire program right now.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void printPuzzle(char** arr, int n);
void searchPuzzle(char** arr, int n, char** list, int listSize);
void searchWord(int j, int k, int gridsize, char** arr, char** list, int listPos);
int main(int argc, char **argv) {
int bSize = 15;
if (argc != 2) {
fprintf(stderr, "Usage: %s <puzzle file name>\n", argv[0]);
return 2;
}
int i, j;
FILE *fptr;
char **block = (char**)malloc(bSize * sizeof(char*));
char **words = (char**)malloc(50 * sizeof(char*));
fptr = fopen(argv[1], "r");
if (fptr == NULL) {
printf("Cannot Open Puzzle File!\n");
return 0;
}
for(i=0; i<bSize; i++){
*(block+i) = (char*)malloc(bSize * sizeof(char));
fscanf(fptr, "%c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", *(block+i), *(block+i)+1, *(block+i)+2, *(block+i)+3, *(block+i)+4, *(block+i)+5, *(block+i)+6, *(block+i)+7, *(block+i)+8, *(block+i)+9, *(block+i)+10, *(block+i)+11, *(block+i)+12, *(block+i)+13, *(block+i)+14 );
}
fclose(fptr);
fptr = fopen("states.txt", "r");
if (fptr == NULL) {
printf("Cannot Open Words File!\n");
return 0;
}
for(i=0; i<50; i++){
*(words+i) = (char*)malloc(20 * sizeof(char));
fgets(*(words+i), 20, fptr);
}
for(i=0; i<49; i++){
*(*(words+i) + strlen(*(words+i))-2) = '\0';
}
printf("Printing list of words:\n");
for(i=0; i<50; i++){
printf("%s\n", *(words + i));
}
printf("\n");
printf("Printing puzzle before search:\n");
printPuzzle(block, bSize);
printf("\n");
searchPuzzle(block, bSize, words, 50);
printf("\n");
printf("Printing puzzle after search:\n");
printPuzzle(block, bSize);
printf("\n");
return 0;
}
void printPuzzle(char** arr, int n){
for(int i = 0; i < n; i++){
printf("\n");
for(int j = 0; j < 15; j++){
printf("%c ", *(*(arr+i)+j));
}
}
}
void searchPuzzle(char** arr, int n, char** list, int listSize){
for(int i = 0; i < listSize; i++){
for(int j = 0; j < 15; j++){
for(int k = 0; k < 15; k++){
searchWord(j, k, 15, arr, list, i);
}
}
}
}
void searchWord(int j, int k, int gridsize, char** arr, char** list, int listPos){
int wordlength = strlen(*(list+listPos));
if(j+wordlength <= gridsize){ //Horizontal
int i = 0;
while(i < wordlength && *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
i++;
}
if(i == wordlength){
while(i > 0 && *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
*(*(arr+(j+i))+k) = tolower(*(*(arr+(j+i))+k));
i--;
}
printf("Word found: ");
for(i = 0; i < wordlength; i++)
printf("%c", *(*(list+listPos)+i));
}
}
if(k+wordlength <= gridsize){ //Vertical
int i = 0;
while(i < wordlength && *(*(arr+j)+(k+i)) == *(*(list+listPos)+i)){
i++;
}
if(i == wordlength){
while(i > 0 && *(*(arr+j)+(k+i)) == *(*(list+listPos)+i)){
*(*(arr+(j+i))+k) = tolower(*(*(arr+(j+i))+k));
i--;
}
printf("Word found: ");
for(i = 0; i < wordlength; i++){
printf("%c", *(*(list+listPos)+i));
}
}
}
if(j+wordlength <= gridsize && k+wordlength <= gridsize){ //Diagonal
int i = 0;
while(i < wordlength && *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
i++;
}
if(i == wordlength){
while(i > 0 && *(*(arr+(j+i))+(k+i)) == *(*(list+listPos)+i)){
*(*(arr+(j+i))+(k+i)) = tolower(*(*(arr+(j+i))+(k+i)));
i--;
}
printf("Word found: ");
for(i = 0; i < wordlength; i++)
printf("%c", *(*(list+listPos)+i));
}
}
}
This is the part I believe there is a problem with.
while(i < wordlength && *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
i++;
}
If I print out the decimal value of i after this while loop it should at some point approach the length of one of the words as I know some words are horizontal, however every time it loops through and prints the value of i it never exceeds 1 which means the while loop never runs more than once which is impossible with the wordsearch files I am using to test this. What is causing this to happen? It is also 0 or 1 for every other direction when I try, the example above was just the while loop from the horizontal search.
There may also be a problem with the function searchPuzzle and the amount it loops through. However, I think that may be just my imagination.
Additional Info: The grid is 15x15 and there are 50 words in the list.
I think that you might need to declare Wordsearch again after the && -
while(i < wordlength && wordlength *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
i++;
}

C, turning camel text into snake text

I am total beginner, I want to make an application that for each lower camel case word supplied as a command line argument will print it's snake case equivalent. Also turns big letters into smaller ones and makes between them "_".
Example:
./coverter Iwant tobe famousAlready.
output:
i_want
tobe
famous_already
I have found some code to make the letters smaller, and output words in the command line separately. But I have no clue how to put them together, how to appeal into single character in function main? Is this even possible?
#include <stdio.h>
int main (int argc, char* argv[]);
{
printf("argc = %d\n", argc);
for (int i = 0; i < argc; i++)
{
printf("argv[%d] = %s\n", i, argv[i]);
}
}
char change()
{
char words[30];
int ch;
printf ("Give the words: ");
int i=0;
while ((ch=getchar()) != EOF)
{
slowko[i]=ch;
if(isupper(slowko[i])) /* isupper, robi rzeczy - sprawdza czy */
/* litera z sekwencji jest duza */
{
slowko[i]=tolower(ch); /*zamien duzy znak na maly*/
printf("_");
}
else if(slowko[i] == ' ')
{
printf("\n");
}
printf ("%c", slowko[i]);
i++;
}
}
You have command line arguments inside argv array starting from index 1. Maybe, it's not the most elegant solution, but it works:
#include <stdio.h>
#include <ctype.h>
void print_snake_case(const char str[]){
int i = 0;
while (str[i] != '\0')
{
if(isupper((unsigned char) str[i])) /*isupper, robi rzeczy - sprawdza czy litera z sekwencji jest duza*/
{
const char ch = tolower((unsigned char) str[i]); /*zamien duzy znak na maly*/
/*
Different order of "_": it should be placed after
the character in case it's at the beginning of the word.
And before the character if it's not at the beginning.
*/
if(i != 0)
{
printf("_");
printf ("%c", ch);
}
else
{
printf ("%c", ch);
printf("_");
}
}
else
printf ("%c", str[i]);
i++;
}
printf("\n");
}
int main (int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
print_snake_case(argv[i]);
}
}
Output:
$ ./converter Iwant tobe famousAlready
i_want
tobe
famous_already

Find missing lower-case letters that are not in a series of words

As stated in the title I am trying to find all lower-case letters that are not in a series of words. There are no upper-case letters, digits, punctuation, or special symbols.
I need help fixing my code. I am stuck and do not know where to go from here.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void){
int letters[26];
char words[50];
int i = 0, b = 0;
printf("Enter your input : ");
scanf("%s", words);
for(i = 0; i < 26; i++){
letters[i] = 0;
}
while(!feof(stdin)){
for(b = 0; b < strlen(words) - 1; b++){
letters[ words[b] - 'a']++;
scanf("%s", words);
}
}
printf("\nMissing letters : %c ", b + 97);
return 0;
}
My output is giving me some random letter that I do not know where it is coming from.
Here is a working first implementation.
As well as the comments that have already been made, you should use functions wherever possible to separate out the functionality of the program into logical steps. Your main function should then just call the appropriate functions in order to solve the problem. Each function should be something that is self contained and testable.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_INPUT 20 /* Max input to read from user. */
char *readinput(void);
void find_missing_lower_case(char *, int);
int main()
{
char *user_input = readinput();
int len_input = strlen(user_input);
printf("user input: %s\n", user_input);
printf("len input: %d\n", len_input);
find_missing_lower_case(user_input, len_input);
/* Free the memory allocated for 'user_input'. */
free(user_input);
return 0;
}
char *readinput()
{
char a;
char *result = (char *) malloc(MAX_INPUT);
int i;
for(i = 0; i < MAX_INPUT; ++i)
{
scanf("%c", &a);
if( a == '\n')
{
break;
}
*(result + i) = a;
}
*(result + i) = '\0';
return result;
}
void find_missing_lower_case(char *input, int len_input)
{
int a = 97; /* ASCII value of 'a' */
int z = 122; /* ASCII value of 'z' */
int lower_case_chars[26] = {0}; /* Initialise all to value of 0 */
/* Scan through input and if a lower case char is found, set the
* corresponding index of lower_case_chars to 1
*/
for(int i = 0; i < len_input; i++)
{
char c = *(input + i);
if(c >= a && c <= z)
{
lower_case_chars[c - a] = 1;
}
}
/* Iterate through lower_case_chars and print any values that were not set
* to 1 in the above for loop.
*/
printf("Missing lower case characters:\n");
for(int i = 0; i < 26; i++)
{
if(!lower_case_chars[i])
{
printf("%c ", i + a);
}
}
printf("\n");
}
I figured it out and this is the code I used.
int main(void)
{
int array[26];
char w;
int i=0;
for(i=0; i<26; i++) {
array[i]=0; }
printf("Enter your input: ");
scanf("%c", &w);
while(!feof(stdin)) {
array[w-97] = 1;
scanf("%c", &w); }
printf("Missing letters: ");
for(i=0; i<26; i++) {
if(array[i] == 0) {
printf("%c ", i+97); }
}
printf("\n");
return 0;
}

Char Count in C?

So I am getting 1 more extra character than I should when i compile this code, someone please tell me the stupid error i am doing.
#include <stdio.h>
#include <conio.h>
int main() {
char str[20];
char A = 'a';
char B = 'A';
int count = 0, i;
printf("Enter a string : ");
fgets(str, 20, stdin);
for (i = 0; str[i] != '\0'; i++) {
if (str[i] == A||B)
count++;
}
if (count == 0)
printf("\nCharacter A is not present");
else
printf("\nThere are %d A's in your string.", count);
getchar();
return 0;
}
/* This is the issue (str[i] == A)||(str[i] == B) */
#include <stdio.h>
#include <conio.h>
int main() {
char str[20];
char A = 'a';
char B = 'A';
int count = 0, i;
printf("Enter a string : ");
fgets(str, 20, stdin);
for (i = 0; str[i] != '\0'; i++) {
if (str[i] == A || str[i] == B)
count++;
}
if (count == 0)
printf("\nCharacter A is not present");
else
printf("\nThere are %d A's in your string.", count);
getchar();
return 0;
}

Arrays in a Palindrome program

So I made a program where I have to input a word and it displays if it is a palindrome (a word that is the same both ways) or not.
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[]){
char word;
int length, counter;
printf("Please enter a word: ");
scanf("%c", &word);
int flag = 1;
for (counter = 0; counter < length && flag; counter++) {
printf("%c\t %c", word[counter], word[length - counter])
if (word[counter] == word[length - counter - 1]){
flag = 0;
}
}
if (flag) {
printf("%c is a palindrome!", word);
}
else {
printf("%c is NOT a palindrome!", word);
}
}
I set it up so that it displays each letter side by side. If a letter isn't the same then the flag is "thrown"(set to 0) and this will end the program saying: "word is NOT a palindrome!"
I get an error at the part where it says word[counter] saying it isn't a subscripted value. What can I do to make this work? Is there anything else I am doing wrong?
This char word; is not an array. This char word[100]; is an Array. Also you read a single character using scanf("%c", &word); not a word (as in a string or series of characters). Use:
fgets (word , 100 , stdin)
Also length is not initialized, so it will lead to UB.
Make this modifications in your program.It will run fine.
#include <stdio.h>
#include <string.h>
int main()
{
char word[100];
int length, counter;
printf("Please enter a word: ");
scanf("%s",word);
length=strlen(word);
int flag = 1;
for(counter = 0; counter < length/2 && flag; counter++)
{
if (word[counter] != word[length-counter-1])
{
flag = 0;
break;
}
}
if (flag)
{
printf("%s is a palindrome!\n", word);
}
else {
printf("%s is NOT a palindrome\n!", word);
}
}
****************************************************************
* Simple Array Palindrome Program *
****************************************************************/
#include <iostream>
using namespace std;
int main (){
int arr_size;
int flag=0;
/*****************************************
* Array Size *
*****************************************/
cout<<"Enter The Array Size: \n->arr[";
cin>>arr_size;cout<<" ]";
int arr[arr_size];
/*****************************************
* User_Input *
*****************************************/
for(int i=0;i<arr_size;i++){
cout<<"Enter Value For Arr[ "<<i<<" ] -> ";
cin>>arr[i];
}
/*****************************************
* Palindrome_Check *
*****************************************/
for(int k=0,j=arr_size-1;k<arr_size && j>-1;k++)
{
if(arr[i]==arr[j];
{
flag++;
}
}
/*****************************************
* Flag Check *
*****************************************/
if(flag==arr_size) {
cout<<"Array Is Palindrome: ";
}
else
{
cout<<"Array Is Not Palindrome: ";
}
}

Resources