Здесь Вы выделяете гораздо больше байт, чем Вам нужно,ss = (char*)calloc(n, sizeof(char*)); // выделяем память под строку
sizeof(char*)
будет равен 8 на 64 битных архитектурах, когда sizeof(char)
- 1. Но при этом стоит не забывать про место под '\0'
в конце строки.Почитайте, что делает функцияgets(ss); printf("Введите свое слово (не забываем про длину строки): "); scanf("%s", ss);
ss = (char*)realloc(i, sizeof(char*)); gets(ss);
gets
. Опять же проблема с размерами символа. Ну и у realloc
несколько другая сигнатура. И вообще realloc
достаточно недешевая операция, не за чем ее делать в цикле много раз над одним указателем, достаточно 1 раз в конце.Проверку на NULL нужно делать сразу после аллокации памяти. А вот в цикле ее делать незачем.if (ss[i] != NULL) // проверка на нулевой указатель
Операцияss[j] = ss[j++];// здесь я заменял тот символ на следующий, тем самым перекидывая его в конец
j++
меняет j
.Операцияfor (int i = 0; i < sizeof(ss); i++)// ну а тут пытался поменять размер
sizeof(ss)
даст размер char*
, то есть размер указателя, что соответствует 8 на 64 битных архитектурах. Для вычисления длины строки (терминированной символом '\0'
) есть функция strlen
. А в данном случае вообще можно посчитать количество удаленных символов и из него вычислить длину результирующей строки, что будет дешевле.Я подумываю сделать проверку символов до и после запятой, но не знаю, как это сделать. Помоги мне, пожалуйста.Проверяйте на число символы
in[indexIN - 1]
и in[indexIN + 1]
, при этом стоит учесть выход за границу при indexIN == 0
.#define IS_DIGIT(I) (in[(I)] >= '0' && in[(I)] <= '9')
if (IS_DIGIT(indexIN) || (in[indexIN] == ',' && indexIN != 0 && IS_DIGIT(indexIN - 1) && IS_DIGIT(indexIN + 1)))
indexIN++;
Насколько критичной проблемой для программиста является ручное управление памятью, которое называют недостатком языка Си?Неосвобожденная память (утечка памяти) - это самое безобидное, что может произойти.
Новый язык программирования Раст, как заявляют, лишен этого недостатка
но разве число ошибок в программе зависит именно от наличия или отсутствия ручного управления памятьюВ Rust ручное управление памятью, как и в C и в C++, просто есть культура, что если некая структура аллоцировала память, то она ее освободит. Всякие Vec, Box и т.д. делают это в Drop. В C++ многие повседневные типы так же освобождают в деструкторе память, которую они выделили. Однако в Rust есть разделение на safe и unsafe код и для прикладного программирования safe возможностей более чем достаточно. В C++ же весь код unsafe.
разве общее число ошибок не перераспределяется на другие недостатки программыНет, не перераспределяется. Хорошая система типов действительно может избавить от многих ошибок, что в целом сделает ПО более надежным. Но надо понимать, что от всех ошибок не избавит ни что. Банальная дискоммуникация с заказчиком порождает огромное число багов.
являются ли ошибки с памятью ошибками программиста, а не компилятора и языка программированияБезусловно это ошибки программиста. Программисты, как правило, - это люди, а людям свойственно ошибаться. И хорошо, когда есть средства статического анализа, которые помогают предотвращать ошибки до выхода ПО в продакшн.
if (correct_Login == 1 && correct_Password == 1)
struct android_app *
- это возвращаемый функцией тип;(void)
после имени означает, что функция без аргументов, современные компиляторы позволяют писать просто пустые скобки ()
;// описание структуры android_app должно быть выше заголовка его использующего,
// иначе он будет невалидным. А вот описание полей (реализация) может быть и ниже
struct android_app;
struct android_app* GetAndroidApp();
комментарии говорится что я могу добавить его в HeaderЭто значит, что данные сигнатуры можно вынести в заголовочный файл (тот что с расширением .h), это позволит вставить его во множество исходников через директиву препроцессора #include
uint8_t main_buffer[512];
uint8_t cryptor;
cryptor = readCryptor();
if(cryptor != 0)
{
// вычислим ближайшую к cryptor степень 2 снизу
uint8_t pow2 = 0x80;
while((pow2 & cryptor) == 0) pow2 >>= 1;
while(readNext512Bytes(main_buffer))
{
// один большой цикл заменим на 2 маленьких
// k будет считать отрезки
// i будет считать позицию внутри отрезка
for(uint16_t k = 0; k < 512; k += pow2 << 1) for(uint8_t i = 0; i < pow2; i++)
{
uint8_t tmp;
tmp = main_buffer[i + k];
main_buffer[i + k] = main_buffer[(i + k) ^ cryptor];
main_buffer[(i + k) ^ cryptor] = tmp;
}
}
}
typedef struct {
char* buffer;
size_t capacity;
size_t length;
} string;
и дальше бы работал с ней, заодно разбив код на небольшие функции. Но преподы программирования народ от разработки далекий, и кроме своих лабараторок в программировании не бум-бум в большинстве своем. А в комментах к вопросу было про то, что структуры нельзя...#include <stdio.h>
#include <stdlib.h>
int main() {
size_t capacity = 1 << 4; // на старте буду выделять 16 байт
size_t length = 0; // строка пока пустая, поэтому 0
char* str = malloc(capacity);
if (str == NULL) { // с памятью в куче может и облом быть
return 1; // вернем код ошибки
}
printf("Write string and press ENTER to continue:\n");
while(1) { // читать символы будем до скончания веков ))
char c = getchar();
if(c == 13 || c == 10) break; // ну или пока юзер не нажмет ентер
length++; // увеличим счетчик символов
if(length > capacity) { // если новый символ не влазит в выделеную память
capacity <<= 1; // то удвоим ее
char* new_str = realloc(str, capacity); // и перевыделим
if (new_str == NULL) { // опять чекнем, вдруг облом
free(str); // ресурсы надо освобождать
return 1; // вернем код ошибки
}
str = new_str; // в str теперь невалидный указатель, можем его заменить
}
str[length - 1] = c; // запомним считанный символ
}
// Здесь решение с вставкой подстроки
// с учетом того, что у нас строка str
// с длиной length и выделеной памятью под нее capacity
free(str); // ресурсы надо освобождать
return 0; // вернем код успешного завершения
}
с самой вставкой подстроки надеюсь справитесь? int* matr = (int*)malloc(n * m * sizeof(int));
а к конкретной ячейке обращаться как matr[i * n + j]void free_matr(int m, int** matr) {
for(int i = 0; i < m; i++) {
free(matr[i]);
}
free(matr);
}
arr[i]
чем *(arr + i)
int arr[10];
компилятор понимает, что тут нужно выделить sizeof(int) * 10 памяти на стеке