Can anyone help me to make that project.
Write a program that calculates statistics on word length for a sentence. The sentence isterminated by a ’.’ For each found length of a word the number of words of that length
is printed. Only those lengths that are found in the input are printed. Only letters from
a-z or A-Z are allowed to form words. Words are separated by a space. No punctuation
characters other than ’.’ are allowed. If any other input character is recognized or the
input is longer than 80 characters the program displays ”NOT VALID” (see Hints). Note,
that in the case that no word is present in the input, nothing is printed.
% u6_stats
Enter a sentence: Bolt was expected to use the super bark.
Length 2: 1
Length 3: 3
Length 4: 2
Length 5: 1
Length 8: 1
% u6_stats
Enter a sentence: Something wasn’t right.
NOT VALID
#include <stdio.h>
#include <conio.h>
void main() {
char s[100];
int numOfWords, lengthOfWord = 0;
int i = 0, j = 0;
printf("Enter the text : ");
fgets(s, sizeof(s), stdin);
numOfWords = 1;
while(s[i]!='\0') {
if(s[i] == ' ')
numOfWords++;
i++;
}
//printf("%d", numOfWords);
i = 0;
int help[numOfWords];
int l;
for(l = 0; l < numOfWords ; l++)
help[l] = 0;
while(s[i]!='\0') {
if(s[i] != ' ' && s[i] !='\n' && s[i]!='.' ) {
lengthOfWord++;
i++;
}else{
help[j] = lengthOfWord;
j++;
lengthOfWord = 0;
i++;
}
}
int repeat[80];
for(l = 0; l < 80 ; l++)
repeat[l] = 1;
int num = 1;
i=0,l=0;
for(i = 0;i<numOfWords;i++) {
for(l=i+1;l<numOfWords;l++)
if(help[i]==help[l]) {
repeat[l]='\0';
num++;
repeat[i] = num;
}
num = 1;
}
l=0;
for (l=0; l<numOfWords; l++)
if (repeat[l]!='\0' && help[--l]!=help[++l])
printf("Length %d: %d\n", help[l],repeat[l]);
}
So, the problem is that if i inpute a text like"abc abcd abc abc"
the result will be like "length 3: 3 length 4: 1 length 3: 2".
So when the program already compared 1st (here 3) element with otheres, this element will not be comparing again, but i have the 3d element with same length, and it that case, the program compare it with remained elements and print 2. How can i rework my code, if i dont wont to compare already compared elements.
Second problem is that i need to get results from lowest length till highst.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void invalid(void){
puts("NOT VALID");
exit(EXIT_FAILURE);
}
int main(void){
int length[80]={0};
int i, ch, word_len=0;
printf("Enter a sentence: ");
while(1){
ch=getchar();
if(isalpha(ch)){
++word_len;
} else if(ch == ' ' || ch == '.'){
if(word_len>80)
invalid();
if(word_len)
length[word_len-1]++;//-1: to 0 origin
if(ch == '.')
break;
word_len = 0;
} else {
invalid();
}
}
for(i=0;i<sizeof(length)/sizeof(*length);++i){
if(length[i])
printf("Length %d: %d\n", i+1, length[i]);
}
return 0;
}
A simple approach is with strtok (http://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm).
#include <stdio.h>
int numwords (char *str);
int main() {
char word[] = "This is a test - does it pass?";
int c = numwords(word);
printf("Words = %d\n", c);
return 0;
}
int numwords(char *str)
{
int n = 0;
for(str=strtok(str, " -.!,;"); str; str=strtok(NULL, " -.!,;"))
n++;
return n;
}
Related
So I have an assignment where I should delete a character if it has duplicates in a string. Right now it does that but also prints out trash values at the end. Im not sure why it does that, so any help would be nice.
Also im not sure how I should print out the length of the new string.
This is my main.c file:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int main() {
char string[256];
int length;
printf("Enter char array size of string(counting with backslash 0): \n");
/*
Example: The word aabc will get a size of 5.
a = 0
a = 1
b = 2
c = 3
/0 = 4
Total 5 slots to allocate */
scanf("%d", &length);
printf("Enter string you wish to remove duplicates from: \n");
for (int i = 0; i < length; i++)
{
scanf("%c", &string[i]);
}
deleteDuplicates(string, length);
//String output after removing duplicates. Prints out trash values!
for (int i = 0; i < length; i++) {
printf("%c", string[i]);
}
//Length of new string. The length is also wrong!
printf("\tLength: %d\n", length);
printf("\n\n");
getchar();
return 0;
}
The output from the printf("%c", string[i]); prints out trash values at the end of the string which is not correct.
The deleteDuplicates function looks like this in the functions.c file:
void deleteDuplicates(char string[], int length)
{
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length;)
{
if (string[j] == string[i])
{
for (int k = j; k < length; k++)
{
string[k] = string[k + 1];
}
length--;
}
else
{
j++;
}
}
}
}
There is a more efficent and secure way to do the exercise:
#include <stdio.h>
#include <string.h>
void deleteDuplicates(char string[], int *length)
{
int p = 1; //current
int f = 0; //flag found
for (int i = 1; i < *length; i++)
{
f = 0;
for (int j = 0; j < i; j++)
{
if (string[j] == string[i])
{
f = 1;
break;
}
}
if (!f)
string[p++] = string[i];
}
string[p] = '\0';
*length = p;
}
int main() {
char aux[100] = "asdñkzzcvjhasdkljjh";
int l = strlen(aux);
deleteDuplicates(aux, &l);
printf("result: %s -> %d", aux, l);
}
You can see the results here:
http://codepad.org/wECjIonL
Or even a more refined way can be found here:
http://codepad.org/BXksElIG
Functions in C are pass by value by default, not pass by reference. So your deleteDuplicates function is not modifying the length in your main function. If you modify your function to pass by reference, your length will be modified.
Here's an example using your code.
The function call would be:
deleteDuplicates(string, &length);
The function would be:
void deleteDuplicates(char string[], int *length)
{
for (int i = 0; i < *length; i++)
{
for (int j = i + 1; j < *length;)
{
if (string[j] == string[i])
{
for (int k = j; k < *length; k++)
{
string[k] = string[k + 1];
}
*length--;
}
else
{
j++;
}
}
}
}
You can achieve an O(n) solution by hashing the characters in an array.
However, the other answers posted will help you solve your current problem in your code. I decided to show you a more efficient way to do this.
You can create a hash array like this:
int hashing[256] = {0};
Which sets all the values to be 0 in the array. Then you can check if the slot has a 0, which means that the character has not been visited. Everytime 0 is found, add the character to the string, and mark that slot as 1. This guarantees that no duplicate characters can be added, as they are only added if a 0 is found.
This is a common algorithm that is used everywhere, and it will help make your code more efficient.
Also it is better to use fgets for reading input from user, instead of scanf().
Here is some modified code I wrote a while ago which shows this idea of hashing:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NUMCHAR 256
char *remove_dups(char *string);
int main(void) {
char string[NUMCHAR], temp;
char *result;
size_t len, i;
int ch;
printf("Enter char array size of string(counting with backslash 0): \n");
if (scanf("%zu", &len) != 1) {
printf("invalid length entered\n");
exit(EXIT_FAILURE);
}
ch = getchar();
while (ch != '\n' && ch != EOF);
if (len >= NUMCHAR) {
printf("Length specified is longer than buffer size of %d\n", NUMCHAR);
exit(EXIT_FAILURE);
}
printf("Enter string you wish to remove duplicates from: \n");
for (i = 0; i < len; i++) {
if (scanf("%c", &temp) != 1) {
printf("invalid character entered\n");
exit(EXIT_FAILURE);
}
if (isspace(temp)) {
break;
}
string[i] = temp;
}
string[i] = '\0';
printf("Original string: %s Length: %zu\n", string, strlen(string));
result = remove_dups(string);
printf("Duplicates removed: %s Length: %zu\n", result, strlen(result));
return 0;
}
char *remove_dups(char *str) {
int hash[NUMCHAR] = {0};
size_t count = 0, i;
char temp;
for (i = 0; str[i]; i++) {
temp = str[i];
if (hash[(unsigned char)temp] == 0) {
hash[(unsigned char)temp] = 1;
str[count++] = str[i];
}
}
str[count] = '\0';
return str;
}
Example input:
Enter char array size of string(counting with backslash 0):
20
Enter string you wish to remove duplicates from:
hellotherefriend
Output:
Original string: hellotherefriend Length: 16
Duplicates removed: helotrfind Length: 10
My code is printing the frequency of characters in random order. What can be done so that it prints the frequency of characters in order in which the word is given. My current code is as follows
#include <stdio.h>
#include <conio.h>
void main() {
char string1[50];
int i = 0, counter[26] = { 0 };
printf("\nEnter a string\n");
//Inputs a string
gets(string1);
while (string1[i] != '\0') {
//checks and includes all the characters
if (string1[i] >= 'a' && string1[i] <= 'z') {
//counts the frequency of characters
counter[string1[i] - 'a']++;
i++;
}
}
//printing frequency of each character
for (i = 0; i < 26; i++) {
if (counter[i] != 0)
printf("%c occurs %d times.\n", i + 'a', counter[i]);
}
getch();
}
sample output:
There are several issues in your code:
you use gets: this function is unsafe, it was removed from the current version of the C Standard.
you increment i only for if string1[i] is a lowercase letter: you will run an infinite loop if you type any other character.
the proper prototype for main is either int main(void) or int main(int arc, char *argv[]).
you only count lower case letters. H is upper case, thus not counted.
Here is an improved version:
#include <stdio.h>
#include <ctype.h>
int main(void) {
char string1[128];
int i = 0, counter[256] = { 0 };
printf("\nEnter a string\n");
//Inputs a string
if (fgets(string1, sizeof string1, stdin) == NULL) {
// empty file: got an empty line
*string1 = '\0';
}
for (i = 0; string1[i] != '\0'; i++) {
if (isalpha((unsigned char)string1[i])) {
//counts the frequency of letters
counter[string1[i]]++;
}
}
//printing frequency of each counted character
//characters are printed in the order of appearance
for (i = 0; string1[i] != '\0'; i++) {
if (counter[string1[i]] != 0) {
printf("%c occurs %d times.\n",
string1[i], counter[string1[i]]);
counter[string1[i]] = 0; // print each letter once.
}
}
getch();
return 0;
}
You can get the characters printed in order of their appearance by using the string a second time to generate the output.
In your section where you are "printing the frequency of each character", use the code to process the input string. This time, if the frequency value is not zero, print it and then reset the frequency value to zero. If the frequency value is zero, you must have already printed it so do nothing.
//printing frequency of each counted character (in input order)
for (i = 0; string1[i] != '\0'; i++) {
char ch = string[i];
if (counter[ch - 'a'] != 0) {
printf("%c occurs %d times.\n", ch, counter[ch - 'a']);
counter[ch - 'a'] = 0;
}
}
For example, the user shall put the input like that, "ABC123," but not "ABC 123" or "A BC123."
Here is my code:
unsigned int convert_to_num(char * string) {
unsigned result = 0;
char ch;
//printf("check this one %s\n", string);
while(ch =*string++) result = result * 26 + ch - 'A' + 1;
return result;
}
int main()
{
char input_string[100];
char arr_col[100] = {'\0'};
char arr_row[100] = {'\0'};
int raiseflag;
int started_w_alpha =0;
int digitflag = 0;
while(scanf("%s", &input_string) != EOF) {
int i = 0, j = 0, digarr = 0;
while (i <=5) {
if (input_string[i] == '\0') {printf("space found!");}
if ((input_string[i] >= 'A' && input_string[i] <= 'Z') && (digitflag == 0)) {
started_w_alpha = 1;
arr_col[j] = input_string[i]; j++;
}
//printf("something wrong here %s and %d and j %d\n", arr_holder, i, j);
if (started_w_alpha == 1) {
if (input_string[i] >=48 && input_string[i]<=57){ digitflag = 1; arr_row[digarr] =input_string[i]; digarr++; }
}
i++; if (i == 5) { raiseflag =1; }
}
printf(" => [%d,%s]\n", convert_to_num(arr_col), arr_row);
if (raiseflag == 1) { raiseflag = 0; memset(arr_col, 0, 5); memset(input_string, 0, 5); memset(arr_row, 0, 5); digitflag = 0; started_w_alpha = 0; }
}
return 0;
}
Apparently, \0 doesn't work in my case because I have an array of 5 and user can put 2 chars. I want to exit the loop whenever a space is found in between the characters.
This is the whole code. I added {'\0'} my array because of the extra characters I get when there is less than 5 characters.
Thanks!
Since the index is starting from 0 and input_string[5]; array size is 5, the only valid indexes are from 0 to 4.
but your loop while (i <=5) { go till 5, it is mean you exceed the array.
If you insert 5 characters to the string, the terminating null is the 6th.
Since you exceed the array it written over some other variable. but you still can find it when you check input_string[5]
So if you want to insert 5 characters you array size should be at least 6
char input_string[6];
if you want to check only the first 5 elements you'll have to change the loop to:
while (i < 5) {
and as I wrote in the comment if you find the terminating null, no use to continue the loop, since it contain garbage or leftover from the previous iteration.
Therefor you should break if it found, like this:
if (input_string[i] == '\0') {printf("space found!"); break;}
EDIT
check this program: it use fgets to read the whole input, then search for white spaces.
Note it doesn't trim the input, means it won't remove spaces when thay appear at the beginning or at the end of the input.
#include <ctype.h>
#include <string.h>
#include <stdio.h>
int main()
{
int i ,size;
char input_string[100];
fgets(input_string,100,stdin);
i=0;
size = strlen(input_string);
while (i<size-1){ //enter is also count
if (isspace(input_string[i]))
{
printf("space found!");
break;
}
i++;
}
return 0;
}
EDIT2
Now with a trim, so it will remove leading and ending spaces:
#include <ctype.h>
#include <string.h>
#include <stdio.h>
char* trim(char *input_string)
{
int i=0;
char *retVal = input_string;
i = strlen(input_string)-1;
while( i>=0 && isspace(input_string[i]) ){
input_string[i] = 0;
i--;
}
i=0;
while(*retVal && isspace(retVal[0]) ){
retVal ++;
}
return retVal;
}
int main()
{
int i ,size;
char input_string[100],*ptr;
fgets(input_string,100,stdin);
ptr = trim(input_string);
i=0;
size = strlen(ptr);
while (i<size){
if (isspace(ptr[i]))
{
printf("space found!");
break;
}
i++;
}
return 0;
}
I am trying to add a space to each space until column = 0. I am not sure how to do this.
The problem is the following. If you look at a newspaper you will see that the writing is justified to fit into the columns. Write a program
that reads in the width of the columns in a newspaper and then a line of text. Justify the line of text to fit into
a column of that width. When your program is running, the screen should look something like this:
Enter the width of the column: 40
Enter a line of text: Good morning how are you?
12345678901234567890123456789012345678901234567890...
Good morning how are you?
The justification is done by counting the number of gaps in the text. In the above example, there are 4 gaps. Then each gap must have spaces added to it. The number of extra spaces must be shared out as evenly as possible. In the above example, the first three gaps have 5 spaces each and the last gap has 4 spaces.
Notes:
If the text is longer than the column then you must report an error – don't try and break it into two lines!
Assume that the text will have more than one word in it.
Note the header line consisting of 123456789012345678.... this is useful to check your result.
You can make this header line as long as you like – 70 spaces would be a useful length.
Thanks
#include <stdio.h>
int clear_input_buffer(void);
int column;
int c;
int g;
int e;
int space;
int length;
char line[40];
int main(){
g = 0;
printf("enter width of column\n");
scanf("%d", &column);
printf("enter line of text\n");
clear_input_buffer();
gets(line);
c = 0;
while(c <= column){
if(g <= 9)
{
printf("%d", g);
g = g + 1;
c = c + 1;
}
else
{
g = 0;
printf("%d", g);
g = g + 1;
c = c + 1;
}
}
printf("\n%s", line);
space = 0;
length = 0;
for( e = 0; line[e] != '\0'; e++ )
{
length = length + 1;
if( line[e] == ' ' )
space = space + 1;
}
column = column - length;
for( e = 0; line[e] != '\0'; e++ )
{
if((line[e] == ' ') && (column > 0))
{
add space to here
column = column - 1;
}
}
printf("%d\n", space);
printf("%d", length);
printf("%s", line);
}
int clear_input_buffer(void) {
int ch;
while (((ch = getchar()) != EOF) && (ch != '\n')) /* void */;
return ch;
}
This is what i made. It's far from ideal, but you get the point.
You just need to put in conditions, like when the string entered is larger or equal than 40 chars, to skip the procedure.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void)
{
int i = 0; // first just initialiaze stuff
char ch[40]; // memset the arrays, get the string
memset(ch, '\0', 40);
gets(ch);
int diff = 40 - strlen(ch);
int spaces = 0;
while(i<strlen(ch))
{
if(*(ch + i++) == ' ') // count the number of words/spaces between words
spaces++;
}
char finalt[40];
memset(finalt, '\0', 40);
i = 0;
diff /= spaces; // diff is the number of spaces to be added between every word
i = 0;
int j = 0; // j is for the finalt array
int k = 0; // k counts through the while, to put in spaces
printf("%d\n", diff);
while(i<40) // just squeeze in the spaces
{
if(ch[i] == ' ') {while(k<diff){ finalt[j++] = ' '; k++;} k = 0;}
else {finalt[j] = ch[i]; j++;}
i++;
}
printf("%s\n", finalt); // print the result
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WIDTH 70
#define _(x) #x
#define str(x) _(x)
void ruler_print(int n){
char ruler[] = "1234567890";
while(n>9){
printf(ruler);
n -= 10;
}
ruler[n] = '\0';
printf("%s\n", ruler);
}
int count_word(const char *text, size_t *count_char){
int i;
char *wk, *p;
p=wk=strdup(text);
*count_char=0;
for(i=0;p=strtok(p, " ");++i,p=NULL){
*count_char+=strlen(p);
}
free(wk);
return i;
}
int main(void){
int column, len, word_count;
int i, spaces, between, remain;
size_t count_char;
char text[WIDTH + 1];
char *p = text;
printf("Enter the width of the column: ");scanf("%d%*c", &column);
printf("Enter a line of text: ");scanf("%" str(WIDTH) "[^\n]", text);
len=strlen(text);
if(len > column || len > WIDTH){
fprintf(stderr, "too long text!\n");
return -1;
}
ruler_print(WIDTH);
word_count = count_word(text, &count_char);
spaces = column - count_char;
between = spaces / (word_count -1);
remain = spaces - (word_count -1)*between;
strtok(text, " ");
for(i=0;i<word_count-1;++i){
printf("%s%*s", p, between + (remain ? 1 : 0), " ");
if(remain) --remain;
p=strtok(NULL, " ");
}
printf("%s\n", p);
return 0;
}
I'm trying to determine if a phrase is a palindrome (a word that is the same from left to rigth) or not but i can't make it work. What's wrong?, i can't use pointers or recursion or string type variables
#include <stdio.h>
#include <string.h>
int main()
{
int i,j = 0,length;
char space = ' ';
char phrase [80],phrase2[80],phrase3[80];
printf("Give me the phrase: ");
gets(phrase);
length = strlen(phrase);
for(i =0; i <= length - 1; i++)
{
if(phrase[i] != space) //Makes the phrase without spaces
{
phrase2[i] = phrase[i];
j++;
}
}
for(i = length -1; i >= 0;i--)
{
if(phrase[i] != space) //Makes the phrase backwards an without spaces
{
phrase3[j] = phrase[i];
j++;
}
}
length = strlen(phrase2);
for(i =0; i <= length -1;i++) //Compare the phrases to know if they are the same
{
if(phrase2[i] != phrase3[i])
{
printf("It's not a palindrome\n");
return 0;
}
}
printf("It's a palindrome\n");
return 0;
}
Try this:
for(i =0, j=0; i <= length - 1; i++)
{
if(phrase[i] != space) //Makes the phrase without spaces
{
phrase2[j] = phrase[i];
j++;
}
}
for(i = length -1, j = 0; i >= 0;i--)
{
if(phrase[i] != space) //Makes the phrase backwards an without spaces
{
phrase3[j] = phrase[i];
j++;
}
}
length = j;
Update
In response to Praetorian's post here's the code to do it without copying the string.
#include <stdio.h>
#include <string.h>
int main()
{
int i, j, length;
char space = ' ';
char phrase[80];
printf("Give me the phrase: ");
gets(phrase);
length = strlen(phrase);
for( i = 0, j = length - 1; i < j; i++, j-- ) {
while (phrase[i] == space) i++;
while (phrase[j] == space) j--;
if( phrase[i] != phrase[j] ) {
printf("It's not a palindrome\n");
return 0;
}
}
printf("It's a palindrome\n");
return 0;
}
Before the 2nd loop you want to set j=0. It should work after that.
PS: If you debugged by printing out your three strings, you would've figured it out in a matter of minutes. When you don't know what goes wrong, print out the values of variables at intermediate steps, so you know where your problem occurs and what it is.
Your question has already been answered by others but I'm posting this code to show that it is not necessary to make the phrase3 copy to hold the reversed string.
#include <stdio.h>
#include <string.h>
int main()
{
int i, j, length, halfLength;
char space = ' ';
char phrase1[80], phrase2[80];
printf("Give me the phrase: ");
gets(phrase1);
length = strlen(phrase1);
for( i = 0, j = 0; i <= length; ++i ) {
if( phrase1[i] != space ) { //Makes the phrase1 without spaces
phrase2[j++] = phrase1[i];
}
}
length = strlen(phrase2);
halfLength = length / 2;
for( i = 0, j = length - 1; i < halfLength; ++i, --j ) {
if( phrase2[i] != phrase2[j] ) {
printf("It's not a palindrome\n");
return 0;
}
}
printf("It's a palindrome\n");
return 0;
}
This is what I came up with:
#include <stdio.h>
void main() {
char a[50],b[50];
int i=0,j,ele,test=0,x;
while((a[i]=getchar())!='\n') {
if(a[i]!=' ' && a[i]!=',') //do not read whitespaces and commas(for palindromes like "Ah, Satan sees Natasha")
i++;
}
a[i]='\0';
ele=strlen(a);
// Convert string to lower case (like reverse of Ava is avA and they're not equal)
for(i=0; i<ele; i++)
if(a[i]>='A'&&a[i]<='Z')
a[i] = a[i]+('a'-'A');
x = ele-1;
for(j=0; j<ele; j++) {
b[j] = a[x];
x--;
}
for(i=0; i<ele; i++)
if(a[i]==b[i])
test++;
if(test==ele)
printf("You entered a palindrome!");
else
printf("That's not a palindrome!");
}
Probably not the best way for palindromes, but I'm proud I made this on my own took me 1 hour :( lol
Why not use a std::stack? You will need two loops, each iterating the length of the input string. In the first loop, go through the input string once, pushing each character ont the stack. In the second loop, pop a character off the stack and compare it with the character at the index. If you get a mismatch before the loop ends, you don't have a palindrome. The nice thing with this is that you don't have to worry about the even/odd length corner-case. It will just work.
(If you are so inclined, you can use one stack (LIFO) and one queue (FIFO) but that doesn't substantially change the algorithm).
Here's the implementation:
bool palindrome(const char *s)
{
std::stack<char> p; // be sure to #include <stack>
for(int i = 0; s[i] != 0; i++)
p.push(s[i]);
for(int i = 0; s[i] != 0; i++)
{
if(p.top() != s[i])
return false; // not a palindrome!
p.pop();
}
return true;
}
Skipping spaces is left as an exercise to the reader ;)