Reputation: 237
I'm a beginner in C# and object programming. I'm trying to write a program that will read characters, put them into words and produce an output that consists of those words written on lines, but there may be only 30 characters per line. If the word is longer that 30 characters, it can be longer than the max allowed length of line.
Here is what I have so far. It seems to be working, but I don't like that it makes 2 extra whitespaces at the end. Also, is there a more effective way to do this program, maybe shorter, "tidier"? Thank you.
class Program
{
public static readonly int MAX_LENGTH = 30; // max number of characters in one line
public static int counter = 0; // counts characters in line
public static bool OverMaxLength(string word) // chcecks, whether the words is bigger than MAX_LENGTH
{
return (word.Length >= MAX_LENGTH);
}
public static void AddToCounter(string word, ref int counter) // adds the length of word into the counter
{
counter += word.Length;
}
public static void CheckIfOverflow(string word, ref int counter)
{
if (counter > MAX_LENGTH) // if counter counts more than is allowed
{
Console.WriteLine();
Console.Write(word + " ");
counter = word.Length + 1;
}
else
{
Console.Write(word + " ");
counter += 1;
}
}
public static string ReadWord()
{
string word = "";
char c;
// reads one character
c = Convert.ToChar(Console.Read());
do
{
word += c;
c = Convert.ToChar(Console.Read());
} while (c != ' ');
return word;
}
static void Main(string[] args)
{
string word = "";
word = ReadWord();
while (word != "konec")
{
if ( (OverMaxLength(word)) & (counter > 0))
{
Console.WriteLine();
Console.WriteLine(word);
counter = 0;
}
else if ((OverMaxLength(word)) & (counter == 0))
{
Console.Write(word);
counter = word.Length;
}
else
{
AddToCounter(word, ref counter);
CheckIfOverflow(word, ref counter);
}
word = ReadWord();
}
Console.Read();
}
}
Upvotes: 1
Views: 97
Reputation: 310
There are quite a lot of things you can improve on so im going to list a few.
First off, you should look at putting your implementation of this word reader into a separate file/class and get rid of the static abuse. Instead of making everything static you can instantiate a class Program p = new Program(); p.ReadWord();
If you want to read words split by spaces you should instead read the entire string at once and split it. string[] words = Console.ReadLine().Split(' ');
When you want boolean operations you should use &&
as &
is a bitwise operator.
As for listing the output 30 characters per line you can do string combinedWords = string.join(words, ' ');
and then use string.Substring
eg. Console.WriteLine(combinedWords.Substring(0, 30));
Upvotes: 1
Reputation: 109732
It might be better to split the logic up somewhat.
First, have a method that returns an IEnumerable<string>
sequence of words.
Then have another method that returns an IEnumerable<string>
sequence of lines with the words concatentated according to your specification.
The latter can be written more succinctly like so:
public static IEnumerable<string> ConcatWithLimit(IEnumerable<string> words, int maxLineLength)
{
var sb = new StringBuilder();
foreach (string word in words)
{
if (sb.Length + word.Length > maxLineLength)
{
yield return sb.ToString().TrimEnd();
sb.Clear();
}
sb.Append(word).Append(" ");
}
if (sb.Length > 0)
yield return sb.ToString().TrimEnd();
}
Some test code for it:
string[] words =
{
"1", "22", "333", "4444", "55555", "666666", "7777777",
"1", "22", "333", "4444", "55555", "666666", "7777777",
"1", "22", "333", "4444", "55555", "666666", "7777777",
"1", "22", "333", "4444", "55555", "666666", "7777777",
"12345678901234567890123456789012345", "55555", "666666",
"1", "22", "333", "4444", "55555", "666666", "7777777",
"1", "22", "333", "4444", "55555", "666666", "7777777",
};
Console.WriteLine(" 1 2 3");
Console.WriteLine("123456789012345678901234567890123456789");
Console.WriteLine(string.Join("\n", ConcatWithLimit(words, 30)));
Upvotes: 1