change characters position and add space between them in c# - c#

how would you change the position of the last two characters in a string and add space between them in c#?
for example, i have a simple string "apple" and it needs to be changed to "appe l".
I have tried several things but without any success.
thanks in advance for all the answers.

In one line:
string s = "apple";
s = $"{s.Substring(0, s.Length - 2)}{s[s.Length - 1]} {s[s.Length - 2]}";

string s = "apple";
var sb = new StringBuilder(s);
var temp = sb[sb.Length - 2];
sb[sb.Length - 2] = sb[sb.Length - 1];
sb[sb.Length - 1] = temp;
sb.Insert(s.Length - 1, " ");
s = sb.ToString();

In C# string type is immutable, which means you cannot modify a string that is already created. If you need multiple modifications done, the usual way is to use StringBuilder class
string s = "apple";
var buf = new StringBuilder(s);
var ch = buf[buf.Length - 1];
buf[buf.Length - 1] = buf[buf.Length - 2];
buf[buf.Length - 2] = ch;
buf.Insert(s.Length - 1, ' ');

You can convert your string into char Array by using string.ToCharArray() method. After this interchange last 2 characters and then add space between them, just like this:
static void Main(string[] args)
{
string fruit = "apple";
char[] charFruit = fruit.ToCharArray();
char temp = charFruit[charFruit.Length - 1]; // holds the last character of the string
charFruit[charFruit.Length - 1] = charFruit[charFruit.Length - 2]; //interchnages the last two characters
charFruit[charFruit.Length - 2] = temp;
fruit = "";
for (int i = 0; i < charFruit.Length; i++){
if (i == charFruit.Length - 2){
fruit += charFruit[i].ToString();
fruit += " ";
}
else
fruit += charFruit[i].ToString();
}
Console.WriteLine(fruit);
}

Related

Odd System.IndexOutOfRangeException when trying to overwrite .txt file c#

I want to extend a data collection in a .txt file.
I'm reading a .txt file into a string array. Then I'm making a new string array with 5 more elements.
string oldarray[] = File.ReadAllLines(targetfile); //it is correctly reading the file
string newarray[] = new string[oldarray.Count()+5];
for (int i = 0; i < oldarray.Count(); i++) { //copy old array into new bigger one
newarray[i] = oldarray[i];
}
newarray[oldarray.Count() + 1] = "Data1"; //fill new space with data
newarray[oldarray.Count() + 2] = "Data2";
newarray[oldarray.Count() + 3] = "Data3";
newarray[oldarray.Count() + 4] = "Data4";
newarray[oldarray.Count() + 5] = " "; //spacer
//now write new array into same textfile over old data
File.WriteAllLines(targetfile, newarray); //System.IndexOutOfRangeException
I also tried writing line by line to the file like so, but it did just spit out the same exception:
using (StreamWriter writer = new StreamWriter(destinationFile)) //System.IndexOutOfRangeException
{
for (int i = 0; i < newarray.Length; i++)
{
writer.WriteLine(newarray[i]);
}
}
Why does it do that, and how do I fix it?
You're off by one - the last element in olaArray is at oldarray.Count() - 1, not oldarray.Count()
for (int i = 0; i < oldarray.Count(); i++){ //copy old array into new bigger one
newarray[i] = oldarray[i];
}
newarray[oldarray.Count()] = "Data1"; //fill new space with data
newarray[oldarray.Count() + 1] = "Data2";
newarray[oldarray.Count() + 2] = "Data3";
newarray[oldarray.Count() + 3] = "Data4";
newarray[oldarray.Count() + 4] = " "; //spacer
Array indexes are zero-based so oldarray.Count() + 5 points to an element after the end of the array. The first element is left empty too.
This could be fixed by fixing the indexes to be between 0 and 4 instead of 1 and 5. A better solution though would be to load the lines as a list and append the new strings :
string lines = File.ReadLines(targetfile).ToList();
var newLines=new[] {"Data1","Data2"...};
lines(newLines);
File.WriteAllLines(targetfile, lines);
Or even
var newLines=....;
string lines = File.ReadLines(targetfile)
.Concat(newLines)
.ToList();
File.WriteAllLines(targetfile, lines);
ReadAllLines uses a List as well and returns a copy of the list as an array. ReadLines on the other hand, returns lines one at a time as an IEnumerable<string>. The file remains open as long as the IEnumerable is iterated, so we need ToList() to consume it and allow the file to close before overwriting it.
The index oldarray.Count() + 5 does not exist in your new array.
Array indexing starts from zero. If you have an array with 10 elements then the first index is 0 and the last index is 9. If you make a new array with oldarray.Count() + 5 items it'll have 15 items and the last index will be 14 (not oldArray.Count + 5 which equals 15).
Just do like this:
newarray[oldarray.Count()] = "Data1";
newarray[oldarray.Count() + 1] = "Data2";
newarray[oldarray.Count() + 2] = "Data3";
newarray[oldarray.Count() + 3] = "Data4";
newarray[oldarray.Count() + 4] = " ";

Trying to move elements in an array instead replaces elements

So, my assignment is that I have to make a program that changes a string and places it in the right order. Now, it is only allowed to do 3 things, one of which I have a question about. It is allowed to take the second character and move it to the third, etc., until you arrive at the second to last character. This one gets replaced by the third to last character. So, abcdef would become aebcdf. My code gives me as output aebbbf. I have this:
class Program{
static void Main(string[] args)
{
var p = new Program();
string input = Console.ReadLine();
char[] characters = new char[input.Length];
characters = input.ToCharArray();
string answer = Console.ReadLine();
if (answer == "x")
{
p.MethodX(characters);
string s = new string(characters);
Console.WriteLine(s);
}
Console.ReadKey();
}
}
And the method MethodX:
public void MethodeX(char[] input)
{
int lengthText = input.Length;
char temp = input[lengthText - 2];
for (int i = 1; i < input.Length - 2; i++)
{
input[i + 1] = input[i];
input[1] = temp;
}
}
Thanks in advance for the help!
Let's have a look at what the method does, exactly.
Assuming the string is abcdef, the derived array has the length 6. 6-2 is 4, so temp should be e - which is correct.
Now the iteration starts at 1, so b. 2, so array element 3 (c), gets replaced by b.
Next iteration: The next character after array element 2 (b) is now also b... As c got replaced by b. So d gets replaced by b, also!
And same goes for e. Output: aebbbf.
A solution could be this:
public char[] Xmethod(char[] input)
{
char[] outputArray = input;
char temp = input[6-2];
for(int i = 1; i < input.Length -2; i++)
{
outputArray[i+1] = input[i];
}
outputArray[1] = temp;
return outputArray
}
Hope this helped.
EDIT: in an earlier version I made a mistake when creating the outputArray. It is fixed now.

Getting System.Char[] instead of value

I'm trying to convert double to binary, but when I run my project, I get System.Char[] in my text box instead of binary values. How can I solve this problem?
int bitCount = sizeof(float) * 8;
char[] result = new char[bitCount];
int intValue = System.BitConverter.ToInt32(BitConverter.GetBytes(testvalue), 0);
for (int bit = 0; bit < bitCount; ++bit)
{
int maskedValue = intValue & (1 << bit);
if (maskedValue > 0)
maskedValue = 1;
result[bitCount - bit - 1] = maskedValue.ToString()[0];
}
new string(result);
richTextBox1.Text = richTextBox1.Text+"\n"+result;
// pictureBox2.Image = bmp;
new string(result);
This is the problem. You do not assign this to any variable. I believe you should use it instead of result when you assing to textbox.Text.
You get System.Char[] in your text box, because ToString() for char arrays returns such a string.
So try following:
String resultString = new string(result);
richTextBox1.Text = richTextBox1.Text + Environment.NewLine + resultString;

Masking all characters of a string except for the last n characters

I want to know how can I replace a character of a string with condition of "except last number characters"?
Example:
string = "4111111111111111";
And I want to make it that
new_string = "XXXXXXXXXXXXX1111"
In this example I replace the character to "X" except the last 4 characters.
How can I possibly achieve this?
Would that suit you?
var input = "4111111111111111";
var length = input.Length;
var result = new String('X', length - 4) + input.Substring(length - 4);
Console.WriteLine(result);
// Ouput: XXXXXXXXXXXX1111
How about something like...
new_string = new String('X', YourString.Length - 4)
+ YourString.Substring(YourString.Length - 4);
create a new string based on the length of the current string -4 and just have it all "X"s. Then add on the last 4 characters of the original string
Here's a way to think through it. Call the last number characters to leave n:
How many characters will be replaced by X? The length of the string minus n.
How can we replace characters with other characters? You can't directly modify a string, but you can build a new one.
How to get the last n characters from the original string? There's a couple ways to do this, but the simplest is probably Substring, which allows us to grab part of a string by specifying the starting point and optionally the ending point.
So it would look something like this (where n is the number of characters to leave from the original, and str is the original string - string can't be the name of your variable because it's a reserved keyword):
// 2. Start with a blank string
var new_string = "";
// 1. Replace first Length - n characters with X
for (var i = 0; i < str.Length - n; i++)
new_string += "X";
// 3. Add in the last n characters from original string.
new_string += str.Substring(str.Length - n);
This might be a little Overkill for your ask. But here is a quick extension method that does this.
it defaults to using x as the masking Char but can be changed with an optional char
public static class Masking
{
public static string MaskAllButLast(this string input, int charsToDisplay, char maskingChar = 'x')
{
int charsToMask = input.Length - charsToDisplay;
return charsToMask > 0 ? $"{new string(maskingChar, charsToMask)}{input.Substring(charsToMask)}" : input;
}
}
Here a unit tests to prove it works
using Xunit;
namespace Tests
{
public class MaskingTest
{
[Theory]
[InlineData("ThisIsATest", 4, 'x', "xxxxxxxTest")]
[InlineData("Test", 4, null, "Test")]
[InlineData("ThisIsATest", 4, '*', "*******Test")]
[InlineData("Test", 16, 'x', "Test")]
[InlineData("Test", 0, 'y', "yyyy")]
public void Testing_Masking(string input, int charToDisplay, char maskingChar, string expected)
{
//Act
string actual = input.MaskAllButLast(charToDisplay, maskingChar);
//Assert
Assert.Equal(expected, actual);
}
}
}
StringBuilder sb = new StringBuilder();
Char[] stringChar = string.toCharArray();
for(int x = 0; x < stringChar.length-4; x++){
sb.append(stringChar[x]);
}
sb.append(string.substring(string.length()-4));
string = sb.toString();
I guess you could use Select with index
string input = "4111111111111111";
string new_string = new string(input.Select((c, i) => i < input.Length - 4 ? 'X' : c).ToArray());
Some of the other concise answers here did not account for strings less than n characters. Here's my take:
var length = input.Length;
input = length > 4 ? new String('*', length - 4) + input.Substring(length - 4) : input;
lui,
Please Try this one...
string dispString = DisplayString("4111111111111111", 4);
Create One function with pass original string and no of digit.
public string DisplayString(string strOriginal,int lastDigit)
{
string strResult = new String('X', strOriginal.Length - lastDigit) + strOriginal.Substring(strOriginal.Length - lastDigit);
return strResult;
}
May be help you....
Try this:
String maskedString = "...."+ (testString.substring(testString.length() - 4, testString.length()));
Late to the party but I also wanted to mask all but the last 'x' characters, but only mask numbers or letters so that any - ( ), other formatting, etc would still be shown. Here's my quick extension method that does this - hopefully it helps someone. I started with the example from Luke Hammer, then changed the guts to fit my needs.
public static string MaskOnlyChars(this string input, int charsToDisplay, char maskingChar = 'x')
{
StringBuilder sbOutput = new StringBuilder();
int intMaskCount = input.Length - charsToDisplay;
if (intMaskCount > 0) //only mask if string is longer than requested unmasked chars
{
for (var intloop = 0; intloop < input.Length; intloop++)
{
char charCurr = Char.Parse(input.Substring(intloop, 1));
byte[] charByte = Encoding.ASCII.GetBytes(charCurr.ToString());
int intCurrAscii = charByte[0];
if (intloop <= (intMaskCount - 1))
{
switch (intCurrAscii)
{
case int n when (n >= 48 && n <= 57):
//0-9
sbOutput.Append(maskingChar);
break;
case int n when (n >= 65 && n <= 90):
//A-Z
sbOutput.Append(maskingChar);
break;
case int n when (n >= 97 && n <= 122):
//a-z
sbOutput.Append(maskingChar);
break;
default:
//Leave other characters unmasked
sbOutput.Append(charCurr);
break;
}
}
else
{
//Characters at end to remain unmasked
sbOutput.Append(charCurr);
}
}
}
else
{
//if not enough characters to mask, show unaltered input
return input;
}
return sbOutput.ToString();
}

Editing a line in a text file without using pointers?

I am trying to edit a line of a text file (.Hex file) containing all Hex characters without using pointers and in a more efficient way.
It takes so long because the program I have to edit some (around 30x4 bytes or 30 float values from the address values of hex file).
Every time the program replaces one byte, it searches the complete file and replaces the values, and copy back back again the new file to another file. This process repeats 30 times, which is quite time consuming and hence not looks appropriate.
What would be the most efficient method?
public static string putbyteinhexfile(int address, char data, string total)
{
int temph, temphl, tempht;
ushort checksum = 0;
string output = null, hexa = null;
StreamReader hex;
RegistryKey reg = Registry.CurrentUser;
reg = reg.OpenSubKey("Software\\Calibratortest");
hex = new StreamReader(((string)reg.GetValue("Select Input Hex File")));
StreamReader map = new StreamReader((string)reg.GetValue("Select Linker Map File"));
while ((output = hex.ReadLine()) != null)
{
checksum = 0;
temph = Convert.ToInt16(("0x" + output.Substring(3, 4)), 16);
temphl = Convert.ToInt16(("0x" + output.Substring(1, 2)), 16);
tempht = Convert.ToInt16(("0x" + output.Substring(7, 2)), 16);
if (address >= temph &&
address < temph + temphl &&
tempht == 0)
{
output = output.Remove((address - temph) * 2 + 9, 2);
output = output.Insert((address - temph) * 2 + 9,
String.Format("{0:X2}", Convert.ToInt16(data)));
for (int i = 1; i < (output.Length - 1) / 2; i++)
checksum += (ushort)Convert.ToUInt16(output.Substring((i * 2) - 1, 2), 16);
hexa = ((~checksum + 1).ToString("x8")).ToUpper();
output = output.Remove(temphl * 2 + 9, 2);
output = output.Insert(temphl * 2 + 9,
hexa.Substring(hexa.Length - 2, 2));
break;
}
else total = total + output + '\r' + '\n';
}
hex.Close();
map.Close();
return total;
}
Assuming you don't want to massively rewrite your existing logic which does 'for each line, do this search and replace logic', I'd think the simplest change would be:
var lines = File.ReadAllLines(filePath);
foreach (change to make)
{
for (int i = 0; i < lines.Length; i++)
{
// read values from line
if (need_to_modify)
{
// whatever change logic you want here.
lines[i] = lines[i].Replace(...);
}
}
}
File.WriteAllLines(filePath, lines);
Basically, you'll still do the logic you have now, except:
You read the file once instead of N times
you get rid of streamreader / streamwriter work
you do your changes on the array of strings in memory
string fileName = "blabla.hex";
StreamReader f1 = File.OpenText(fileName);
StreamWriter f2 = File.CreateText(fileName + ".temp_");
while (!f1.EndOfStream)
{
String s = f1.ReadLine();
//change the content of the variable 's' as you wish
f2.WriteLine(s);
}
f1.Close();
f2.Close();
File.Replace(fileName + ".temp_", fileName, null);

Categories