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++;
}
Related
I've been sent a exercise where I have to print to the console (in C) a triangle using three different symbols in the following way:
The program must ask how many rows the triangle will have.
The program will print the triangle in the following way:
From outside to inside, the first triangle will be formed of *, the one inside it will be -, the one inside again will be $ and then the other way around...
This is my code:
#include <stdio.h>
int num = 0; //Var to store the user input.
int blank; //Var to store number of blank spaces.
int main() {
printf("Number of rows? ");
scanf("%d", &num);
printf("\n");
blank = num - 1;
//For loop to print each row of the triangle.
for(int k = 1; k <= num; k++) {
//For loop to print each blank space.
for(int j = 1; j <= blank; j++) {
printf(" ");
}
blank--; //Decrease number of blank spaces.
//For loop to print each symbol of the triangle.
for(int r = 1; r <= 2 * k - 1; r++) {
if(r % 2 == 0) {
printf("-");
}
else if(r % 3 == 0) {
printf("$");
}
else {
printf("*");
}
}
printf("\n");
}
blank = 1;
return 0;
}
And this is what it's printing:
Try working out the pattern on paper first.
For example, the dollar sign starts two rows below the top of the outermost triangle. All subsequent dollar signs are each one column before or one column after the preceding dollar sign. In this way each character of a new line is remotely dependent on the very first character.
Once you understand the underlying pattern, you can start programming the loop.
I am trying to print out an inverted hash triangle.
./upside_down_oddnumber
###########
#######
###
My work so far -
int main(void) {
int row, column;
int size;
printf("Enter size: ");
scanf("%d", &size);
row = 1;
while (row <= size) {
column = 1;
while (column <= size) {
if (row == (4 * size) -1 || row == column) {
printf("#");
} else {
printf(" ");
}
column++;
}
printf("\n");
row++;
}
return 0;
}
Currently it is printing a diagonal line sideways and I should use the equation 4n-1. How should I proceed from here? Any help will be greatly appreciated!!
Thanks :)
Start by examining the arithmetics behind the problem:
4*size-1 is the length of the top row of #, i.e. the width of your printout
Each row has an offset of spaces
The number of spaces starts at zero for the initial row, and increases by 2
These three observations should be enough to construct a program. Start row and column numbers at zero for consistency. Each row should be width characters long. Decide which character to print using this formula:
if (column >= offset && column < width-offset) {
printf("#");
} else {
printf(" ");
}
Demo.
The problem is your if statement.
The first section row == (4 * size) -1 is never going to be true, because the row will never be bigger then size, so 4*size will always be bigger then row and thus the statement will never give true.
The second section row == column will of course give you the line.
You should rethink your algorithm.
Or you could do
for(i=size; i>0; --i)
{
for(j=0; j<(4*size-1 - (4*i-1))/2; ++j)
{
printf(" ");
}
for(j=0; j<4*i-1; ++j)
{
printf("%c", '#');
}
printf("\n");
}
(4*size-1 - (4*i-1))/2 will give the number of spaces that must be printed at the start of each line.
After printing the required number of spaces, the #s are printed out.
You could also use
printf("%*s", (4*size-1 - (4*i-1))/2, "");
instead of the loop to print the spaces.
The * in %*s is used to specify the width of the string to be printed.
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.
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.
Okay so I'm using Kernighan and Ritchie's "The C Programming Language" and I'm on exercise 1.13 and I can't seem to get this right. My program seems to not be printing much. The problem is as follows:
Exercise 1-13. Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with
the bars horizontal; a vertical orientation is more challenging.
Besides the creation of variables, here's my pseudocode for reading the input and storing what I want to store in the array.
Create an array -- in this case, my array is of size 21 (21 elements, from 0 to 20) all assigned a value of 0 initially. It has 21 elements because I'm not going to use words that have more than 20 characters. I realize this is weird given no words have zero characters.
Begin counting characters in input.
If I encounter a space, tab, or newline character (i.e., this means the first word ended), stop.
Depending on how many characters the word had, increment that particular position in the array (i.e., if the word had two characters add 1 to the element at position 2 in the array).
Increment the wordCounter variable -- this variable as it's name indicates keeps track of the number of words that have been "read" in the input.
Continue doing this to each word until EOF is reached.
Here's my pseudocode for printing the histogram (horizontally).
For the first position, print the value stored in the first position of the array (i.e., 0) using tick marks |
Do this for every element in the array.
Here's my code:
#include <stdio.h>
#define SIZEOFWORDSOFLENGTH 21
int main() {
int wordsOfLength[SIZEOFWORDSOFLENGTH];
int c, i, j;
int lengthCounter = 0;
/*Initializing all array elements to 0.*/
for (i = 0; i < SIZEOFWORDSOFLENGTH; i++)
wordsOfLength[i] = 0;
/*Going through the input and counting.*/
while ((c = getchar()) != EOF) {
++lengthCounter;
if (c == ' ' || c == '\t' || c == '\n') {
++wordsOfLength[lengthCounter - 1];
lengthCounter = 0;
}
}
for (i = 0; i < SIZZEOFWORDSOFLENGTH; i++) {
printf("Words of Length %d: ", i);
/*The third argument of the following for loop was previously j = j*/
for (j = 0; j < SIZEOFWORDSOFLENGTH; j++) {
while (j < wordsOfLength[i]) {
printf("|");
/*Was previously j++ instead of break*/
break;
}
}
printf("\n");
}
}
I debugged it by hand but I can't seem to find the problem. Maybe something really simple is going over my head. Also, I know this question has been asked before but I'm not trying to find a solution for the actual problem, I think my pseudocode is right if not somewhat right, I just want to know what's wrong with my code and maybe learn something. Thank you in advance.
As indicated in Ji-Young Park's answer, the reading loop has problems because it uses negative indexes into the array wordsOfLength. I would keep life simple and have wordsOfLength[i] store the number of words of length i, though it effectively wastes wordsOfLength[0]. I would use the macros from <ctype.h> to spot word boundaries, and I'd keep a record of whether I was in a word or not. You get credit for using int c.
int inword = 0;
while ((c = getchar()) != EOF)
{
if (!isspace(c))
lengthCounter++;
else if (inword)
{
wordsOfLength[lengthCounter]++;
lengthCounter = 0;
inword = 0;
}
}
if (inword)
wordsOfLength[lengthCounter]++;
This code is not bamboozled by leading white space in the file. If you think there's any risk of reading 'antidisestablishmentarianism' (28) or 'floccinaucinihilipilification' (29) or other grotesquely long words, you should check on lengthCounter before blindly using it as an index, either dropping overlong words from the count or mapping them all to '20+ characters' class.
Your final triple loop is quite problematic too — it is currently:
for (i = 0; i < SIZZEOFWORDSOFLENGTH; i++) {
printf("Words of Length %d: ", i);
/*The third argument of the following for loop was previously j = j*/
for (j = 0; j < SIZEOFWORDSOFLENGTH; j++) {
while (j < wordsOfLength[i]) {
printf("|");
/*Was previously j++ instead of break*/
break;
}
}
printf("\n");
}
Under my scheme, I'd start with i = 1, but that isn't a major issue. I'd ensure that the first printf() printed for 2 digits to align the output for the counts of words of lengths 10-20.
The inner for loop should be constrained by wordsOfLength[i] rather than SIZEOFWORDSOFLENGTH, and the while loop is redundant (not least because you break it on the first iteration each time). You just need simple nested for loops:
for (i = 1; i < SIZZEOFWORDSOFLENGTH; i++)
{
printf("Words of Length %2d: ", i);
for (j = 0; j < wordsOfLength[i]; j++)
printf("|");
printf("\n");
}
The only issue now is if the maximum value in wordsOfLength is too long for comfort (for example, you've read the entire works of Shakespeare, so some of the words appear thousands of times).
you don't need to substract '1' from lengthCounter in
++wordsOfLength[lengthCounter - '1'];
It should be
++wordsOfLength[lengthCounter];