Въпрос за кастване при елементи от масив


2
Здравейте.
Имам следния проблем, на който се натъкнах при решаването на задачата Excell Columns. Искам да взимам десетичната стойност на главните букви от ASCII таблицата и да ги приравня на A=1, B=2 и т.н.
В други задачи съм го правил и работи- например това:
string letters = "AB"; int a; a = (int)letters[0]; Console.WriteLine(a); //връща 65 a = (int)letters[1]; Console.WriteLine(a); //връща 66

В тази задача реших да го направя същото, но елементите да са от масиви и не се получава:
string[ ] letters= new string [10];
int[ ] a=new int[10];
и например при:
for(i=0;i<10;i++)
{
a[ i ] = (int)letters[ i ]; ----ERROR->cannot convert type string to int
}
Ще съм благодарен за съвет дали е възможно да се направи това чрез масиви или да търся друг път.



Отговори



2

Опитай по следния начин

 string[] letters = new string[10];
 
            int[] a = new int[10];
 
 
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = Convert.ToInt32(letters[i]);
            }



0
Да, но така като сложи в letters някакъв стринг и гърми.

от cchapo (583 точки)

0
Мда, прав си. Трябва да е само digits в letters в този случай.



1
По скоро така би станало по-добре:
char[] letters = new char[] { 'A', 'B' };
byte[] a = Encoding.ASCII.GetBytes(letters);
foreach (var item in a) { Console.WriteLine(item); }
Принтирва се 65 и 66. Дано съм помогнал.
Успех!

от cchapo (583 точки)


2
В първия пример "търкаляш" по единс тринг и взимаш един негов елемент, който е char.
Във втория имаш масив от стрингове, всеки елемент от който е стринг. Не можеш да кастнеш директно стринг към инт, тъй като няма гаранция че в стринга ще има само цифри.
в първия пример имаш 1 ред текст, всяка буквичка от него е char, който има "вълшебното" свойство да е знак и число едновременно. Но за съжаление може да е само един символ дълъг.
Във втория ... имаш 10 реда текст, като всеки ред съдържа много знаци, които моце да са цифри, а може и да не са.
Не е ясно какво искаш да направиш. Дефинирай си желанието по-конкретно, за да ти дадем конкретен отгвор. Нямам нерви да търся условието на адачата - дай линк поне.

от JulianG (5316 точки)


0
С две думи условието: Въвеждат се главните букви A до Z и се индексират като А=1,Z=26, AA=27 и т.н. Общо взето се калкулира индекс, които се получава чрез формула. Идеята ми е да взимам десетичната стойностт от ASCII таблицата , да вадя от нея 64 и да получавам индекс.

от b_ivanov (53 точки)


1

Здравей, хубава задачка :)

Опитай така:

string[ ] letters= new string [10];

int[ ] a=new int[10];

for(i=0;i<10;i++)

{

    a[ i ] = (int) letters[ i ] [ 0 ];

}

Когато работиш с масив от стрингове и ги обработваш, използвайки представянето на всеки от тях като масив от символи, фактически имаш назъбен (както ме поправи @easlavov) масив. За да достъпиш първия символ на всеки стринг, трябва да използваш неговия индекс, който е 0.

Дава ти грешка, защото се опитваш да кастнеш не първия символ, а целия стринг.

Едит: назъбен масив е правилно.

Edit1: А ако съм разбрала правилно и истинската ти цел е да получиш масив от номерата на първите букви от стринговете в изходния масив, а те започват с главни латински букви, това е едно примерно решение:

            string[] letters ={"Adhg","BDRFUTfty","Cdhg","DRFUTfty","Edhg",

                               "FDRFUTfty","Gdhg","HDRFUTfty","Idhg","JDRFUTfty",};

            int[] letterNumber = new int[10];

            for(int i=0;i<10;i++)

            {

                letterNumber[i]=letters[i][0] - 65 + 1;
                Console.WriteLine(letterNumber[i]);

            }


от ellapt (6303 точки)


0
Не трябва ли да е letters[i][0]; ? Т.е. не двумерен, ами назъбен масив се получава. Достъпваш нулевия елемент от стринга на позиция i в масива от стрингове.

от easlavov (4118 точки)

0
Да, сигурно е назъбен - е даде грешка за двумерен, защото letters е едномерен, благодаря! Ще го проиграя, но след малко :-).

от ellapt (6303 точки)


1
Здравей,
Според мен търсиш ето това решение. Като при кастването трябва да дадеш нулевия елемент на стринга. Ако масива letters e от тип char[] - можеше да стане директно с твоя код
 
string[] letters = new string[10]{"A","B","C","D","E","F","G","H","I","J"};
 
            int[] a = new int[10];
 
            for (int i = 0; i < 10; i++)
            {
 
                a[i] = (int)letters[i][0]
                Console.WriteLine(a[i]);
            }

от bankoff (3997 точки)


2

"..Искам да взимам десетичната стойност на главните букви от ASCII таблицата и да ги приравня на A=1, B=2 и т.н..."

Изцяло подвеждащо условие на задача :) Отделете една минута отново и си отговорете трябва ли да "преиндексирате"  стойностите на главните букви (A(65) - A(1)???) след като абстрактно те винаги имат еднаква тежест за вас - от А до Z са 26 стойности и въобще не ме интересува дали А ще е 1 или 65. И както отбеляза juliang, char имат магическото свойство да бъдат едновременно знак и число!

//char is number!  A=65,  Z=90,  AZ "length" = 26

result  +=

                (long)((charInput - 64) * Math.Pow(26, numberN - 1));     
 
Math.Pow(26, numberN - 1) - най-изчанчения вариант на побитова маска :))) (не е точно маска, но върши работа да ви изчисли тежестта на чара на позиция N в резултата)

от redOne (0 точки)


2

Хора. четете си УСЛОВИЕТО!!! Добре прочетеното условие е половин решена задача.

Никой не пейства условието, така че трябва аз да си го търся. А в него се казва следното:

"On each of the next N lines there will be a single character. All characters together construct a column identifier."

Виждате ли какво пише? "Single character". Значи, подава ви се броя знаци N и N реда от по 1 знак. Какъв назъбен масив, к'ви 5 лева?

входа ви ще бъде следния:

5

А

С

Е

Р

К

- винаги по един знак на ред.

И за да не си усложнявате излишно работата четейки char, можете да напавите следното (пиша без да тествам, ако има някаква грешка сори);

            int n = int.Parse(Console.ReadLine());
            int sum = 0;
            for (int i = 0; i < n; i++)
            {
                sum = sum * 26 + Console.ReadLine()[0] - 64;
                
            }
            Console.WriteLine(sum);
 

Малко обяснение:

сумата е нула, при първото минаване първо я умножавам с 26 (пак си остава нула) и прибавям първия (той би трябвало да е и единствен съгласно условието) знак от стринга, който съм прочел от клавиатурата. Обаче взимайки с [0] знак от  стринг (какъвто тип връща readLine), той става char и придобива магичсткото свойство да е и число. От това число вадя 64 (вижте кодовете в ASCII таблицата и ще разберете защо точно 64) и тогава го прибавям към сумата.

При следващото минаване сумата се умножава по 26 (вместо да ползвам безумно бавната Math.Pow() функция) и отново прибавям каквото ми се подаде от клавиатурата като следваща стойност.

Няма масиви. Каквото ми се подаде като вход, го използвам на момента.

Да, малко е нечетим кода за начинаещи, но ...  трябва отрано да свиквате да ползвате разни хитринки. Примерно да се сетите че Console.ReadLine с нищо не се различава от стринговата променлива s, и че върху ReadLine можете да изпълнявате същите операции както върху стринг.

 

Ако въведете 

3

А

В

С

цикъла ще се извърти 3 пъти и ще сметне

1: 0+1(ascii кода на "А"-64)

2:1 (резултата от горе)*26+2(ascii кода на "В"-64)

3: ((1*26+2)(резултата отгоре)*26+3(ascii кода на "С"-64)

няма никаква нужда от безумно бавната Math.Pow


от JulianG (5316 точки)


0
Ако искате да си упражнявате побитовите операции: sum = sum * 26 + (Console.ReadLine()[0] & 0x1F); или пък с остатък от делене на 64: sum = sum * 26 + (Console.ReadLine()[0] % 64);

от JulianG (5316 точки)

0
ако "отговаряш" на мен, направи го като коментар под моя пост! Понеже аз отговарям на задалия въпроса, даже съм сложил в началото текст на какво точно отговарям. Не използвам никакви масиви за тази задача. Решил съм да използвам Math.Pow според момента. Ако съм на изпит въобще няма да се замисля ако задачата ми дава 100 % да търся по изпилено и елегантно решение. И последно - чел съм условието достатъчно дълго за да си измисля собствено решение. Поздрави

от redOne (0 точки)



1
И като казах "побитови операции"... черпя една бира първия (от есенния прием), който направи сметката
sum = sum * 26 + (Console.ReadLine()[0] & 0x1F);
без да ползва знака за умножение :)

от JulianG (5316 точки)


0
sum = (sum << 4) + (sum << 3) + (sum << 1) + (Console.ReadLine()[0] & 0x1F);
Това е по-бавно от директно умножение, нали така? Въпреки, че шифтинга е по-бърз, събиранията бавят. Даже направих тест и се потвърди.

от skaniol (90 точки)


1
Здравейте отново.
Неслучайно не зададох условието на задачата в първия постинг- решението е ясно, може да се получи и по друг начин...
Разгорелият се спор е излишен.
Просто ме интересуваше защо нещата не се получават когато са с масив в примера, който дадох. А това, че въпросът възникна в конкретната задача е случайност.
Сега разбрах- просто трябва ( не знам дали се изразявам правилно) второ индексиране за масива когато е от стрингове или директно да се ползва свойството на чаровете-> числа.
За мен беше изключително полезно.
Благодаря на всички!

от b_ivanov (53 точки)