In this exercise I put two words then I do a function to check if they are anagram, but there is an error in the output knowing that the outpout is true of which there is the same length of the two words
Example of words Anagram:
bob - obb
users - resus
can you help me...
bool Anagram(int l, int k, char T1[l],char T2[k])
{
int i = 0;
while (i < l)
{
for (int j = 0; j < k; j++)
{
if (T1[i] != T2[j])
{
return 0;
}
}
i++;
}
return 1;
}
int main()
{
char T1[100], T2[100];
printf("Give the first word :");
gets(T1);
int k = strlen(T1);//k is the length of the first word
printf("Give the second word :");
gets(T2);
int l = strlen(T2);//l is the length of the second word
if (l != k)
{
printf("\nThe two words are not Anagrams !\n");
return 0;
}
else
{
if (Anagram(l, k, T2, T1) == true)
{
printf("\nThe two words are Anagrams !\n");
}
else
{
printf("\nThe two words are not Anagrams !\n");
}
}
}
qsort is your friend! Why reinvent the wheel? The stdlib provides all means for this task!
Whitespace can easily be stripped after sorting using strcspn, as each of the whitespace chars ascii code is < alnum characters ascii code.
If you don't want to rely on those ascii properties, the compare_chars function can easily adapted so that all whitespace are sorted either to the front or to the end (In the example it sorts the ws to the end).
I wonder if somebody comes up with a unicode version of isAnagram.
Please note that i applied the sorting on a copy of the original strings so that the isAnagram function does not mess up the input.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
int compare_chars(const void *c1, const void *c2)
{
// Sign corresponds to backward sorting so that
// whitespace appears at the end
return *(char *)c2 - *(char *)c1;
}
void sort_remove_whitespace(const char *src, char dest[strlen(src) + 1])
{
strcpy(dest, src);
qsort(dest, strlen(dest), sizeof(char), compare_chars);
dest[strcspn(dest, " \b\t\v\r\n")] = '\0';
}
bool isAnagram(char* T1, char *T2)
{
char T1_copy[strlen(T1) + 1];
char T2_copy[strlen(T2) + 1];
sort_remove_whitespace(T1, T1_copy);
sort_remove_whitespace(T2, T2_copy);
printf("T1 sorted: '%s', T2 sorted: '%s'\n", T1_copy, T2_copy);
return 0 == strcmp(T1_copy, T2_copy);
}
void prompt(const char *msg, char *buf, size_t N)
{
char *fgets_return;
puts(msg);
fgets_return = fgets(buf, N, stdin);
if (NULL == fgets_return)
{
printf("Input error!");
exit(-1); // fail fast fail early
}
printf("OK. Got %s\n", buf);
}
int main()
{
char T1[100], T2[100];
prompt("Give the first word :", T1, sizeof(T1));
prompt("Give the second word :", T2, sizeof(T2));
if ( isAnagram(T1, T2) )
{
printf("The two words are Anagrams !\n");
}
else
{
printf("The two words are not Anagrams !\n");
}
return 0;
}
Example output:
Give the first word :
dead beef
OK. Got dead beef
Give the second word :
fat thief
OK. Got fat thief
T1 sorted: 'feeeddba', T2 sorted: 'ttihffea'
The two words are not Anagrams !
Give the first word :
anagram
OK. Got anagram
Give the second word :
nag a ram
OK. Got nag a ram
T1 sorted: 'rnmgaaa', T2 sorted: 'rnmgaaa'
The two words are Anagrams !
The biggest problem is with your concept of Anagram. The classic example is:
"anagram"
"nag a ram"
Each uses the same letters exactly once with whitespace ignored.
There are several ways to approach determining in two strings are an anagram. You can either use a single array (generally of 128 integer values initialized all zero to cover all characters in the ASCII character set, or 256 to also cover the Extended-ASCII characters.
With the single array, you simply loop over each string. With the first string for each non-whitespace character you increment the index corresponding to the ASCII value of the character, and for the second string you decrement the value at the index corresponding to the ASCII value of the character. At the end, if each character in each string is used exactly the same number of times -- all array values will be zero which will confirm an anagram.
Using two arrays of the same size (either 128 or 256), you simply loop over the characters in each string and for each non-whitespace character you increment the index corresponding to that characters ASCII value in similar fashion, but when done, you compare whether the two arrays are equal to each other with a loop or memcmp().
A short implementation would be:
#include <stdio.h>
#include <ctype.h>
#define NCHARS 256 /* constant to count array size, covers ASCII + extended ASCII */
int isanagram (const char *s1, const char *s2)
{
int count[NCHARS] = {0}; /* counting array, covers all extended ASCII */
for (; *s1; s1++) /* loop over chars in string 1 */
if (!isspace(*s1)) /* if not whitespace */
count[(int)*s1]++; /* add 1 to index corresponding to char */
for (; *s2; s2++) /* loop over chars in string 2 */
if (!isspace(*s2)) /* if not whitespace */
count[(int)*s2]--; /* subtract 1 from index corresponding to char */
for (int i = 0; i < NCHARS; i++) /* loop over counting array */
if (count[i]) /* if any index non-zero, not anagram */
return 0;
return 1; /* all chars used same number of times -> anagram */
}
(NULL parameter checks omitted above, add for completeness)
To test you could use a simple main() that reads two strings and then checks the return from the function above. A return of 1 (true) means the words are anagrams, otherwise they are not anagrams. Simple press Enter alone on a line to quit.
int main (void) {
char str1[NCHARS * 4], str2[NCHARS * 4]; /* arrays for string 1 & string 2 */
for (;;) { /* loop continually */
fputs ("\nenter string 1: ", stdout);
if (!fgets (str1, sizeof str1, stdin) || *str1 == '\n') /* EOF or ENTER alone */
break;
fputs ("enter string 2: ", stdout);
if (!fgets (str2, sizeof str2, stdin) || *str2 == '\n') /* EOF or ENTER alone */
break;
printf ("\nwords %s an anagram\n", isanagram (str1, str2) ? "are" : "are not");
}
}
Example Use/Output
$ ./bin/anagram_count_array
enter string 1: anagram
enter string 2: nag a ram
words are an anagram
enter string 1: anagram
enter string 2: naag a ram
words are not an anagram
enter string 1: cat
enter string 2: tac
words are an anagram
enter string 1: cat
enter string 2: a t c
words are an anagram
enter string 1:
Look things over and let me know if you have questions.
As I understand your anagram is just the word with ordered other wany same letters.
#define NCHARS (127-31)
int *freq(const char *str)
{
int *freqTable = calloc(NCHARS, sizeof(freqTable)) ;
if(freqTable)
{
while(*str)
{
if( *str < ' ')
{
free(freqTable);
freqTable = NULL;
break;
}
freqTable[*str++ -' ']++;
}
}
return freqTable;
}
bool isAnagram(const char *str1, const char *str2)
{
int *freq1 = freq(str1), *freq2 = freq(str2);
bool result = false;
if(freq1 && freq2)
{
result = !memcmp(freq1, freq2, sizeof(*freq1) * NCHARS);
}
free(freq1); free(freq2);
return result;
}
int main(void)
{
printf("%d", isAnagram("bob", "obb"));
}
Related
I am trying to enter a word, and get how many times the letters were typed.
Say my input is "hello"
my output would be: h = 1, e = 1 l = 2 etc.
I am very close to getting it right, but I have a small issue with this code:
#include <stdio.h>
#include <string.h>
void find_frequency(char s[], int count[]) {
int c = 0;
while (s[c] != '\0') {
if (s[c] >= 'a' && s[c] <= 'z' )
count[s[c]-'a']++;
c++;
}
}
int main()
{
char string[100];
int c, count[26] = {0};
printf("Input a string\n");
gets(string);
find_frequency(string, count);
printf("Character Count\n");
for (c = 0 ; c < 26 ; c++)
if(count[c] > 0)
printf("%c : %d\n", c + 'a', count[c]);
return 0;
}
This code does half of the job, but not all.
It's output is in alphabetical order. How can i change it to give me an output of just the chararray that is input?
As Ry- suggested in this comment you could iterate back over the original string and use the chars as indices into your frequency table. Something like the following:
int len_string = strlen(string);
for (c=0; c<len_string; c++) {
char ch = string[c];
printf("%c: %d, ", ch, count[ch-'a']);
}
This won't completely match your expected output, since this code will output l: 2 twice, but that raises the question:
What is your expected output when you have a string like abba? a:2, b:2? a:1, b:2, a:1? a: 2, b:2, a:2? It's hard to help when you ask such an ambiguous question.
#include <stdio.h>
#include <string.h>
size_t ASCIIfreq[256];
void CountASCII(void *buff, size_t size)
{
unsigned char *charsptr = buff;
memset(ASCIIfreq, 0, sizeof(ASCIIfreq));
while(size--)
{
ASCIIfreq[*charsptr++]++;
}
}
void print(int printall)
{
for(size_t index = 0; index < 256; index++)
{
if(ASCIIfreq[index] || printall)
{
printf("The %03zu (0x%02zx) ASCII - '%c' has occured in the buffer %zu time%c\n",
index, index, (index > 32 && index < 127) ? (char)index : ' ',
ASCIIfreq[index], ASCIIfreq[index] == 1 ? ' ' : 's');
}
}
}
int main()
{
char teststring[] = "i am trying to enter a word, and get how many times the letters were typed. Say my input is \"hello\" my output would be: h = 1, e = 1 l = 2 etc.I am very close to getting it right, but i have a small issue with this code";
CountASCII(teststring, sizeof(teststring));
print(0);
return 0;
}
It's not clear what you mean by:
How can i change it to give me an output of just the chararray that is input?
Because that's exactly what you're doing in any case: Inputting a char array to the function; which is updated with numbers alphabetically; and later output as is.
So I'm guessing that you want to output the counts in the same order that each char was first encountered?
Solution
This will require a bit more work. You could keep a second array tracking the the order each character is encountered within find_frequency. But then that simple clean function starts doing too much.
So consider rather tweaking how you do the output:
void output_frequency(char s[], int count[]) {
int c = 0;
//loop s for the output
while (s[c] != '\0') {
if (s[c] >= 'a' && s[c] <= 'z' ) {
//found a character, report the count only if not reported before
if (count[s[c]-'a'] > 0) {
printf("%c : %d\n", s[c], count[s[c] - 'a']);
count[s[c]-'a'] = 0; //so you don't report this char again
}
}
c++;
}
}
If you are attempting to get an in-order count instead of a count in alphabetical order, you simply need to coordinate the indexes of your count array with the order of characters in your input buffer. To do that, simply loop over all characters in your input buffer and make a second pass counting the number of times the current character occurs. This will give you an in-order count of the number of times each character occurs, e.g.
#include <stdio.h>
#include <string.h>
#define COUNT 128
#define MAXC 1024
int main (void) {
char buf[MAXC] = ""; /* buffer to hold input */
int count[COUNT] = {0}; /* array holding inorder count */
fputs ("enter string: ", stdout); /* prompt for input */
if (!fgets (buf, MAXC, stdin)) { /* read line into buf & validate */
fputs ("error: EOF, no valid input.\n", stderr);
return 1;
}
/* loop over each character not '\n' */
for (int i = 0; buf[i] && buf[i] != '\n'; i++) {
char *p = buf; /* pointer to buf */
size_t off = 0; /* offset from start of buf */
while ((p = strchr (buf + off, buf[i]))) { /* find char buf[i] */
count[i]++; /* increment corresponding index in count */
off = p - buf + 1; /* offset is one past current char */
}
}
for (int i = 0; count[i]; i++) /* output inorder character count */
printf (i ? ", %c: %d" : "%c: %d", buf[i], count[i]);
putchar ('\n'); /* tidy up with new line */
return 0;
}
(note: strchr is used for convenience to simply find the next occurrence of the current character within the string and then off (offset) is used to start the search with the following character until no other matches in the string are found. You can simply use an additional loop over the characters in the buffer if you like.)
Example Use/Output
$ /bin/charcnt_inorder
enter string: hello
h: 1, e: 1, l: 2, l: 2, o: 1
However, this does recount each character and give the count again if the character is duplicated, (e.g. l: 2, l: 2 for each 'l'). Now it is unclear from:
"my output would be: h = 1, e = 1 l = 2 etc."
what you intended in that regard, but with just a little additional effort, you can use a separate index and a separate array to store the first instance of each character (in say a chars[] array) along with the count of each in your count[] array and preserve your inorder count while eliminating duplicate characters. The changes needed are shown below:
#include <stdio.h>
#include <string.h>
#define COUNT 128
#define MAXC 1024
int main (void) {
char buf[MAXC] = "",
chars[COUNT] = ""; /* array to hold inorder chars */
int count[COUNT] = {0};
size_t cdx = 0; /* add count index 'cdx' */
fputs ("enter string: ", stdout);
if (!fgets (buf, MAXC, stdin)) {
fputs ("error: EOF, no valid input.\n", stderr);
return 1;
}
for (int i = 0; buf[i] && buf[i] != '\n'; i++) {
char *p = buf;
size_t off = 0;
chars[cdx] = buf[i]; /* store in chars array */
if (i) { /* if past 1st char */
int n = i;
while (n--) /* simply check all before */
if (buf[n] == buf[i]) /* if matches current */
goto next; /* bail and get next char */
}
while ((p = strchr (buf + off, buf[i]))) {
count[cdx]++; /* increment count at index */
off = p - buf + 1;
}
cdx++; /* increment count index */
next:; /* goto label to jump to */
}
for (int i = 0; count[i]; i++)
printf (i ? ", %c: %d" : "%c: %d", chars[i], count[i]);
putchar ('\n');
return 0;
}
Example Use/Output
$ /bin/charcnt_inorder2
enter string: hello
h: 1, e: 1, l: 2, o: 1
or
$ ./bin/charcnt_inorder2
enter string: amarillo
a: 2, m: 1, r: 1, i: 1, l: 2, o: 1
Now your 'l' is only reported once with the correct count.
Note, in each example you should do additional validation to insure the entire input fit within your buffer, etc... The count (and chars) array were sized at 128 to cover the entire range of ASCII values. Don't skimp on buffer size. If you explicitly limit your input to UPPERcase or lowercase -- then you can limit your count size to 26, otherwise you need to consider the additional characters and punctuation that will be encountered. The same applies to your input buffer. If you anticipate you max input would be 500 chars, double it (generally to next available power of two, no real requirement for powers of two, but you are likely to see it that way).
Bottom line, I'd rather be 10,000 characters too long that one character too short... leading to Undefined Behavior.
Lastly, as mentioned in my comment never, never, never use gets. It is so insecure it has been removed from the C standard library in C11. Use fgets or POSIX getline instead.
Look things over and let me know if you have further questions.
This is for Homework
I have to create a program where I place an asterisk between every other character in a string. My program kind of works but it overwrites characters when the asterisk is just supposed to be placed between every other character and not after the last character. The issues in my code are in the stars function and the case w within the main. You can ignore the rest. I'll place the examples after my program. Thanks for any help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void merge(char *s1, char *s2, char *output)
{
while(*s1 != '\0' && *s2 != '\0')
{
*output++ = *s1++;
*output++ = *s2++;
*output='\0'; }
}
void stars(char *as1, char *as2, char *output2)
{
strcpy(output2, as1);
strcat(output2, as2);
for(int i =1; i < outasteriskput2[i]; i+=2) {
output2[i] = '*';
}
}
int main(int argc , char *argv[])
{
//int i = 3;
char string1[30];
char string2[30];
if (argc == 2) {
switch (argv[1][1]) {
case 'i':
//char string1[30];
//char string2[30];
printf("Please enter a string of maximum 30 characters: ");
scanf("%s" ,string1);
printf("Please enter a string of maximum 30 characters: ");
scanf("%s" ,string2);
char *output=malloc(strlen(string1)+strlen(string2)+1);
//allocate memory for both strings+1 for null
merge(string1,string2,output);
printf("%s\n",output);
break;
case 'w':
printf("Please enter a string of maximum 30 characters: ");
scanf("%s" ,string1);
printf("Please enter a string of maximum 30 characters: ");
scanf("%s" ,string2);
char *output2=malloc(strlen(string1)+strlen(string2));
//allocate memory for both strings+1 for null
stars(string1, string2, output2);
printf("%s\n",output2);
break;
}
}
return 0;
}
What my program does:
Enter String 1: abc
Enter String 2: 123
Output a*c*2*
What it should do:
Enter String 1: abc
Enter String 2: 123
Output a * b * c * 1 * 2 * 3
-> There shouldn't be any spaces I just separated it by spaces because the website would put the whole thing in italics
This solution is close to the original one:
void stars(char *as1, char *as2, char *output2)
{
char *buffer=malloc(strlen(as1)+strlen(as2)+1);
strcpy(buffer, as1);
strcat(buffer, as2);
int i, k = 0;
for (i=0; i < 2*strlen(buffer)-1; i++)
if (i%2){
output2[i] = '*';
} else {
output2[i] = buffer[k];
k++;
}
output2[i] = '\0';
}
It creates a large enough buffer to hold both input strings. At the same time, output2 is a char array of the size twice larger than as1 and as2 together, so that it can hold the * and the terminating character,
char *output2=malloc(2*(strlen(string1)+strlen(string2)));
The loop iterates through the output2 array and inserts a star at every odd index position i.e. when i%2 is not 0.0. It inserts the character from buffer when i%2 is zero while using a separate index k for the buffer array. It stops at i = 2*strlen(buffer)-1 to avoid placing a * past the last character from as2 and places the NULL character at the end of the resulting output2 array.
This question already has answers here:
How do I check if a number is a palindrome?
(53 answers)
Closed 5 years ago.
I am trying to check if an input number is a palindrome. I am doing it through strings rather than ints. So, I am taking in a string and reversing it into another string. However, when I use the string compare function it does not give me 0, stating that the strings are not the same. Even when I put in for example "1001", both the input and reverse strings displays 1001. I have figured it out with other methods but am trying to understand what is wrong with this one in specific.
#include <stdio.h>
#include <string.h>
int main(void)
{
char input[100];
char reverse[100];
int numLen = 0;
printf("Enter a number\n");
fgets(input, 100, stdin);
printf("The number is: %s\n", input);
numLen = strlen(input) - 1;
printf("Length of string is: %d\n", numLen);
for (int i = 0; i < numLen; i++)
{
reverse[i] = input[numLen - 1 - i];
if (i == numLen - 1)
{
reverse[i + 1] = '\0';
}
}
printf("The reverse number is: %s\n", reverse);
printf("The original number is: %s\n", input);
int result = strcmp(input, reverse);
printf("Result of strcmp gives us: %d\n", result);
if (strcmp(input, reverse) == 0)
{
printf("These numbers are palindromes\n");
}
else
{
printf("These numbers are not palindromes\n");
}
return 0;
}
The problem is you are not handling the strings properly. You should overwrite the '\n' with \0.
...
char input[100];
char reverse[100];
int numLen = 0;
printf("Enter a number\n");
fgets(input, 100, stdin);
printf("The number is: %s\n", input);
input[strcspn(input,"\n")]='\0'; // getting the length of the
// string without `\n`
// and overwriting with `\0`
numLen = strlen(input) ; // now you don't need to put the -1
printf("Length of string is: %d\n", numLen);
for (int i = 0; i < numLen; i++)
{
....
Apart from these two changes everything else remains the same. You were reversing it all right. And then you used strcmp right way. But the extra \n is removed in the code I have shown.
(still) Why it works?
Now to give you a better idea. You formed the reversed string alright. But the original string has \n within itself.
printf("The reverse number is: (%s)\n", reverse);
printf("The original number is: (%s)\n", input);
In the previous program you just do write these two lines. You will understand where you went wrong.
On giving input 1001Enter it gives this output.
The reverse number is: (1001)
The original number is: (1001
)
What is strcspn doing?
I have using strcspn function got the length without \n and overwriting it with \0.
0 1 2 3 4 5 --> indices
1 0 0 1 \n \0 --> strcspn(input,"\n") returns 4.
1 0 0 1 \0 \0 --> input[strcspn(input,"\n")]='\0'
You can do simply like this without the copying and everything.
Without extra memory - in place palindrome checking
bool checkPal(const char *s){
for(int i = 0, j= strlen(s)-1; i< strlen(s) && j>=0 ; i++)
if(s[i] != s[j])
return false;
return true;
}
int main(void)
{
char input[100];
char reverse[100];
printf("Enter a number\n");
if( fgets(input, 100, stdin) )
printf("The number is: %s\n", input);
input[strcspn(input,"\n")]='\0';
int numLen = strlen(input) ;
printf("Length of string is: %d \n", numLen);
printf("These numbers are %spalindromes\n", checkPal(input)?"not ":"");
return 0;
}
A more succinct way to write the checkPal() would be,
bool checkPal(const char *first){
const char *last = first + strlen(first);
while (first < last) {
if (*first++ != *--last) {
return false;
}
}
return true;
}
last points to the \0 character. Subtraction is necessary before we start doing comparison. To get a clear idea of what happens you have to know the precedence and few rules.
The first<last part is obvious. We are comparing till we reach a point where we first > last (For even length strings) or first = last (for odd length strings).
The if is a bit tricky. *first++ there are two operators involved. * (indirection) and ++(post increment).
And precedence of ++ is higher than de-reference *.
So *first++ will be - first is incremented. Then you might think that we are missing one character very first time but that's not the case. Value of a postfix expression is the value before we do first++. So now you have the first character.
Same way *--last will have the same effect except the value of the prefix expression is the value after the operation. So you are considering the last character.
If they matches we continue. first and last already contain the modified value. We repeat the same logic for rest of the characters in the smaller sub-string.
If a mismatch occurs then we return immediately. (Because it's not a palindrome).
Sorry, my bad. Try this:
#include <stdio.h>
#include <string.h>
// A function to check if a string str is palindrome
void isPalindrome(char str[])
{
// Start from leftmost and rightmost corners of str
int l = 0;
int h = strlen(str) - 1;
// Keep comparing characters while they are same
while (h > l)
{
if (str[l++] != str[h--])
{
printf("%s is Not Palindromen", str);
return;
}
}
printf("%s is palindromen", str);
}
// Driver program to test above function
int main()
{
isPalindrome("abba");
isPalindrome("abbccbba");
isPalindrome("geeks");
return 0;
}
Does this one work?
A variant, recursive version that has no more that the string as argument (or a copy of the original string)
int pal(char *s) {
int n = strlen(s);
if (n <= 1) return 1;
if (s[0] != s[n-1]) return 0;
s[n-1] = '\0';
return pal(++s);
}
return 0: not a palindrome, 1: is a palindrome
Note the string is altered, so you can call it this way if it's a problem (or if the string is created in a static area)
char *copy = malloc(strlen(string)+1); // string is original string
strcpy(copy, string);
int ispal = pal( copy );
printf("Is %s a palindrome\n", ispal ? "":"not");
Here is a program with Strings where I am trying
Pig Latin translation is simply taking the first letter of a “word” and appending that letter to the end of the word with “ay” added to the end as well
I have issue with m1=m2+3 ( resetting the Initial Marker ).
Input that I am giving : "Alex, how are you right"
The output I am expecting is : lexay, owhay reay ouyay ightray
But
I am getting this : lex,Aay way ay ayo gayi
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void initialize(char english[], char piglatin[]);
void readinput (char english[]);
int countwords(char english[]);
void convert ( int words, char english[], char piglatin[]);
void writeoutput( char piglatin[]);
int main()
{
char english[80], piglatin[80];
int words;
initialize(english, piglatin);
printf("enter the string\t");
fflush(stdin);
gets(english);
printf ("\nInput buffer contents: %s\n", english);
words = countwords(english);
convert(words,english,piglatin);
writeoutput(piglatin);
printf ("Have a nice day\n");
}
void initialize(char english[], char piglatin[])
{
int count;
for(count =0; count<80;++count)
{
english[count]=piglatin[count]=' ';
}
return;
}
/* Scan the english test and determine the number of words */
int countwords(char english[])
{
int count, words =1;
for ( count =0;count <79;++count)
{
if(english[count]==' ' && english[count+1]!=' ')
++words;
}
printf("%d\n",words);
return (words);
}
/* convert each words in to piglatin*/
void convert ( int words, char english[], char piglatin[])
{
int n, count;
int m1=0;
int m2;
/* convert each word */
for ( n=1;n<=words;++n)
{
/* locate the end of the current word*/
count = m1;
printf ("\ before conversion word contents: %d\n", count);
while ( english[count]!=' ')
{
m2=count++;
}
printf ("\ before conversion word contents: %d\n", m2);
/* transpose the first letter and add 'a', 'y'*/
for (count =m1;count<m2;++count)
{
piglatin[count+(n-1)]=english[count+1];
}
piglatin[m2+(n-1)] = english[m1];
piglatin[m2+1] = 'a';
piglatin[m2+2] = 'y';
m1=m2+3;
printf ("\ Converted word contents: %s\n", piglatin);
}
return;
}
void writeoutput( char piglatin[])
{
int count =0;
for (count =0; count <80; ++count)
{
putchar(piglatin[count]);
}
printf ("\n");
return;
}
I see various problems here:
Alex -> lex,Aay: You should check for punctuation marks when determining the end of the words, thus inserting the Aay part before the comma character
Alex -> lex,Aay: Every character from the start of a word should be converted to lowercase and the resulting first character should be converted to upper case respectively
Now the conversion function: I have changed it a bit to get you started; it should work now ( at least it does with your test string ) without taking 1 and 2 into account though
void convert(int words, char english[], char piglatin[])
{
int estart = 0;
int ppos = 0;
int m2;
for (int n = 0; n < words; n++)
{
//locate the start of the current word, to make
//sure something like this is converted:
//"Alex, how are you"
while (english[estart] == ' ')
{
//make sure we do not exceed the strings boundaries!
if (english[estart] == '\0')
{
return;
}
estart++;
}
//locate the end of the word
int eend = estart;
while (english[eend] != ' ')
{
//never forget to check for the end of the string
if (english[eend] == '\0')
{
break;
}
eend++;
}
/* transpose the first letter and add 'a', 'y'*/
for (int i = estart+1; i < eend; i++, ppos++)
{
piglatin[ppos] = english[i];
}
piglatin[ppos++] = english[estart];
piglatin[ppos++] = 'a';
piglatin[ppos++] = 'y';
//dont forget to add a whitespace or your string might behave
//very stangely!
piglatin[ppos++] = ' ';
estart = eend;
printf("\ Converted word contents: %s\n", piglatin);
}
}
I hope this gets you started in the right direction.
Please also check your array sizes for english and piglatin. The string for piglatin is alway longer than the english one but your array sizes are the same! Also i would advise you add some boundary checks to make sure you do not leave the array boundaries.
So, we were given this program in class. "Write a Program in C to count the number of words in a sentence input by the user."
This is what i could come up with, but the number of words is always one less than what is the correct number. My teacher told everyone to just add 1 to the word count before printing it. I think it has a bug, if we don't enter any words, i.e. , press Enter instead of typing,the program suggested by my teacher would still give word count as 1 not 0. Do you know of any way to get proper word count without just adding 1 at the end?
Code:
My code(giving 1 less than correct) :
#include <stdio.h>
#include <string.h>
void main()
{
char s[200];
int count = 0, i;
printf("enter the string\n");
gets(s);
for (i = 0;i<strlen(s);i++)
{
if (s[i] == ' ')
count++;
}
printf("number of words in given string are: %d\n", count);
}
It's just that you're counting spaces, this would also be incorrect if the user ended the string with a bunch of spaces. Try something like this:
#include <stdio.h>
#include <string.h>
void main()
{
char s[200];
int count = 0, i;
int foundLetter = False;
printf("enter the string\n");
gets(s);
for (i = 0;i<strlen(s);i++)
{
if (s[i] == ' ')
foundLetter = False;
else
{
if (foundLetter == False)
count++;
foundLetter = True;
}
}
printf("number of words in given string are: %d\n", count);
}
As other users have commented, your program is susceptible to many other issues depending on the string inputed. The example I have posted assumes that anything that is not a space is a letter and if you find at least one letter, than that's a word. Instead of boolean values you could use a counter to make sure that the word is at least a certain length. You could also check to see that it is not a number or symbol by either writing your own regex function or using an existing one. As others have said there is a lot more you can do with this program, but I've provided an example to point you in the right direction.
You are counting the amount of non-words, but you should be counting the amount of words.
If a word is defined as a sequence of one or more letters, your code might go as:
for every character in the string
if the character is part of a word ( "the car's wheel" is three words )
increase the word count
while the character is part of a word, increment your pointer
One improvement would be to handle lines that contain multiple spaces between words or tabs, while still considering a simple return '\n' as a word. Using getline provides a number of advantages including providing the number of characters read. Here is an example of the approach:
Edit logic simplified:
#include <stdio.h>
int main (void) {
char *line = NULL; /* pointer to use with getline () */
char *p = NULL; /* pointer to parse getline return */
ssize_t read = 0;
size_t n = 0;
int spaces = 0; /* counter for spaces and newlines */
int total = 0; /* counter for total words read */
printf ("\nEnter a line of text (or ctrl+d to quit)\n\n");
while (printf (" input: ") && (read = getline (&line, &n, stdin)) != -1) {
spaces = 0;
p = line;
if (read > 1) { /* read = 1 covers '\n' case (blank line with [enter]) */
while (*p) { /* for each character in line */
if (*p == '\t' || *p == ' ') { /* if space, */
while (*p == '\t' || *p == ' ') /* read all spaces */
p++;
spaces += 1; /* consider sequence of spaces 1 */
} else
p++; /* if not space, increment pointer */
}
}
total += spaces + 1; /* words in line = spaces + 1 */
printf (" chars read: %2zd, spaces: %2d total: %3d line: %s\n",
read, spaces, total, (read > 1) ? line : "[enter]\n");
}
printf ("\n\n Total words read: %d\n\n", total);
return 0;
}
output:
Enter a line of text (or ctrl+d to quit)
input: my
chars read: 3, spaces: 0 total: 1 line: my
input: dog has
chars read: 8, spaces: 1 total: 3 line: dog has
input: fleas and ticks
chars read: 17, spaces: 2 total: 6 line: fleas and ticks
input:
chars read: 1, spaces: 0 total: 7 line: [enter]
input:
chars read: 1, spaces: 0 total: 8 line: [enter]
input: total_words 10
chars read: 17, spaces: 1 total: 10 line: total_words 10
input:
Total words read: 10
//input should be alphanumeric sentences only
#include <bits/stdc++.h>
using namespace std;
int main()
{
freopen("count_words_input.txt","r",stdin); // input file
char c;
long long i,wcount=0,f=0;
i=0;
while(scanf("%c",&c) == 1)
{
if(c == ' ' || c == '\n' || c == '\t' || c == '.')
f=0;
else if(f == 0)
{
wcount++;
f=1;
}
}
printf("%lld\n",wcount);
return 0;
}