Trouble finding end of string - c

Uni project below.
In the // ### section I have added a check for whether an additional space is needed to make sure the last character lines up at the end.
However, the check is there to find the end of string, but it appears to be stopping at the first space..
Output
Enter the width of the column : 40
Enter a line a text : the black cat
* * * *** Num = 4
1234567890123456789012345678901234567890
the black cat
Am I missing something and am actually ending the string early? Or is my check flawed?
/*
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:
1. If the text is longer than the column then you must report an error – don't try and break it into two lines!
2. Assume that the text will have more than one word in it.
3. 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.
*/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int width, length, difference, n, x, b;
int num, i, spaces, words, requiredSpaces;
char sentence[100];
char temp[100];
int main () {
// reads in column width
printf ("Enter the width of the column : ");
scanf ("%d", &width);
getchar(); // used to remove Enter from the gets below
// reads in the string
while (true) {
printf("Enter a line a text : ");
gets(sentence);
length = strlen(sentence);
if (length > width) {
printf ("Error, please enter a line of text shorter than the column width\n");
} else {
break;
}
}
// calculates the difference between width and length
difference = width - length;
// printf ("length is %d\ndifference is %d\n", length, difference);
// count how many words
spaces = 0;
for (i = 0; i < length; i++) {
if (sentence[i] == ' ') {
spaces++;
}
}
words = spaces + 1;
// printf ("spaces %d\nwords %d\n", spaces, words);
// calculates the required spaces between each word
requiredSpaces = difference / spaces;
// printf ("Required spaces %d\n", requiredSpaces);
i = 0;
n = 0;
for (x = 0; x < words; x++) {
while (sentence[i] != ' ') {
if (sentence[i] == '\0') {
break;
} else {
temp[n] = sentence[i];
i++;
n++;
}
}
i++;
n++;
for (b = 0; b < requiredSpaces; b++) {
temp[n] = ' ';
n++;
}
}
n++;
temp[n] = '\0';
printf ("")
// ###################################################################################################################
// if an odd number of elements in the string, this will add one space to the first space gap
if (length % 2 == 1) {
// counts the number of the elements in the array
i = 0;
while (temp[i] != '\0') {
i++;
printf("* ");
}
i++; // this makes sure that the \0 is also moved up one
num = i;
}
printf (" *** Num = %d\n\n", num);
// ###################################################################################################################
i = 0;
printf ("1234567890123456789012345678901234567890\n");
while (i < width) {
printf ("%c", temp[i]);
i++;
}
return 0;
}

With this line
// calculates the difference between width and length
difference = width - length;
you seem to forget that length already includes a number of spaces.
With this line
// calculates the required spaces between each word
requiredSpaces = difference / spaces;
you seem to forget that some rounding may occur. You cant just add the same number of spaces after each word.
You have to calculate exactly how many spaces you need. Something like
spaces_needed = width - length + words - 1; // + words - 1 because that is the
// number of spaces already in the string
Then you need to distribute that number of spaces into words-1 holes. Not necessarily the same number of spaces in each.
For instance with 3 words and length equal 13 you'll need a total of 29 spaces (40 - 13 + 3 - 1). You only have two holes so you must place 15 in one and 14 in the other.
tip
When you have the spaces_needed you do
spaces_to_add_after_each_word_except_the_last = spaces_needed/(words-1);
remaining_spaces_to_distribute = spaces_needed % (words-1);
The variable remaining_spaces_to_distribute tells how many extra spaces you need to add. Put 1 after the first word. Another after the second word and so on until you have added all the extra spaces.

Related

Why did I get Wrong Answer on this problem(Uva OJ 455)

I'm crazy about this problem (Uva 455):
A character string is said to have period k if it can be formed by
concatenating one or more repetitions of another string of length k.
For example, the string ”abcabcabcabc” has period 3, since it is
formed by 4 repetitions of the string ”abc”. It also has periods 6
(two repetitions of ”abcabc”) and 12 (one repetition of
”abcabcabcabc”).
Write a program to read a character string and
determine its smallest period.
Input
The first line oif the input file
will contain a single integer N indicating how many test case that
your program will test followed by a blank line. Each test case will
contain a single character string of up to 80 non-blank characters.
Two consecutive input will separated by a blank line.
Output
An
integer denoting the smallest period of the input string for each
input. Two consecutive output are separated by a blank line.
Sample Input
1
HoHoHo
Sample Output
2
I've checked all test cases I could imagine and all of them returned correct result, but I still get Wrong Answer on the online judge. Where did I go wrong?
(English is not my native language; please excuse typing or syntax errors.)
#include <stdio.h>
#include <string.h>
#define maxn 85
int check(char* s, int per){
for(int i = 0; i < strlen(s) - per; i++){
if(s[i + per] != s[i]) return 0;
}
return 1;
}
int main(){
int T;
scanf("%d", &T);
char s[maxn];
while(T--){
scanf("%s", s);
int len = strlen(s);
bool OK = false;
for(int i = 1; i <= len/2 && (len % i == 0); i++){//That's wrong.
if(check(s, i)){
printf("%d\n", i);
OK = true;
break;
}
}
if(!OK) printf("%d\n", len);
if(T) printf("\n");
}
return 0;
}
The problem is in for(int i = 1; i <= len/2 && (len % i == 0); i++). You are stopping as soon as you encounter an i that doesn't divide len, instead of skipping it.
Write the loop as:
for (int i = 1; i <= len/2; i++) {
if (len % i != 0) continue;
...
}

C language - counting number of different vowels with no pointers or additional functions

I got this exercise that I haven't been able to solve, the point is to create a program where you type in a text, then the program analyzes each word of the text and counts the vowels of each word, then the program returns in screen the number of words that have 3 or more different vowels, and by different I mean, it doesn't matter if the word has 3 "a", it only count as one (the word has the vowels "a", it doesn't matter how many times), so for example, the word "above" has 3 vowels, the word "been" has 1 vowels, the word "example" has 2 vowels. The vowels can be upper case or lower case, it doesn't matter, and here is the tricky part: It cannot contain any pointers or functions made by us.
what i did was asking the user to enter word by word so the program analyze each word, and then at the end returns the number of words that contain 3 or more vowels, but I feel like there must be an easier way where the user can type a complete paragraph or text, then the program analyzes each word and return the number of words that have 3 or more different vowels.
Anyway, my code is as follows, any suggestions would be appreciated:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
main() {
int vowels, text, words, c, total=0,a=0,e=0,i=0,o=0,u=0;
printf ("How many words does your text has? ");
scanf("%d",&words);
for(c=1;c<=words;c++){
printf("Type your word %d, after that press enter, then press 'control' and 'z' at the same time, and then press enter again: \n", c);
while (EOF != (text=getchar())){
if (text == 'a' || text == 'A'){
a++;
if (a >=2){
a = 1;
}
}
if (text == 'e' || text == 'E'){
e++;
if (e >=2){
e = 1;
}
}
if (text == 'i' || text == 'I'){
i++;
if (i >=2){
i = 1;
}
}
if (text == 'o' || text == 'O'){
o++;
if (o >=2){
o = 1;
}
}
if (text == 'u' || text == 'U'){
u++;
if (u >=2){
u = 1;
}
}
}
vowels = a+e+i+o+u;
if(vowels >=3){
total = total +1;
}
a=0,e=0,i=0,o=0,u=0;
vowels = 0;
}
printf("\n\nThe total of words with 3 or more vowels is: %d", total);
printf("\n");
total=0;
return 0;
}
In order to read and analyze a single word, or a paragraph words to determine the number of words that contain at least three different vowels (of any case), this is one of the rare times when reading input with scanf (using the '%s' format specifier) actually is a reasonable choice.
Recall the '%s' format specifier will read characters up to the first whitespace. That gives you a simple way to read a word at a time from stdin. To end input, the user simply need to generate an EOF by entering ctrl+d (or ctrl+z on windows). This satisfies your paragraph requirement.
For parsing, you can take advantage of converting each character to lower case to simplify checking for vowels. Using a frequency array of 5 elements provides a simple way to track the number of different vowels found in each word. Then a final test to see if the number of vowels found equals the required number is all you need before incrementing your total word count for words with three different vowels.
A simple implementation would be something similar to:
#include <stdio.h>
enum { NREQD = 3, NVOWEL = 5, MAXC = 128 }; /* declare constants */
int main (void) {
char word[MAXC] = ""; /* word buffer */
size_t wordcnt = 0; /* words with 3 different vowels */
printf ("enter a word(s) below, [ctrl+d on blank line to end]\n");
for (;;) {
int vowels[NVOWEL] = {0}, /* frequency array */
vowelcnt = 0, /* vowels per-word */
rtn; /* scanf return */
if ((rtn = scanf ("%127s", word)) == EOF) /* chk EOF */
break;
for (int i = 0; word[i]; i++) { /* loop over each char */
if ('A' <= word[i] && word[i] <= 'Z') /* check upper */
word[i] ^= 'a' - 'A'; /* convert to lower */
switch (word[i]) { /* check if vowel */
case 'a': vowels[0] = 1; break;
case 'e': vowels[1] = 1; break;
case 'i': vowels[2] = 1; break;
case 'o': vowels[3] = 1; break;
case 'u': vowels[4] = 1; break;
}
}
for (int i = 0; i < NVOWEL; i++) /* loop over array */
if (vowels[i]) /* check index */
vowelcnt++; /* increment vowelcnt */
if (vowelcnt >= NREQD) /* do we have at least 3 vowels? */
wordcnt++; /* increment wordcnt */
}
printf ("\nThere are %zu words with %d different vowels.\n",
wordcnt, NREQD);
}
Example Use/Output
$ ./bin/vowelcnt
enter a word(s) below, [ctrl+d on blank line to end]
Everyone Understands That The Dictionary Doesn't Track
Words That Contain Vowels Like It Does Etimology.
There are 4 words with 3 different vowels.
Look things over and let me know if you have further questions.
You can use fgets to read a whole line. I don't know how you define a
paragraph though, do you mean just a long text or a collection of lines? You can
copy & paste multiple lines in the console and if you loop using fgets, then
you get all the lines. But allowing the user to enter multiple lines at once,
it's more tricky, because you should know how many lines the user will input.
That's why I'd say focus on reading the text line by line.
Your solution reads characters by characters and you are ignoring non-vowels.
That's OK, but you are not detecting words like you should do. The for loop
makes no sense, because in the first iteration you enter in a while loop that
is only going to leave when there are no more characters to read from stdin.
So the next iteration of the for loop will not enter the while loop and you
won't be reading anything any more.
You are also repeating too much code, I know you assignment says not to use your
own functions, but this can be improved with a simple look up table by creating
an array of chars using the characters as an index for the array. I'll explain
that in the code.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
int main(void)
{
char line[1024];
// initializing look ups with 0
int lookup_vowels[1 << CHAR_BIT] = { 0 };
// using 'a', 'e' as index for the lookup table
// if you want to know if a character is a vowel,
// lookup_vowels[character] will be 1 if character is
// a vowel, 0 otherwise
lookup_vowels['a'] = lookup_vowels['e'] = lookup_vowels['i'] =
lookup_vowels['o'] = lookup_vowels['u'] = 1;
// for parsing word with strtok
const char *delim = " \t\r\n";
int num_of_words = 0;
printf("Enter some text, to end input press ENTER and then CTRL+D\n");
while(1)
{
if(fgets(line, sizeof line, stdin) == NULL)
break;
// parsing words
char *word = strtok(line, delim);
if(word == NULL)
continue; // the line has only delimiters, ignore it
do {
// will be access with the same principle as the lookup
// table, the character is the index
int present[1 << CHAR_BIT] = { 0 };
size_t len = strlen(word);
for(size_t i = 0; i < len; ++i)
{
// I'll explain later the meaning
int c = tolower(word[i]);
if(lookup_vowels[c])
present[c] = 1; // set the present for a vowel to 1
}
int count = present['a'] + present['e'] + present['i'] + present['o']
+ present['u'];
if(count > 2)
{
printf("'%s' has more than three distinct vowels\n", word);
num_of_words++;
}
} while((word = strtok(NULL, delim)));
}
printf("The number of word with three or more distinct vowels: %d\n", num_of_words);
return 0;
}
So let me quickly explain some of the technique I use here:
The lookup table is an array of size 256 because a char is 8-bit1
value and can have 256 different values (range [0,255]). The idea is that this
array is initialized with 0 overall (int lookup_vowels[1<<CHAR_BIT] = { 0 };) and then
I set to 1 only in 5 places: at the position of the vowels using their
ASCII value as index.
So instead of doing the repeating task if checking
// where c is a char
if(c == 'a' || c == 'A')
a=1;
}
for all vowels, I just can do
int idx = tolower(c);
if(lookup_vowels[idx])
{
// c is a vowel
}
The present variable function similar to the lookup table, here I use the
ASCII code of a vowel as index and set it to 1 if a vowel is present in word.
After scanning all characters in word, I sum all values stored in present.
If the value is greater than 2, then the word has at least 3 or more distinct
vowels and the counter variable is increased.
The function strtok is used to split the line using a defined set of
delimiters, in this case the empty character, tab, carriage return and line
feed. To start parsing the line, strtok must be called with the source string
as the first argument and the delimiters as the second argument. All other
subsequent calls must pass NULL as the first argument. The function returns a
pointer to the next word and returns NULL when no more words have been found.
When a word is found, it calculates the number of distinct vowels and checks if
this number is greater than 2.
fotenotes
1CHAR_BIT defined in limits.h returns the number of bits of byte.
Usually a byte is 8-bit wide, so I could have written 256 instead. But there are
"exotic" architectures where a byte is not 8-bit long, so by doing 1<<CHAR_BIT
I'm getting the correct dimension.

Adding spaces between words in a string c [duplicate]

This question already has answers here:
Add space to a string
(2 answers)
Closed 6 years ago.
I am trying to write a program to insert spaces between words to fit a column, for example:
You read in a line of text, eg: Good morning how are you?
You read in the width of the column, eg: 40.
Then I have counted how many spaces there are in this text (4).
Now I need to distribute the remaining spaces in between these words so the length of the text is 40.
For example:
Good morning how are you?
1234567890123456789012345678901234567890
My problem comes when I try to insert the spaces in between words as I don't know how to do this. This is what I have so far.
#include <stdio.h>
#include <string.h>
char text[65], spaces[50], ch;
int i, remainder, spacesr, count, column, length, distribution;
int main(){
i = 0;
count = 0;
printf("Please enter a line of text: ");
while(ch != '\n')
{
ch = getchar();
text[i]=ch;
i++;
}
text[i]='\0';
printf("Text: %s",text);
printf ("Please enter the width of the column: ");
scanf ("%d", &column);
for (i = 0; text[i] != '\0'; i++) {
if (text[i] == ' ') {
count++;
}
}
length = strlen(text);
spacesr = column - length;
distribution = spacesr / count;
remainder = spacesr % count;
if (length > column) {
printf ("ERROR: Length of text exceeds column width.");
}
}
I have calculated the amount of spaces in the read in text, then calculated the amount of spaces I would have remaining, then divided that by the amount of spaces to determine how many spaces I need to put between each word. The remainder of these spaces will be distributed evenly after the main spaces have been entered.
What do you mean by main spaces?
Basically I want to fit the phrase "Good morning how are you?" to a column 40 characters wide by adding spaces between words. Is it possible to do something like this:
for (i = 0; text[i] != '\0'; i++) {
if (text[i] == ' ') {
then add a certain amount of spaces to it
You need to break your input string into separate words. Take a look at the answers to this earlier question on StackOverflow for some techniques that you can use for that.
After that, it's just a matter of emitting the separate words with the correct number of spaces in between.
One of the many ways to do it.
Suppose totalSpace is the buffer length in which we have to fit the string.
and str = the original string we have.
Algo:
int extraSpace = totalSpace - strlen(str);
int numWords = findWordsInString(str);
int numSpaces = numWords - 1;
int incrementEachSpaceby = extraSpace/numSpace;
//Now linear scan of str and increase spaces by value of incrementEachSpaceby
char *newStr = malloc(totalspace);
int i =0, int j = 0;
int k;
while (i < strlen(str) && j < totalspace)
{
while (str[i] != ' ') {
newStr[j++] = str[i++];
}
while (str[i] == ' ')
newStr[j++] = str[i++];
k = incrementEachSpaceby;
while (k) {
newStr[j++] = ' ';
k--;
}
}
This is just a superficial idea. you can improve it further.

Spliting the value of a % between multiple characters

I've been given an assignment question, and I've managed to figure it all out so far, with the exception of splitting a remainder value betwen a few (input determinate) characters.
Any help would be greatly appreciated.
For reference, my assignment question is:
"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.
"
And my code so far is:
int main() {
//input column width
printf("Enter the width of the column: ");
int column;
scanf("%d", &column);
//input text line
printf("Enter a line of text: ");
char string[80];
getchar();
gets(string);
//print 1234567890 column header
int y = 1,x = 0;
while(x < column){
if(y > 9){
y = 0;
}
printf("%d", y);
y++;
x++;
}
printf("\n");
//count spaces
int i = 0;
int space_count = 0;
while(string[i] != '\0'){
if(string[i] == 0x20){
space_count++;
}
//printf("%c", string[i]);
i++;
}
//work out variables
int string_length = i;
int remainder_space = (column - string_length);
int space_power = (remainder_space / space_count);
//int oddremainder = (space_count % remainder_space) ;
//space_power = (space_power + oddremainder);
//if
//remainder %
//insert column width check
if(string_length > column)
{
printf("Text is too long. Shouldn't be more than %dcharacters\n",
column);
return 1;
}
//output
i = 0;
while(string[i] != '\0'){
if(string[i] == 0x20){
for(x = 0; x < space_power; x++){
printf("%c", 0x20);
}
}
printf("%c", string[i]);
i++;
}
I'm sorry if this isn't the appropriate way of asking a question, my brain is fried and I can't get my head around this.
Any pointers or discusion in the right direction would be greatly appreciated.
Lets see the example. It has 19 spaces to be filled in 4 gaps. If your code runs like that, the value of space_power will be 4 (int(19/4)), and this leaves 3 spaces in the end. You need to keep track of 19 % 4, ie. 3 extra spaces.
So, keep a count, initially equal to 3. Then, while this count is greater than 0, print one extra space along with all space_power number of spaces. Decrease count every time you print a word.
Your code would be like this:
count = remainder_space % space_count;
and output block:
i = 0;
while(string[i] != '\0'){
int k = count > 0 ? 1 : 0;
if(string[i] == 0x20){
for(x = 0; x < space_power + k; x++){
printf("%c", 0x20);
}
count--;
}
printf("%c", string[i]);
i++;
}

Count words in a user-input string in C

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

Resources