Adding spaces between words in a string c [duplicate] - c

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.

Related

A function to check if the word has an increasing or decreasing sequence of chars in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm new in C.
I've been asked to write a function that checks if the string has increasing/decreasing sequence of letters based on ASCII values + not includes white spaces(tabs,new lines etc.).
For example: demo is a very increasing string
beef is an increasing string
aa or zzz is an increasing string
tonic is a very decreasing string
spoon is a decreasing string
suddenly has no clear sequence.
So I wrote this code,it works but not so well..can you help me to improve it a little bit?
#include <stdio.h>
void f_sequence (char str[]);
int main()
{
char strl[101];
printf("your string is:\n");
scanf("%s\n", strl);
f_sequence(strl);
return 0;
}
void f_sequence(char str[])
{
int increase=0;
int decrease=0;
int match=0;
int i = 1;
if(!str[0])
printf("empty");
else if(!str[1])
printf("need more chars");
for(i=1; str[i]; i++)
{
if (str[i] == str[i-1])
match = 1;
if (str[i] > str[i-1])
increase = 1;
if (str[i] < str[i-1])
decrease = 1;
}
if((decrease==1) && (increase==0) && (match==0))
printf("we have a very descreasing sequence in here");
if((decrease==0) && (increase==1) && (match==0))
printf("we have a very increasing sequence in here");
if((decrease==1) && (increase==0) && (match==1))
printf("we have a descreasing sequence in here");
if((decrease==0) && (increase==1) && (match==1))
printf("we have an increasing sequence in here");
if((decrease==0) && (increase==0) && (match==1))
printf("we have an increasing sequence in here");
if((decrease==1) && (increase==1))
printf("not increasing and not decreasing");
puts("");
}
To ignore whitespaces, you can use isspace from <ctype.h> and skip in your calculations:
for(i = 1; str[i]; i++)
{
if (isspace((unsigned char)str[i])) continue;
...
}
But as is, you can't read input string with whitespaces as scanf with %s would stop reading at the first whitespace. You need fgets to read a line (so that you could read a string with whitespaces):
int main()
{
char strl[101];
printf("your string is:\n");
if (fgets(strl, sizeof strl, stdin)) {
char *p = strchr(strl, '\n');
if (p) *p = '\0'; // Remove newline if present
f_sequence(strl);
}
}
fgets would also read the newline character if there's space in the buffer which you may want to remove as shown (include <string.h> for strchr).
Use a function like below to remove whitespaces:
void removeSpaces(char *str)
{
// To keep track of non-space character count
int count = 0;
// Traverse the given string. If current character
// is not space, then place it at index 'count++'
for (int i = 0; str[i]; i++)
if (str[i] != ' ')
str[count++] = str[i]; // here count is
// incremented
str[count] = '\0';
}
And then add this function in the first line of f_sequence function. like this:
removeSpaces(str);

Trouble finding end of string

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.

Attach a String to another String in C WITHOUT any spaces

this is my first post in this forum so please be patient.
I need to make a short programm, where the user can enter 2 strings which should be attached afterwards.
I already got this code below (I am not allowed to use other "includes").
What I need to know is: How can I deny any spaces which the user will enter?
Example: 1. String "Hello " | 2. String "World" Result should be "HelloWorld" instead of "Hello World".
#include <stdio.h>
void main()
{
char eingabe1[100];
char eingabe2[100];
int i = 0;
int j = 0;
printf("Gib zwei Wörter ein, die aneinander angehängt werden sollen\n");
printf("1. Zeichenkette: ");
gets(eingabe1);
printf("\n");
printf("2. Zeichenkette: ");
gets(eingabe2);
printf("\n");
while (eingabe1[i] != '\0')
{
i++;
}
while (eingabe2[j] != '\0')
{
eingabe1[i++] = eingabe2[j++];
}
eingabe1[i] = '\0';
printf("Nach Verketten: ");
puts(eingabe1);
}
You have to filter out the spaces as you copy your strings.
You have two string indices, i for the first string and and j for the second string. You could make better use of these indices if you used i for the reading position (of both strings subsequently; you can "reuse" loop counters in independent loops) and j for the writing position.
Here's how. Note that the code attempts to prevent buffer overflow by only adding characters if there is space in the string. This check needs only to be done when copying the second string, because j <= i when you process the first string.
#include <stdio.h>
int main()
{
char str1[100] = "The quick brown fox jumps over ";
char str2[100] = "my big sphinx of quartz";
int i = 0;
int j = 0;
while (str1[i] != '\0') {
if (str1[i] != ' ') str1[j++] = str1[i];
i++;
}
i = 0;
while (str2[i] != '\0') {
if (str2[i] != ' ' && j + 1 < sizeof(str1)) str1[j++] = str2[i];
i++;
}
str1[j] = '\0';
printf("'%s'\n", str1);
return 0;
}
In addition to avoiding spaces between your two words, you also have to avoid the newline ('\n') character placed in the input buffer by the user pressing Enter. You can do that with a simple test after you have read the line with fgets() NOT gets(). gets() is no longer part of the standard C library and should not be used due to insecurity reasons. Plus fgets provides simple length control over the number of characters a user may enter at any time.
Below, you run into trouble when you read eingabe1. After the read, eingabe1 contains a '\n' character at its end. (as it would using any of the line-oriented input functions (e.g. getline(), fgets(), etc) To handle the newline, you can simply compare its length minus '1' after you loop over the string to find the nul character. e.g.:
if (eingabe1[i-1] == '\n') i--; /* remove trailing '\n', update i */
By simply reducing the index 'i', this will guarantee that the concatenation with eingabe2 will not have any spaces or newline characters between the words.
Putting the pieces together, and using fgets in place of the insecure gets, after #define MAX 100'ing a constant to prevent hardcoding your array indexes, you could come up with something similar to:
#include <stdio.h>
#define MAX 100
int main (void)
{
char eingabe1[MAX] = {0};
char eingabe2[MAX] = {0};
int i = 0;
int j = 0;
printf("Gib zwei Wörter ein, die aneinander angehängt werden sollen\n");
printf("1. Zeichenkette: ");
/* do NOT use gets - it is no longer part of the C library */
fgets(eingabe1, MAX, stdin);
putchar ('\n');
printf("2. Zeichenkette: ");
/* do NOT use gets - it is no longer part of the C library */
fgets(eingabe2, MAX, stdin);
putchar ('\n');
while (eingabe1[i]) i++; /* set i (index) to terminating nul */
if (i > 0) {
if (eingabe1[i-1] == '\n') i--; /* remove trailing '\n' */
while (i && eingabe1[i-1] == ' ') /* remove trailing ' ' */
i--;
}
while (eingabe2[j]) { /* concatenate string - no spaces */
eingabe1[i++] = eingabe2[j++];
}
eingabe1[i] = 0; /* nul-terminate eingabe1 */
printf("Nach Verketten: %s\n", eingabe1);
return 0;
}
Output
$ ./bin/strcatsimple
Gib zwei Wörter ein, die aneinander angehängt werden sollen
1. Zeichenkette: Lars
2. Zeichenkette: Kenitsche
Nach Verketten: LarsKenitsche
Let me know if you have any further questions. I have highlighted the changes with comments above.
/**
return: the new len of the string;
*/
int removeChar(char* string, char c) {
int i, j;
int len = strlen(string)+1; // +1 to include '\0'
for(i = 0, j = 0 ; i < len ; i++){
if( string[i] == c )
continue; // avoid incrementing j and copying c
string[ j ] = string[ i ]; // shift characters
j++;
}
return j-1; // do not count '\0';
}
int main(){
char str1[] = "sky is flat ";
char str2[100] = "earth is small ";
strcat( str2, str1 );
printf("with spaces:\n\t'%s'\n", str2) ;
removeChar(str2, ' ');
printf("without spaces:\n\t'%s'\n", str2 );
}
/**
BONUS: this will remove many characters at once, eg "\n \r\t"
return: the new len of the string;
*/
int removeChars(char* string, char *chars) {
int i, j;
int len = strlen(string);
for(i = 0, j = 0 ; i < len ; i++){
if( strchr(chars,string[i]) )
continue; // avoid incrementing j and copying c
string[ j ] = string[ i ]; // shift characters
j++;
}
string[ j ]=0;
return j;
}
Thank you everyone for all the answers.
I got the solution now.
I read some advices from you and will try to remember for the future.
See the code below:
(Excuse me for the strange names for the variables, I use german words)
A few notices:
I am not allowed to use library functions
I am not allowed to use fgets for some reasons as a trainee
#include <stdio.h>
void main()
{
char eingabe1[100];
char eingabe2[100];
int i = 0;
int j = 0;
printf("gib zwei wörter ein, die aneinander angehängt werden sollen\n");
printf("1. zeichenkette: ");
gets(eingabe1);
printf("\n");
printf("2. zeichenkette: ");
gets(eingabe2);
printf("\n");
//Attach Strings
while (eingabe1[i] != '\0')
{
i++;
}
while (eingabe2[j] != '\0')
{
eingabe1[i++] = eingabe2[j++];
}
//Remove Space
eingabe1[i] = '\0';
i = 0;
j = 0;
while (eingabe1[i] != '\0')
{
if (eingabe1[i] != 32)
{
eingabe2[j++] = eingabe1[i];
}
i++;
}
eingabe2[j] = '\0';
printf("Nach verketten: ");
puts(eingabe2);
}
Sounds like homework to me.
I just wanted to mention that you probably shouldn't use sizeof() on strings these days because there may be multibyte characters in there. Use strlen() instead. The only time sizeof() would be appropriate is if you're going to malloc() a certain number of bytes to store it.
I write little loops fairly often to do low level text stuff one character at a time, just be aware that strings in C usually have a 0 byte at the end. You have to expect to encounter one and be sure you put one on the output. Space is 0x20 or decimal 32 or ' ', it's just another character.

C Programming: Counting word length occurences in a string

How would you be able to count word lengths and output their occurrences from a string using gets() or fgets()? For example, here is code doing so but using getchar()below. I think writing it in gets() would make it easier to incorporate all of the delimiters in the program rather than having to manually set if statements for each one of those would it not?
#include <string.h>
#include <ctype.h>
const char delim[] = ", . - !*()&^%$##<> ? []{}\\ / \"";
#define SIZE 100
int main(void){
int length[SIZE] = { 0 };
int name[SIZE];
int i = 0, ch, word_len = 0;
int count = 0;
printf("enter sentence: ");
while (1){
ch = getchar();
if (isalpha(ch)){
++word_len;
}
else if (ch == ' ' || ch == '.'){
if (word_len)
length[word_len - 1]++;//-1: to 0 origin
if (ch == '.')
break;
word_len = 0;
}
}
printf("Word Length \tCount \n");
for (i = 0; i<sizeof(length) / sizeof(*length); ++i){
if (length[i])
printf(" %d \t\t%d\n", i + 1, length[i]);
}
return 0;
}
You can build your custom delimiter detection function.
// globals
const char *delim = " .,;:!?\n\0";
const int n_delim = 9;
int is_delim(int c)
{
register int i;
for (i = 0; i < n_delim; i++)
if (c == delim[i]) return 1;
return 0;
}
This function will return 1 every time it can match c with delim. So you can use it like this:
fgets(buffer, 200, stdin);
for (i = 0; i < strlen(buffer); i++) {
if (is_delim(buffer[i])) {
wl[words++] = length;
length = 0;
continue;
}
length++;
}
I'm assuming you're familiar with the fgets function.
You basically will loop through your buffer, making comparisons with each character. Every loop iteration you check if the current character is a word delimiter, if it is, you save the current length and set length=0 for a new word, and at every iteration you increment the length.
You'll need to come up with a way of either not inserting the zero length values due to double delimiters or just ignore them when you're printing the results.
Basically you want to split a string into words, based on some delimiters, and compute their length. The C standard library provides the strtok function, which does exactly what you need: it splits the given string into multiple tokens.

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

Resources