Mutating to a new string array - c#

I'm doing an exercise that says I have to enter a phrase and put it in array, then I have to delete all the repeated characters and show the new phrase.
I did it like this but I don't know how to get char from string array and put it into another string array.
PS: I must only use the basics of C# and arrays :(
namespace Exercice3
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Entrez une phrase SVP!!");
string phrase = Console.ReadLine();
string[] phraseArray = new string[]{ phrase };
string[] newPhrase = new string[phrase.Length];
for (int i = 0; i <= phrase.Length - 1; i++)
{
for (int j = 1; j <= phrase.Length - 1; j++)
{
if (phraseArray[i] != phraseArray[j])
newPhrase = phraseArray[i]; //Probleme here
}
}
Console.WriteLine(newPhrase);
}
}
}

something like this would do it. You don't have to do it this way...
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var newColl = new List<char>();
foreach(char c in "aaabbbccc".ToCharArray())
{
if (!newColl.Contains(c))
newColl.Add(c);
}
Console.WriteLine(new string(newColl.ToArray()));
}
}
Output:
abc
Array-only method
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
const string orig = "aaabbbcccddd";
int origLen = orig.Length;
char[] newArr = new char[origLen]; // get max possible spots in arr
int newCount = 0;
for(int i = 0; i < origLen; i++)
{
bool yes = false;
for(int j = 0; j < newCount + 1; j++)
{
if (newArr[j] == orig[i])
{
yes = true;
break;
}
}
if (!yes)
{
newArr[newCount] = orig[i];
newCount++;
}
}
Console.WriteLine(new string(newArr));
}
}
Output:
abcd

The main problem here is that you are using arrays of strings. That is inappropriate because you are trying to iterate the characters of the string.
You need to construct your array of characters like this:
char[] phraseArray = phrase.ToCharArray();
This should allow you the ability to iterate the set of characters, check for duplicates, and form the new character array.

The reason why you're getting an IndexOutOfRangeException is because if you look at the two arrays:
string[] phraseArray = new string[]{ phrase };
And
string[] newPhrase = new string[phrase.Length];
The length of both arrays are completely different, phraseArray has a length of 1 and newPhrase will be set to the length of your phrase, so if you insert a world of more than 1 character both arrays will not match and then either:
if (phraseArray[i] != phraseArray[j])
Or
newPhrase = phraseArray[i];
Will fail, specially newPhrase = phraseArray[i];, because here you're trying to replace newPhrase an array, for a character phrase[i]. Basically your solution won't work. So what you can do is do what #Travis suggested, basically change your arrays from String[]to char[], then:
char[] phraseArray = phrase.ToCharArray();
Or Instead of using arrays you can just use another string to filter your phrase. The first string being your phrase and the second would be the string you'd add your non repeated characters to. basically this:
Console.WriteLine("Entrez une phrase SVP!!");
string phrase = Console.ReadLine();
string newPhrase = "";
// loop through each character in phrase
for (int i = 0; i < phrase.Length; i++) {
// We check if the character of phrease is within our newPhrase, if it isn't we add it, otherwise do nothing
if (newPhrase.IndexOf(phrase[i]) == -1)
newPhrase += phrase[i]; // here we add it to newPhrase
}
Console.WriteLine(newPhrase);
Don't forget to read the comments in the code.
Edit:
Based on the comments and suggestions given I implemented a similar solution:
Console.WriteLine("Entrez une phrase SVP!!");
char[] phrase = Console.ReadLine().ToCharArray();
char[] newPhrase = new char[phrase.Length];
int index = 0;
// loop through each character in phrase
for (int i = 0; i < phrase.Length; i++) {
// We check if the character of phrease is within our newPhrase, if it isn't we add it, otherwise do nothing
if (Array.IndexOf(newPhrase, phrase[i]) == -1)
newPhrase[index++] = phrase[i]; // here we add it to newPhrase
}
Console.WriteLine(newPhrase);

Related

How do I make my own String.Split() and Array.Reverse() built-in functions in one user-defined function to reverse a given string?

I have tried this:
using System;
using System.Collections;
using System.Collections.Generic;
public class HelloWorld
{
public static string reverseWords(string str){
ArrayList strArr = new ArrayList();
int start = 0;
string revStr = "";
for(int i = 0; i < str.Length; i++){
if(str[i] == ' '){ // if there's a space,
while(start <= str[i - 1]){ // loop thru the iterated values before space
strArr.Add(str[start]); // add them to the ArrayList
start++; // increment `start` until all iterated values are-
} // stored and also for the next word to loop thru
}
}
for(int j = strArr.Count - 1; j >= 0; j--){
revStr += strArr[j] + " "; // keep appending ArrayList values to the-
} // string from the last to the first value
return revStr;
}
public static void Main(string[] args)
{
Console.WriteLine(reverseWords("Our favorite color is Pink"));
//Expected output : Pink is color favorite Our
}
}
And it's giving this error:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
Please help me understand why this is not working. And also, if there's better way to do this ReverseWord function manually(not using any built-in functions at all).
I'm sorry if this is such a noob question. Any constructive criticism is appreciated. Thanks!
Here is a little improved version of your code that actually works for what you are willing to do.
using System;
using System.Collections;
public class HelloWorld
{
public static string reverseWords(string str){
ArrayList strArr = new ArrayList();
string currentWordString = string.Empty;
string revStr = string.Empty;
for(int i = 0; i < str.Length; i++){
if(str[i] == ' '){ // if there's a space,
strArr.Add(currentWordString); // add the accumulated word to the array
currentWordString = string.Empty; // reset accumulator to be used in next iteration
}else {
currentWordString += str[i]; // accumulate the word
}
}
strArr.Add(currentWordString); // add last word to the array
for(int j = strArr.Count - 1; j >= 0; j--){
revStr += strArr[j] + " "; // keep appending ArrayList values to the-
} // string from the last to the first value
return revStr;
}
public static void Main(string[] args)
{
Console.WriteLine(reverseWords("Our favorite color is Pink"));
//Expected output : Pink is color favorite Our
}
}
I'll let you do the remaining. Like removing the trainling space at the end of the sentence. add seperators other than space (e.g comma, semicolons...)
Try this
"Our favorite color is Pink".Split('\u0020').Reverse().ToList().ForEach(x =>
{
Console.WriteLine(x);
});
This will help
public static string ReverseCharacters(string str)
{
if(str == null)
{
throw new ArgumentNullException(nameof(str));
}
int lastIndex = str.Length - 1;
char[] chars = new char[str.Length];
char temp;
for(int i = 0; i < str.Length/2+1; i++)
{
// Swap. You could refactor this to its own method if needed
temp = str[i];
chars[i] = str[lastIndex - i];
chars[lastIndex - i] = temp;
}
return new string(chars);
}
public static string ReverseWords(string str)
{
if (str == null)
{
throw new ArgumentNullException(nameof(str));
}
if (string.IsNullOrWhiteSpace(str))
{
return str;
}
string space = " ";
StringBuilder reversed = new StringBuilder();
// reverse every characters
var reversedCharacters = ReverseCharacters(str);
// split words (space being word separator here)
var reversedWords = reversedCharacters.Split(space);
// for every revered word characters, reverse it back one more time and append.
foreach(var reversedWord in reversedWords)
{
reversed.Append(ReverseCharacters(reversedWord)).Append(space);
}
// remove last extra space
reversed = reversed.Remove(reversed.Length - 1, 1);
return reversed.ToString();
}
Here is the test result:

Can't reverse a string using a for loop

I need to reverse a string using a for loop but I just can't do it. What I'm doing wrong?
class Program
{
static void Main(string[] args)
{
string s;
string sReverse;
Console.WriteLine("Say any word please: ");
s = Console.ReadLine();
for (int i = 0; i < s.Length; i++)
{
s[s.Length - i] = sReversa[i];
}
}
}
Strings are immutable. You can't change them character by character.
If you want random access to the characters in a string, convert it to a char array first (using ToCharArray), then convert it back when you're done (String has a constructor that accepts a char array).
string a = "1234";
char[] b = a.ToCharArray();
b[1] = 'X';
a = new string(b);
Console.WriteLine("{0}", a);
Output:
1X34
There are much easier ways to reverse a string (e.g. LINQ would let you do var output = new string(input.Reverse().ToArray());), but if you want to use a for loop and your current approach, this is probably the piece of information you are missing.
These will be the minimal changes required in your code:
public static void Main()
{
string s;
string sReverse = string.Empty; // Initialise (always recommended)
Console.WriteLine("Say any word please: ");
s = Console.ReadLine();
for (int i = s.Length-1; i >=0 ; i--) // Chnage the order of indexing
{
sReverse += s[i]; // makes a new string everytime since strings are immutable.
}
Console.WriteLine(sReverse); // print your new string
}
As others said this may not be the best approach for very large number of string manipulation / formation. Instead, use StringBuilder.
StringBuilder is suited in situations where you need to perform repeated modifications to a string, the overhead associated with
creating a new String object can be costly.
Below is the snippet on how to use StringBuilder:
using System;
using System.Text; // Add this for StringBuilder
public class Program
{
public static void Main()
{
string s;
StringBuilder sReverse = new StringBuilder(); // Instantiate the object.
Console.WriteLine("Say any word please: ");
s = Console.ReadLine();
for (int i = s.Length-1; i >=0 ; i--)
{
sReverse.Append(s[i]); // Keep Appending to original string.
}
Console.WriteLine(sReverse.ToString()); // finally convert to printable string.
}
}
string reverse = string.Join("", "some word".Reverse());
You can not use s[s.Length - i] = sReversa[i];
Because Strings are immutable.
Instead, you can use sReverse = sReverse + s[Length];
The following code will give you reverse of a string:
static void Main(string[] args)
{
string s;
string sReverse = "";
int Length;
Console.WriteLine("Say any word please: ");
s = Console.ReadLine();
Length = s.Length - 1;
for (int i = Length; i >= 0; i--)
{
sReverse = sReverse + s[Length];
Length--;
}
Console.WriteLine("{0}", sReverse);
Console.ReadLine();
}
Note: For a large number of iteration, this might be a performance issue.
The simplest way to make your code work with minimal changes is to use a StringBuilder. Unlike string a StringBuilder is mutable.
Here's the code:
Console.WriteLine("Say any word please: ");
string s = Console.ReadLine();
StringBuilder sb = new StringBuilder(s);
for (int i = 0; i < s.Length; i++)
{
sb[s.Length - i - 1] = s[i];
}
string r = sb.ToString();
If you must use a for loop the way you want, you will have to allocate a new char array, initialize it with the string's characters from back to front, then take advantage of the string constructor that takes a char array as input. The code looks as follows:
public static string ReverseWithFor(string s)
{
if (string.IsNullOrEmpty(s)) return s;
char[] a = new char[s.Length];
for (int i = 0; i < s.Length; i++)
a[s.Length - 1 - i] = s[i];
return new string(a);
}

Reverse word of full sentence using for loop in c#

I want to print the string in reverse format in for loop:
Input: I'm Learning c#
Output: c# Learning I'm
No Split functions and reverse functions should be used, it has to do only with forloop.
for (int i = m.Length - 1; i >= 0; i--)
{
b[j]=a[i];
j++;
if(a[i]==' '|| a[i]==0)
{
for (int x = b.Length - 1; x >= 0; x--)
{
c[k] = b[x];
Console.Write(c[k]);
k++;
}
}
} Console.ReadKey();
You have to create an array of the words in the sentence:
var words = input.Split(' ');
Then you just loop through the above array from the end to the start:
for(int i=words.Length-1; i>=0; i--)
{
Console.Write(words[i]+" ");
}
With LINQ and string methods you can simplify it:
var reversedWords = input.Split().Reverse(); // Split without parameters will use space, tab and new-line characters as delimiter
string output = string.Join(" ", reversedWords); // build reversed words, space is delimiter
Use Stack<Queue<char>>
Hey if you want to show off your knowledge of data structures, use a queue and a stack! This makes for a very concise answer as well.
You want the sentence to be LIFO with respect to words but FIFO with respect to letters within words, so you need a stack (which are LIFO) of queues (which are FIFO). You can take advantage of the fact that a string, a queue<char>, and a stack<char> all expose IEnumerable<char> as well, so it's easy to convert back and forth; once you have all the characters ordered in your data structure, you can extract the whole thing as a character array using SelectMany(), which you can pass to a string constructor for the final answer.
This solution uses no Split() or Reverse() functions, as required.
public static string ReverseSentence(string input)
{
var word = new Queue<char>();
var sentence = new Stack<IEnumerable<char>>( new [] { word } );
foreach ( char c in input )
{
if (c == ' ')
{
sentence.Push( " " );
sentence.Push( word = new Queue<char>() );
}
else
{
word.Enqueue(c);
}
}
return new string( sentence.SelectMany( w => w ).ToArray() );
}
Usage:
public void Test()
{
var input = "I'm Learning c#";
var output = ReverseSentence(input);
Console.WriteLine(output);
}
Output:
c# Learning I'm
DotNetFiddle
Without split and reverse, I modify your logic little bit to achieve what you need
namespace MyNamespace
{
public class Program
{
public static void Main(string[] args)
{
var m="this is mystring";
var b = new char [m.Length];
var j=0;
//Your code goes here
for (int i = m.Length - 1; i >= 0; i--)
{
b[j]=m[i];
j++;
if(m[i]==' ' || i==0)
{
if(i==0)
{
b[j]=' ';
}
for (int x = b.Length - 1; x >= 0; x--)
{
Console.Write(b[x]);
}
b=new char[m.Length];
j=0;
}
}
Console.ReadKey();
Console.WriteLine("Hello, world!");
}
}
}
Input: "this is mystring"
Output: "mystring is this"
Here is a simple console application for your question
Without using Reverse and Split methods (just for loop)
class Program
{
static void Main()
{
string input = "I'm learning C#";
string[] result = new string[3];
int arrayIndex = 0;
string tempStr = "";
// Split string
for (int i = 0; i < input.Length; i++)
{
tempStr += input[i].ToString();
if (input[i] != ' ')
{
result[arrayIndex] = tempStr;
}
else
{
tempStr = "";
arrayIndex++;
}
}
// Display Result
for (int i = result.Length - 1; i >= 0; i--)
{
System.Console.Write(result[i] + ' ');
}
System.Console.WriteLine();
}
}
Press Ctrl + F5 to run the program
Output: C# learning I'm

How to reverse an array of strings without changing the position of special characters in C#

I'm working on reversing a sentence. I'm able to do it. But I'm not sure, how to reverse the word without changing the special characters positions. I'm using regex but as soon as it finds the special characters it's stopping the reversal of the word.
Following is the code:
Console.WriteLine("Enter:");
string w = Console.ReadLine();
string rw = String.Empty;
String[] arr = w.Split(' ');
var regexItem = new Regex("^[a-zA-Z0-9]*$");
StringBuilder appendString = new StringBuilder();
for (int i = 0; i < arr.Length; i++)
{
char[] chararray = arr[i].ToCharArray();
for (int j = chararray.Length - 1; j >= 0; j--)
{
if (regexItem.IsMatch(rw))
{
rw = appendString.Append(chararray[j]).ToString();
}
}
sb.Append(' ');
}
Console.WriteLine(rw);
Console.ReadLine();
Example : Input
Marshall! Hello.
Expected output
llahsram! olleh.
A basic solution with regex and LINQ. Try it online.
public static void Main()
{
Console.WriteLine("Marshall! Hello.");
Console.WriteLine(Reverse("Marshall! Hello."));
}
public static string Reverse(string source)
{
// we split by groups to keep delimiters
var parts = Regex.Split(source, #"([^a-zA-Z0-9])");
// if we got a group of valid characters
var results = parts.Select(x => x.All(char.IsLetterOrDigit)
// we reverse it
? new string(x.Reverse().ToArray())
// or we keep the delimiters as it
: x);
// then we concat all of them
return string.Concat(results);
}
The same solution without LINQ. Try it online.
public static void Main()
{
Console.WriteLine("Marshall! Hello.");
Console.WriteLine(Reverse("Marshall! Hello."));
}
public static bool IsLettersOrDigits(string s)
{
foreach (var c in s)
{
if (!char.IsLetterOrDigit(c))
{
return false;
}
}
return true;
}
public static string Reverse(char[] s)
{
Array.Reverse(s);
return new string(s);
}
public static string Reverse(string source)
{
var parts = Regex.Split(source, #"([^a-zA-Z0-9])");
var results = new List<string>();
foreach(var x in parts)
{
results.Add(IsLettersOrDigits(x)
? Reverse(x.ToCharArray())
: x);
}
return string.Concat(results);
}
This is a solution without LINQ. I wasn't sure about what are considered special characters.
string sentence = "Marshall! Hello.";
List<string> words = sentence.Split(' ').ToList();
List<string> reversedWords = new List<string>();
foreach (string word in words)
{
char[] arr = new char[word.Length];
for( int i=0; i<word.Length; i++)
{
if(!Char.IsLetterOrDigit((word[i])))
{
for ( int x=0; x< i; x++)
{
arr[x] = arr[x + 1];
}
arr[i] = word[i];
}
else
{
arr[word.Length - 1 - i] = word[i];
}
}
reversedWords.Add(new string(arr));
}
string reversedSentence = string.Join(" ", reversedWords);
Console.WriteLine(reversedSentence);
And this is the output:
Updated Output = llahsraM! olleH.
Here is a non-regex version that does what you want:
var sentence = "Hello, john!";
var parts = sentence.Split(' ');
var reversed = new StringBuilder();
var charPositions = sentence.Select((c, idx) => new { Char = c, Index = idx })
.Where(_ => !char.IsLetterOrDigit(_.Char));
for (int i = 0; i < parts.Length; i++)
{
var chars = parts[i].ToCharArray();
for (int j = chars.Length - 1; j >= 0; j--)
{
if (char.IsLetterOrDigit(chars[j]))
{
reversed.Append(chars[j]);
}
}
}
foreach (var ch in charPositions)
{
reversed.Insert(ch.Index, ch.Char);
}
// olleH, nhoj!
Console.WriteLine(reversed.ToString());
Basically the trick is to remember the position of special (i.e. non letter or digit) characters and insert them at the end to those positions.
This solution is without LINQ and Regex. It may not be an efficient answer but working properly for small string values.
// This will reverse the string and special characters will just stay there.
public string ReverseString(string rString)
{
StringBuilder ss = new StringBuilder(rString);
int y = 0;
// The idea is to swap values. Like swapping first value with last one. It will keep swapping unless it reaches at the middle of the string where no swapping will be needed.
// This first loop is to detect first values.
for(int i=rString.Length-1;i>=0;i--)
{
// This condition is to check if the values is String or not. If it is not string then it is considered as special character which will just stay there at same old position.
if(Char.IsLetter(Convert.ToChar(rString.Substring(i,1))))
{
// This is second loop which is starting from end to swap values from end with first.
for (int k = y; k < rString.Length; k++)
{
// Again checking last values if values are string or not.
if (Char.IsLetter(Convert.ToChar(rString.Substring(k, 1))))
{
// This is swapping. So st1 is First value in that string
// st2 is the last item in that string
char st1 = Convert.ToChar(rString.Substring(k, 1));
char st2 = Convert.ToChar(rString.Substring(i, 1));
//This is swapping. So last item will go to first position and first item will go to last position, To make sure string is reversed.
// Remember when the string value is Special Character, swapping will move forward without swapping.
ss[rString.IndexOf(rString.Substring(i, 1))] = st1;
ss[rString.IndexOf(rString.Substring(k, 1))] = st2;
y++;
// When the swapping is done for first 2 items. The loop will stop to change the values.
break;
}
else
{
// This is just increment if value was Special character.
y++;
}
}
}
}
return ss.ToString();
}
Thanks!

How to extgract an integer and a two dimensional integer array from a combination of both in C#

I have an input as
2:{{2,10},{6,4}}
I am reading this as
string input = Console.ReadLine();
Next this input has to be passed to a function
GetCount(int count, int[,] arr)
{
}
How can I do so using C#?
Thanks
You could use RegularExpressions for extracting in an easy way each token of your input string. In the following example, support for extra spaces is included also (the \s* in the regular expressions).
Remember that always is a great idea to give a class the responsibility of parsing (in this example) rather than taking an procedural approach.
All the relevant lines are commented for better understanding.
Finally, i tested this and worked with the provided sample input strings.
using System;
using System.Text.RegularExpressions;
namespace IntPairArrayParserDemo
{
class Program
{
static void Main(string[] args)
{
var input = "2:{{2,10},{6,4}}";
ParseAndPrintArray(input);
var anotherInput = "2 : { { 2 , 10 } , { 6 , 4 } }";
ParseAndPrintArray(anotherInput);
}
private static void ParseAndPrintArray(string input)
{
Console.WriteLine("Parsing array {0}...", input);
var array = IntPairArrayParser.Parse(input);
var pairCount = array.GetLength(0);
for (var i = 0; i < pairCount; i++)
{
Console.WriteLine("Pair found: {0},{1}", array[i, 0], array[i, 1]);
}
Console.WriteLine();
}
}
internal static class IntPairArrayParser
{
public static int[,] Parse(string input)
{
if (string.IsNullOrWhiteSpace(input)) throw new ArgumentOutOfRangeException("input");
// parse array length from string
var length = ParseLength(input);
// create the array that will hold all the parsed elements
var result = new int[length, 2];
// parse array elements from input
ParseAndStoreElements(input, result);
return result;
}
private static void ParseAndStoreElements(string input, int[,] array)
{
// get the length of the first dimension of the array
var expectedElementCount = array.GetLength(0);
// parse array elements
var elementMatches = Regex.Matches(input, #"{\s*(\d+)\s*,\s*(\d+)\s*}");
// validate that the number of elements present in input is corrent
if (expectedElementCount != elementMatches.Count)
{
var errorMessage = string.Format("Array should have {0} elements. It actually has {1} elements.", expectedElementCount, elementMatches.Count);
throw new ArgumentException(errorMessage, "input");
}
// parse array elements from input into array
for (var elementIndex = 0; elementIndex < expectedElementCount; elementIndex++)
{
ParseAndStoreElement(elementMatches[elementIndex], elementIndex, array);
}
}
private static void ParseAndStoreElement(Match match, int index, int[,] array)
{
// parse first and second element values from the match found
var first = int.Parse(match.Groups[1].Value);
var second = int.Parse(match.Groups[2].Value);
array[index, 0] = first;
array[index, 1] = second;
}
private static int ParseLength(string input)
{
// get the length from input and parse it as int
var lengthMatch = Regex.Match(input, #"(\d+)\s*:");
return int.Parse(lengthMatch.Groups[1].Value);
}
}
}
Not to do your work for you, you will first have to parse the whole string to find the individual integers, either using regular expressions or, as I would do it myself, the string.Split method. Then parse the substrings representing the individual integers with the int.Parse or the int.TryParse methods.
I doubt you're going to get a serious parsing answer for your custom format. If you NEED to have the value inputted that way, I'd look up some info on regular expressions. If that's not powerful enough for you, there are some fairly convienient parser-generators you can use.
Alternatively, the much more realistic idea would be something like this:
(NOTE: Haven't tried this at all... didn't even put it in VS... but this is the idea...)
int rows = 0;
string rowsInput = "";
do {
Console.Write("Number of rows:");
rowsInput = Console.ReadLine();
} while (!Int32.TryParse(rowsInput, out rows);
int columns = 0;
string columnsInput = "";
do {
Console.Write("Number of columns:");
string columnsInput = Console.ReadLine();
} while (!Int32.TryParse(columnsInput, out columns);
List<List<int>> values = new List<List<int>>();
for (int i = 0; i < rows; i++)
{
bool validInput = false;
do {
Console.Write(String.Format("Enter comma-delimited integers for row #{0}:", i.ToString()));
string row = Console.ReadLine();
string[] items = row.split(',');
int temp;
validInput = (items.Length == columns) && (from item in items where !Int32.TryParse(item, out temp) select item).count() == 0;
if (validInput)
{
values.add(
(from item in items select Convert.ToInt32(item)).ToList()
);
}
} while (!validInput);
}

Categories