Действительно ли возможно реализовать ограниченный по объему, привязывают C#?

str[i] эквивалентно *(str + i) и str[i][j] эквивалентно *(*(str + i) + j).
В вашем коде вы используете (*(str + i) + j), что неверно.

Когда char *[] перейдет к функции, оно уменьшится до char **. Итак, в bigLetters() вы можете указать char **str в качестве параметра. Кроме того, это соответствует вашему требованию - запрещено использовать оператор [] .

Вместо жесткого кодирования измерения SIZE в char *strArr[SIZE], вы можете дать пустое [] и позволить компилятору назначить измерение на основе размера инициализатора. В вашем случае размер инициализатора равен 4, как вы дали 4 строк в инициализаторе strArr. Вы можете вычислить размер strArr следующим образом:

sizeof(strArr)/sizeof(strArr[0]);

Вы можете сделать:

#include <stdio.h>
#include <stdlib.h>

char *bigLetters(char **str, size_t size) {

        char *strNew = calloc(size + 1, 1); // sizeof(char) is always 1
                                            // calloc will initialize all bytes in the allocated storage to zero.
                                            // You dont need to add the null terminating character at the end of strNew
        if (strNew == NULL)
                exit(EXIT_FAILURE);

        for (size_t i = 0; i < size; i++) {
                for (size_t j = 0; *(*(str + i)+j) != '\0'; j++) {
                        if (*(*(str + i) + j) > *(strNew + i)) {
                                // You can directly fill the allocated memory with biggest ASCII
                                *(strNew + i) = *(*(str + i) + j);
                        }
                }
        }

        return strNew;
}

int main(void) {
        char *strArr[] = { "hello", "and", "good", "morning" };

        char *res = bigLetters(strArr, sizeof(strArr)/sizeof(strArr[0]));

        if (res != NULL) {
                printf("The new string is --> %s\n", res);
                free (res);
        }
        else
                printf("bigLetters returned NULL\n");

        return 0;
}

Обратите внимание, что void тип возвращаемого значения main() не соответствует стандарту. Вместо этого вы должны использовать int в качестве возвращаемого типа main().

5
задан Motti 3 December 2008 в 13:32
поделиться

5 ответов

Ваше понимание относительно using является неправильным, это - способ определить объем действий, происходят детерминированным способом (никакая организация очередей к GC не происходит).

C# предоставляет lock ключевое слово, которое обеспечивает монопольную блокировку и если Вы хотите иметь различные типы (например, Чтение-запись) необходимо будет использовать using оператор.

P.S. Этот поток может заинтересовать Вас.

5
ответ дан 18 December 2019 в 06:36
поделиться

Для усиления ответа Timothy оператор блокировки действительно создает ограниченную по объему блокировку с помощью монитора. По существу это переводит во что-то вроде этого:

lock(_lockKey)
{
    // Code under lock
}

// is equivalent to this
Monitor.Enter(_lockKey)
try
{
     // Code under lock
}
finally
{
    Monitor.Exit(_lockKey)
}

В C# Вы редко используете dtor для этого вида шаблона (см. использование statement/IDisposable). Одна вещь, которую можно заметить в коде, является этим, если асинхронное исключение происходит между Монитором. Войдите и попытка, похоже, что монитор не будет выпущен. JIT на самом деле делает специальную гарантию этим если Монитор. Войдите сразу предшествует, попытка блокируются, асинхронного исключения не произойдет до блока попытки, таким образом гарантирующего выпуск.

12
ответ дан 18 December 2019 в 06:36
поделиться

Это верно, что Вы не знаете точно, когда dtor собирается работать..., но, если Вы реализуете интерфейс IDisposable и затем используете или блок 'использования' или вызов, 'Располагают ()' сами, у Вас будет место для помещения кода.

Вопрос: при высказывании "блокировки" Вы имеете в виду блокировку потока так, чтобы только один поток за один раз мог использовать объект? Как в:

lock (_myLockKey) { ... }

Разъяснитесь.

4
ответ дан 18 December 2019 в 06:36
поделиться

Для полноты существует другой способ достигнуть подобного эффекта RAII без использования using и IDisposable. В C# using обычно более ясно (см. также здесь еще для некоторых мыслей), но на других языках (например, Java), или даже в C#, если using не является соответствующим по некоторым причинам, полезно знать.

Это - идиома, названная, "Выполняются Вокруг", и идея состоит в том, что Вы называете метод, который делает пред и отправляет материал (например, блокировка/разблокирование Ваших потоков, или установка и фиксация / закрытие Вашего соединения с БД и т.д.), и Вы передаете в тот метод делегата, который реализует операции, Вы хотите произойти промежуточные.

например:


funkyObj.InOut( delegate{ System.Console.WriteLine( "middle bit" ); } );

В зависимости от того, что делает метод InOut, вывод мог бы быть чем-то как:

first bit
middle bit
last bit

Как я говорю, этот ответ для полноты только, предыдущих предложений using с IDisposable, а также lock ключевое слово, будут лучшими 99% времени.

Это - позор, который, в то время как .NET пошел далее, чем много других современных языков OO в этом, расценивает (я смотрю на Вас, Java), это все еще возлагает ответственность за RAII для работы над клиентским кодом (т.е. код, который использует using), тогда как в C++ деструктор будет всегда работать в конце объема.

3
ответ дан 18 December 2019 в 06:36
поделиться

Я был действительно побеспокоен фактом это using до разработчика, чтобы не забыть делать - в лучшем случае Вы получаете предупреждение, которое большинство людей никогда не потрудилось способствовать ошибке. Так, я играл с идеей как это - она вынуждает клиент, по крайней мере, ПОПЫТАТЬСЯ сделать вещи правильно. К счастью, и к сожалению, это - закрытие, таким образом, клиент мог все еще сохранить копию ресурса и попытаться использовать его снова позже - но этот код, по крайней мере, пытается продвинуть клиент в правильном направлении...

public class MyLockedResource : IDisposable
{
    private MyLockedResource()
    {
        Console.WriteLine("initialize");
    }

    public void Dispose()
    {
        Console.WriteLine("dispose");
    }

    public delegate void RAII(MyLockedResource resource);

    static public void Use(RAII raii)
    {
        using (MyLockedResource resource = new MyLockedResource())
        {
            raii(resource);
        }
    }

    public void test()
    {
        Console.WriteLine("test");
    }
}

Хорошее использование:

MyLockedResource.Use(delegate(MyLockedResource resource)
{
    resource.test();
});

Плохое использование! (К сожалению, это не может быть предотвращено...),

MyLockedResource res = null;
MyLockedResource.Use(delegate(MyLockedResource resource)
{
    resource.test();
    res = resource;
    res.test();
});
res.test();
0
ответ дан 18 December 2019 в 06:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: